refactor(store,tools): migrate IDs from UUID to bigserial int64
Some checks failed
CI / build-and-test (push) Failing after -31m12s
Some checks failed
CI / build-and-test (push) Failing after -31m12s
All internal entity lookups now use bigserial primary keys (int64) while GUIDs are retained for external/public identification. Updated store functions (TouchProject, UpdateThoughtMetadata, AddThoughtAttachment) to query by id instead of guid, added GetThoughtByID, changed semanticSearch and all tool helpers to use *int64 project IDs, and updated retry/backfill workers to use int64 thought IDs throughout.
This commit is contained in:
@@ -9,10 +9,11 @@ import (
|
|||||||
|
|
||||||
type ModelPublicAgentGuardrails struct {
|
type ModelPublicAgentGuardrails struct {
|
||||||
bun.BaseModel `bun:"table:public.agent_guardrails,alias:agent_guardrails"`
|
bun.BaseModel `bun:"table:public.agent_guardrails,alias:agent_guardrails"`
|
||||||
ID resolvespec_common.SqlUUID `bun:"id,type:uuid,pk,default:gen_random_uuid()," json:"id"`
|
ID resolvespec_common.SqlInt64 `bun:"id,type:bigserial,pk,autoincrement," json:"id"`
|
||||||
Content resolvespec_common.SqlString `bun:"content,type:text,notnull," json:"content"`
|
Content resolvespec_common.SqlString `bun:"content,type:text,notnull," json:"content"`
|
||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
||||||
Description resolvespec_common.SqlString `bun:"description,type:text,default:'',notnull," json:"description"`
|
Description resolvespec_common.SqlString `bun:"description,type:text,default:'',notnull," json:"description"`
|
||||||
|
GUID resolvespec_common.SqlUUID `bun:"guid,type:uuid,default:gen_random_uuid(),notnull," json:"guid"`
|
||||||
Name resolvespec_common.SqlString `bun:"name,type:text,notnull," json:"name"`
|
Name resolvespec_common.SqlString `bun:"name,type:text,notnull," json:"name"`
|
||||||
Severity resolvespec_common.SqlString `bun:"severity,type:text,default:'medium',notnull," json:"severity"`
|
Severity resolvespec_common.SqlString `bun:"severity,type:text,default:'medium',notnull," json:"severity"`
|
||||||
Tags resolvespec_common.SqlString `bun:"tags,type:text,nullzero," json:"tags"`
|
Tags resolvespec_common.SqlString `bun:"tags,type:text,nullzero," json:"tags"`
|
||||||
|
|||||||
@@ -9,10 +9,11 @@ import (
|
|||||||
|
|
||||||
type ModelPublicAgentSkills struct {
|
type ModelPublicAgentSkills struct {
|
||||||
bun.BaseModel `bun:"table:public.agent_skills,alias:agent_skills"`
|
bun.BaseModel `bun:"table:public.agent_skills,alias:agent_skills"`
|
||||||
ID resolvespec_common.SqlUUID `bun:"id,type:uuid,pk,default:gen_random_uuid()," json:"id"`
|
ID resolvespec_common.SqlInt64 `bun:"id,type:bigserial,pk,autoincrement," json:"id"`
|
||||||
Content resolvespec_common.SqlString `bun:"content,type:text,notnull," json:"content"`
|
Content resolvespec_common.SqlString `bun:"content,type:text,notnull," json:"content"`
|
||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
||||||
Description resolvespec_common.SqlString `bun:"description,type:text,default:'',notnull," json:"description"`
|
Description resolvespec_common.SqlString `bun:"description,type:text,default:'',notnull," json:"description"`
|
||||||
|
GUID resolvespec_common.SqlUUID `bun:"guid,type:uuid,default:gen_random_uuid(),notnull," json:"guid"`
|
||||||
Name resolvespec_common.SqlString `bun:"name,type:text,notnull," json:"name"`
|
Name resolvespec_common.SqlString `bun:"name,type:text,notnull," json:"name"`
|
||||||
Tags resolvespec_common.SqlString `bun:"tags,type:text,nullzero," json:"tags"`
|
Tags resolvespec_common.SqlString `bun:"tags,type:text,nullzero," json:"tags"`
|
||||||
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),notnull," json:"updated_at"`
|
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),notnull," json:"updated_at"`
|
||||||
|
|||||||
@@ -9,18 +9,19 @@ import (
|
|||||||
|
|
||||||
type ModelPublicChatHistories struct {
|
type ModelPublicChatHistories struct {
|
||||||
bun.BaseModel `bun:"table:public.chat_histories,alias:chat_histories"`
|
bun.BaseModel `bun:"table:public.chat_histories,alias:chat_histories"`
|
||||||
ID resolvespec_common.SqlUUID `bun:"id,type:uuid,pk,default:gen_random_uuid()," json:"id"`
|
ID resolvespec_common.SqlInt64 `bun:"id,type:bigserial,pk,autoincrement," json:"id"`
|
||||||
AgentID resolvespec_common.SqlString `bun:"agent_id,type:text,nullzero," json:"agent_id"`
|
AgentID resolvespec_common.SqlString `bun:"agent_id,type:text,nullzero," json:"agent_id"`
|
||||||
Channel resolvespec_common.SqlString `bun:"channel,type:text,nullzero," json:"channel"`
|
Channel resolvespec_common.SqlString `bun:"channel,type:text,nullzero," json:"channel"`
|
||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
||||||
|
GUID resolvespec_common.SqlUUID `bun:"guid,type:uuid,default:gen_random_uuid(),notnull," json:"guid"`
|
||||||
Messages resolvespec_common.SqlJSONB `bun:"messages,type:jsonb,default:'[',notnull," json:"messages"`
|
Messages resolvespec_common.SqlJSONB `bun:"messages,type:jsonb,default:'[',notnull," json:"messages"`
|
||||||
Metadata resolvespec_common.SqlJSONB `bun:"metadata,type:jsonb,default:'{}',notnull," json:"metadata"`
|
Metadata resolvespec_common.SqlJSONB `bun:"metadata,type:jsonb,default:'{}',notnull," json:"metadata"`
|
||||||
ProjectID resolvespec_common.SqlUUID `bun:"project_id,type:uuid,nullzero," json:"project_id"`
|
ProjectID resolvespec_common.SqlInt64 `bun:"project_id,type:bigint,nullzero," json:"project_id"`
|
||||||
SessionID resolvespec_common.SqlString `bun:"session_id,type:text,notnull," json:"session_id"`
|
SessionID resolvespec_common.SqlString `bun:"session_id,type:text,notnull," json:"session_id"`
|
||||||
Summary resolvespec_common.SqlString `bun:"summary,type:text,nullzero," json:"summary"`
|
Summary resolvespec_common.SqlString `bun:"summary,type:text,nullzero," json:"summary"`
|
||||||
Title resolvespec_common.SqlString `bun:"title,type:text,nullzero," json:"title"`
|
Title resolvespec_common.SqlString `bun:"title,type:text,nullzero," json:"title"`
|
||||||
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),notnull," json:"updated_at"`
|
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),notnull," json:"updated_at"`
|
||||||
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=guid" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=id" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName returns the table name for ModelPublicChatHistories
|
// TableName returns the table name for ModelPublicChatHistories
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ type ModelPublicEmbeddings struct {
|
|||||||
Embedding resolvespec_common.SqlString `bun:"embedding,type:vector,notnull," json:"embedding"`
|
Embedding resolvespec_common.SqlString `bun:"embedding,type:vector,notnull," json:"embedding"`
|
||||||
GUID resolvespec_common.SqlUUID `bun:"guid,type:uuid,default:gen_random_uuid(),notnull," json:"guid"`
|
GUID resolvespec_common.SqlUUID `bun:"guid,type:uuid,default:gen_random_uuid(),notnull," json:"guid"`
|
||||||
Model resolvespec_common.SqlString `bun:"model,type:text,notnull,unique:uidx_embeddings_thought_id_model," json:"model"`
|
Model resolvespec_common.SqlString `bun:"model,type:text,notnull,unique:uidx_embeddings_thought_id_model," json:"model"`
|
||||||
ThoughtID resolvespec_common.SqlUUID `bun:"thought_id,type:uuid,notnull,unique:uidx_embeddings_thought_id_model," json:"thought_id"`
|
ThoughtID int64 `bun:"thought_id,type:bigint,notnull,unique:uidx_embeddings_thought_id_model," json:"thought_id"`
|
||||||
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),nullzero," json:"updated_at"`
|
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),nullzero," json:"updated_at"`
|
||||||
RelThoughtID *ModelPublicThoughts `bun:"rel:has-one,join:thought_id=guid" json:"relthoughtid,omitempty"` // Has one ModelPublicThoughts
|
RelThoughtID *ModelPublicThoughts `bun:"rel:has-one,join:thought_id=id" json:"relthoughtid,omitempty"` // Has one ModelPublicThoughts
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName returns the table name for ModelPublicEmbeddings
|
// TableName returns the table name for ModelPublicEmbeddings
|
||||||
|
|||||||
@@ -9,31 +9,32 @@ import (
|
|||||||
|
|
||||||
type ModelPublicLearnings struct {
|
type ModelPublicLearnings struct {
|
||||||
bun.BaseModel `bun:"table:public.learnings,alias:learnings"`
|
bun.BaseModel `bun:"table:public.learnings,alias:learnings"`
|
||||||
ID resolvespec_common.SqlUUID `bun:"id,type:uuid,pk,default:gen_random_uuid()," json:"id"`
|
ID resolvespec_common.SqlInt64 `bun:"id,type:bigserial,pk,autoincrement," json:"id"`
|
||||||
ActionRequired bool `bun:"action_required,type:boolean,default:false,notnull," json:"action_required"`
|
ActionRequired bool `bun:"action_required,type:boolean,default:false,notnull," json:"action_required"`
|
||||||
Area resolvespec_common.SqlString `bun:"area,type:text,default:'other',notnull," json:"area"`
|
Area resolvespec_common.SqlString `bun:"area,type:text,default:'other',notnull," json:"area"`
|
||||||
Category resolvespec_common.SqlString `bun:"category,type:text,default:'insight',notnull," json:"category"`
|
Category resolvespec_common.SqlString `bun:"category,type:text,default:'insight',notnull," json:"category"`
|
||||||
Confidence resolvespec_common.SqlString `bun:"confidence,type:text,default:'hypothesis',notnull," json:"confidence"`
|
Confidence resolvespec_common.SqlString `bun:"confidence,type:text,default:'hypothesis',notnull," json:"confidence"`
|
||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
||||||
Details resolvespec_common.SqlString `bun:"details,type:text,default:'',notnull," json:"details"`
|
Details resolvespec_common.SqlString `bun:"details,type:text,default:'',notnull," json:"details"`
|
||||||
DuplicateOfLearningID resolvespec_common.SqlUUID `bun:"duplicate_of_learning_id,type:uuid,nullzero," json:"duplicate_of_learning_id"`
|
DuplicateOfLearningID resolvespec_common.SqlInt64 `bun:"duplicate_of_learning_id,type:bigint,nullzero," json:"duplicate_of_learning_id"`
|
||||||
|
GUID resolvespec_common.SqlUUID `bun:"guid,type:uuid,default:gen_random_uuid(),notnull," json:"guid"`
|
||||||
Priority resolvespec_common.SqlString `bun:"priority,type:text,default:'medium',notnull," json:"priority"`
|
Priority resolvespec_common.SqlString `bun:"priority,type:text,default:'medium',notnull," json:"priority"`
|
||||||
ProjectID resolvespec_common.SqlUUID `bun:"project_id,type:uuid,nullzero," json:"project_id"`
|
ProjectID resolvespec_common.SqlInt64 `bun:"project_id,type:bigint,nullzero," json:"project_id"`
|
||||||
RelatedSkillID resolvespec_common.SqlUUID `bun:"related_skill_id,type:uuid,nullzero," json:"related_skill_id"`
|
RelatedSkillID resolvespec_common.SqlInt64 `bun:"related_skill_id,type:bigint,nullzero," json:"related_skill_id"`
|
||||||
RelatedThoughtID resolvespec_common.SqlUUID `bun:"related_thought_id,type:uuid,nullzero," json:"related_thought_id"`
|
RelatedThoughtID resolvespec_common.SqlInt64 `bun:"related_thought_id,type:bigint,nullzero," json:"related_thought_id"`
|
||||||
ReviewedAt resolvespec_common.SqlTimeStamp `bun:"reviewed_at,type:timestamptz,nullzero," json:"reviewed_at"`
|
ReviewedAt resolvespec_common.SqlTimeStamp `bun:"reviewed_at,type:timestamptz,nullzero," json:"reviewed_at"`
|
||||||
ReviewedBy resolvespec_common.SqlString `bun:"reviewed_by,type:text,nullzero," json:"reviewed_by"`
|
ReviewedBy resolvespec_common.SqlString `bun:"reviewed_by,type:text,nullzero," json:"reviewed_by"`
|
||||||
SourceRef resolvespec_common.SqlString `bun:"source_ref,type:text,nullzero," json:"source_ref"`
|
SourceRef resolvespec_common.SqlString `bun:"source_ref,type:text,nullzero," json:"source_ref"`
|
||||||
SourceType resolvespec_common.SqlString `bun:"source_type,type:text,nullzero," json:"source_type"`
|
SourceType resolvespec_common.SqlString `bun:"source_type,type:text,nullzero," json:"source_type"`
|
||||||
Status resolvespec_common.SqlString `bun:"status,type:text,default:'pending',notnull," json:"status"`
|
Status resolvespec_common.SqlString `bun:"status,type:text,default:'pending',notnull," json:"status"`
|
||||||
Summary resolvespec_common.SqlString `bun:"summary,type:text,notnull," json:"summary"`
|
Summary resolvespec_common.SqlString `bun:"summary,type:text,notnull," json:"summary"`
|
||||||
SupersedesLearningID resolvespec_common.SqlUUID `bun:"supersedes_learning_id,type:uuid,nullzero," json:"supersedes_learning_id"`
|
SupersedesLearningID resolvespec_common.SqlInt64 `bun:"supersedes_learning_id,type:bigint,nullzero," json:"supersedes_learning_id"`
|
||||||
Tags resolvespec_common.SqlString `bun:"tags,type:text,nullzero," json:"tags"`
|
Tags resolvespec_common.SqlString `bun:"tags,type:text,nullzero," json:"tags"`
|
||||||
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),notnull," json:"updated_at"`
|
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),notnull," json:"updated_at"`
|
||||||
RelDuplicateOfLearningID *ModelPublicLearnings `bun:"rel:has-one,join:duplicate_of_learning_id=id" json:"relduplicateoflearningid,omitempty"` // Has one ModelPublicLearnings
|
RelDuplicateOfLearningID *ModelPublicLearnings `bun:"rel:has-one,join:duplicate_of_learning_id=id" json:"relduplicateoflearningid,omitempty"` // Has one ModelPublicLearnings
|
||||||
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=guid" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=id" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
||||||
RelRelatedSkillID *ModelPublicAgentSkills `bun:"rel:has-one,join:related_skill_id=id" json:"relrelatedskillid,omitempty"` // Has one ModelPublicAgentSkills
|
RelRelatedSkillID *ModelPublicAgentSkills `bun:"rel:has-one,join:related_skill_id=id" json:"relrelatedskillid,omitempty"` // Has one ModelPublicAgentSkills
|
||||||
RelRelatedThoughtID *ModelPublicThoughts `bun:"rel:has-one,join:related_thought_id=guid" json:"relrelatedthoughtid,omitempty"` // Has one ModelPublicThoughts
|
RelRelatedThoughtID *ModelPublicThoughts `bun:"rel:has-one,join:related_thought_id=id" json:"relrelatedthoughtid,omitempty"` // Has one ModelPublicThoughts
|
||||||
RelSupersedesLearningID *ModelPublicLearnings `bun:"rel:has-one,join:supersedes_learning_id=id" json:"relsupersedeslearningid,omitempty"` // Has one ModelPublicLearnings
|
RelSupersedesLearningID *ModelPublicLearnings `bun:"rel:has-one,join:supersedes_learning_id=id" json:"relsupersedeslearningid,omitempty"` // Has one ModelPublicLearnings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ import (
|
|||||||
|
|
||||||
type ModelPublicPlanDependencies struct {
|
type ModelPublicPlanDependencies struct {
|
||||||
bun.BaseModel `bun:"table:public.plan_dependencies,alias:plan_dependencies"`
|
bun.BaseModel `bun:"table:public.plan_dependencies,alias:plan_dependencies"`
|
||||||
ID resolvespec_common.SqlInt32 `bun:"id,type:serial,pk,autoincrement," json:"id"`
|
ID resolvespec_common.SqlInt64 `bun:"id,type:bigserial,pk,autoincrement," json:"id"`
|
||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
||||||
DependsOnPlanID resolvespec_common.SqlUUID `bun:"depends_on_plan_id,type:uuid,notnull,unique:uidx_plan_dependencies_plan_id_depends_on_plan_id," json:"depends_on_plan_id"`
|
DependsOnPlanID int64 `bun:"depends_on_plan_id,type:bigint,notnull,unique:uidx_plan_dependencies_plan_id_depends_on_plan_id," json:"depends_on_plan_id"`
|
||||||
PlanID resolvespec_common.SqlUUID `bun:"plan_id,type:uuid,notnull,unique:uidx_plan_dependencies_plan_id_depends_on_plan_id," json:"plan_id"`
|
PlanID int64 `bun:"plan_id,type:bigint,notnull,unique:uidx_plan_dependencies_plan_id_depends_on_plan_id," json:"plan_id"`
|
||||||
RelDependsOnPlanID *ModelPublicPlans `bun:"rel:has-one,join:depends_on_plan_id=id" json:"reldependsonplanid,omitempty"` // Has one ModelPublicPlans
|
RelDependsOnPlanID *ModelPublicPlans `bun:"rel:has-one,join:depends_on_plan_id=id" json:"reldependsonplanid,omitempty"` // Has one ModelPublicPlans
|
||||||
RelPlanID *ModelPublicPlans `bun:"rel:has-one,join:plan_id=id" json:"relplanid,omitempty"` // Has one ModelPublicPlans
|
RelPlanID *ModelPublicPlans `bun:"rel:has-one,join:plan_id=id" json:"relplanid,omitempty"` // Has one ModelPublicPlans
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ import (
|
|||||||
|
|
||||||
type ModelPublicPlanGuardrails struct {
|
type ModelPublicPlanGuardrails struct {
|
||||||
bun.BaseModel `bun:"table:public.plan_guardrails,alias:plan_guardrails"`
|
bun.BaseModel `bun:"table:public.plan_guardrails,alias:plan_guardrails"`
|
||||||
ID resolvespec_common.SqlInt32 `bun:"id,type:serial,pk,autoincrement," json:"id"`
|
ID resolvespec_common.SqlInt64 `bun:"id,type:bigserial,pk,autoincrement," json:"id"`
|
||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
||||||
GuardrailID resolvespec_common.SqlUUID `bun:"guardrail_id,type:uuid,notnull,unique:uidx_plan_guardrails_plan_id_guardrail_id," json:"guardrail_id"`
|
GuardrailID int64 `bun:"guardrail_id,type:bigint,notnull,unique:uidx_plan_guardrails_plan_id_guardrail_id," json:"guardrail_id"`
|
||||||
PlanID resolvespec_common.SqlUUID `bun:"plan_id,type:uuid,notnull,unique:uidx_plan_guardrails_plan_id_guardrail_id," json:"plan_id"`
|
PlanID int64 `bun:"plan_id,type:bigint,notnull,unique:uidx_plan_guardrails_plan_id_guardrail_id," json:"plan_id"`
|
||||||
RelGuardrailID *ModelPublicAgentGuardrails `bun:"rel:has-one,join:guardrail_id=id" json:"relguardrailid,omitempty"` // Has one ModelPublicAgentGuardrails
|
RelGuardrailID *ModelPublicAgentGuardrails `bun:"rel:has-one,join:guardrail_id=id" json:"relguardrailid,omitempty"` // Has one ModelPublicAgentGuardrails
|
||||||
RelPlanID *ModelPublicPlans `bun:"rel:has-one,join:plan_id=id" json:"relplanid,omitempty"` // Has one ModelPublicPlans
|
RelPlanID *ModelPublicPlans `bun:"rel:has-one,join:plan_id=id" json:"relplanid,omitempty"` // Has one ModelPublicPlans
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ import (
|
|||||||
|
|
||||||
type ModelPublicPlanRelatedPlans struct {
|
type ModelPublicPlanRelatedPlans struct {
|
||||||
bun.BaseModel `bun:"table:public.plan_related_plans,alias:plan_related_plans"`
|
bun.BaseModel `bun:"table:public.plan_related_plans,alias:plan_related_plans"`
|
||||||
ID resolvespec_common.SqlInt32 `bun:"id,type:serial,pk,autoincrement," json:"id"`
|
ID resolvespec_common.SqlInt64 `bun:"id,type:bigserial,pk,autoincrement," json:"id"`
|
||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
||||||
PlanAID resolvespec_common.SqlUUID `bun:"plan_a_id,type:uuid,notnull,unique:uidx_plan_related_plans_plan_a_id_plan_b_id," json:"plan_a_id"`
|
PlanAID int64 `bun:"plan_a_id,type:bigint,notnull,unique:uidx_plan_related_plans_plan_a_id_plan_b_id," json:"plan_a_id"`
|
||||||
PlanBID resolvespec_common.SqlUUID `bun:"plan_b_id,type:uuid,notnull,unique:uidx_plan_related_plans_plan_a_id_plan_b_id," json:"plan_b_id"`
|
PlanBID int64 `bun:"plan_b_id,type:bigint,notnull,unique:uidx_plan_related_plans_plan_a_id_plan_b_id," json:"plan_b_id"`
|
||||||
RelPlanAID *ModelPublicPlans `bun:"rel:has-one,join:plan_a_id=id" json:"relplanaid,omitempty"` // Has one ModelPublicPlans
|
RelPlanAID *ModelPublicPlans `bun:"rel:has-one,join:plan_a_id=id" json:"relplanaid,omitempty"` // Has one ModelPublicPlans
|
||||||
RelPlanBID *ModelPublicPlans `bun:"rel:has-one,join:plan_b_id=id" json:"relplanbid,omitempty"` // Has one ModelPublicPlans
|
RelPlanBID *ModelPublicPlans `bun:"rel:has-one,join:plan_b_id=id" json:"relplanbid,omitempty"` // Has one ModelPublicPlans
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ import (
|
|||||||
|
|
||||||
type ModelPublicPlanSkills struct {
|
type ModelPublicPlanSkills struct {
|
||||||
bun.BaseModel `bun:"table:public.plan_skills,alias:plan_skills"`
|
bun.BaseModel `bun:"table:public.plan_skills,alias:plan_skills"`
|
||||||
ID resolvespec_common.SqlInt32 `bun:"id,type:serial,pk,autoincrement," json:"id"`
|
ID resolvespec_common.SqlInt64 `bun:"id,type:bigserial,pk,autoincrement," json:"id"`
|
||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
||||||
PlanID resolvespec_common.SqlUUID `bun:"plan_id,type:uuid,notnull,unique:uidx_plan_skills_plan_id_skill_id," json:"plan_id"`
|
PlanID int64 `bun:"plan_id,type:bigint,notnull,unique:uidx_plan_skills_plan_id_skill_id," json:"plan_id"`
|
||||||
SkillID resolvespec_common.SqlUUID `bun:"skill_id,type:uuid,notnull,unique:uidx_plan_skills_plan_id_skill_id," json:"skill_id"`
|
SkillID int64 `bun:"skill_id,type:bigint,notnull,unique:uidx_plan_skills_plan_id_skill_id," json:"skill_id"`
|
||||||
RelPlanID *ModelPublicPlans `bun:"rel:has-one,join:plan_id=id" json:"relplanid,omitempty"` // Has one ModelPublicPlans
|
RelPlanID *ModelPublicPlans `bun:"rel:has-one,join:plan_id=id" json:"relplanid,omitempty"` // Has one ModelPublicPlans
|
||||||
RelSkillID *ModelPublicAgentSkills `bun:"rel:has-one,join:skill_id=id" json:"relskillid,omitempty"` // Has one ModelPublicAgentSkills
|
RelSkillID *ModelPublicAgentSkills `bun:"rel:has-one,join:skill_id=id" json:"relskillid,omitempty"` // Has one ModelPublicAgentSkills
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,22 +9,23 @@ import (
|
|||||||
|
|
||||||
type ModelPublicPlans struct {
|
type ModelPublicPlans struct {
|
||||||
bun.BaseModel `bun:"table:public.plans,alias:plans"`
|
bun.BaseModel `bun:"table:public.plans,alias:plans"`
|
||||||
ID resolvespec_common.SqlUUID `bun:"id,type:uuid,pk,default:gen_random_uuid()," json:"id"`
|
ID resolvespec_common.SqlInt64 `bun:"id,type:bigserial,pk,autoincrement," json:"id"`
|
||||||
CompletedAt resolvespec_common.SqlTimeStamp `bun:"completed_at,type:timestamptz,nullzero," json:"completed_at"`
|
CompletedAt resolvespec_common.SqlTimeStamp `bun:"completed_at,type:timestamptz,nullzero," json:"completed_at"`
|
||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
||||||
Description resolvespec_common.SqlString `bun:"description,type:text,default:'',notnull," json:"description"`
|
Description resolvespec_common.SqlString `bun:"description,type:text,default:'',notnull," json:"description"`
|
||||||
DueDate resolvespec_common.SqlTimeStamp `bun:"due_date,type:timestamptz,nullzero," json:"due_date"`
|
DueDate resolvespec_common.SqlTimeStamp `bun:"due_date,type:timestamptz,nullzero," json:"due_date"`
|
||||||
|
GUID resolvespec_common.SqlUUID `bun:"guid,type:uuid,default:gen_random_uuid(),notnull," json:"guid"`
|
||||||
LastReviewedAt resolvespec_common.SqlTimeStamp `bun:"last_reviewed_at,type:timestamptz,nullzero," json:"last_reviewed_at"`
|
LastReviewedAt resolvespec_common.SqlTimeStamp `bun:"last_reviewed_at,type:timestamptz,nullzero," json:"last_reviewed_at"`
|
||||||
Owner resolvespec_common.SqlString `bun:"owner,type:text,nullzero," json:"owner"`
|
Owner resolvespec_common.SqlString `bun:"owner,type:text,nullzero," json:"owner"`
|
||||||
Priority resolvespec_common.SqlString `bun:"priority,type:text,default:'medium',notnull," json:"priority"` // low, medium, high, critical
|
Priority resolvespec_common.SqlString `bun:"priority,type:text,default:'medium',notnull," json:"priority"` // low, medium, high, critical
|
||||||
ProjectID resolvespec_common.SqlUUID `bun:"project_id,type:uuid,nullzero," json:"project_id"`
|
ProjectID resolvespec_common.SqlInt64 `bun:"project_id,type:bigint,nullzero," json:"project_id"`
|
||||||
ReviewedBy resolvespec_common.SqlString `bun:"reviewed_by,type:text,nullzero," json:"reviewed_by"`
|
ReviewedBy resolvespec_common.SqlString `bun:"reviewed_by,type:text,nullzero," json:"reviewed_by"`
|
||||||
Status resolvespec_common.SqlString `bun:"status,type:text,default:'draft',notnull," json:"status"` // draft, active, blocked, completed, cancelled, superseded
|
Status resolvespec_common.SqlString `bun:"status,type:text,default:'draft',notnull," json:"status"` // draft, active, blocked, completed, cancelled, superseded
|
||||||
SupersedesPlanID resolvespec_common.SqlUUID `bun:"supersedes_plan_id,type:uuid,nullzero," json:"supersedes_plan_id"`
|
SupersedesPlanID resolvespec_common.SqlInt64 `bun:"supersedes_plan_id,type:bigint,nullzero," json:"supersedes_plan_id"`
|
||||||
Tags resolvespec_common.SqlString `bun:"tags,type:text,nullzero," json:"tags"`
|
Tags resolvespec_common.SqlString `bun:"tags,type:text,nullzero," json:"tags"`
|
||||||
Title resolvespec_common.SqlString `bun:"title,type:text,notnull," json:"title"`
|
Title resolvespec_common.SqlString `bun:"title,type:text,notnull," json:"title"`
|
||||||
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),notnull," json:"updated_at"`
|
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),notnull," json:"updated_at"`
|
||||||
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=guid" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=id" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
||||||
RelSupersedesPlanID *ModelPublicPlans `bun:"rel:has-one,join:supersedes_plan_id=id" json:"relsupersedesplanid,omitempty"` // Has one ModelPublicPlans
|
RelSupersedesPlanID *ModelPublicPlans `bun:"rel:has-one,join:supersedes_plan_id=id" json:"relsupersedesplanid,omitempty"` // Has one ModelPublicPlans
|
||||||
RelDependsOnPlanIDPublicPlanDependencies []*ModelPublicPlanDependencies `bun:"rel:has-many,join:id=depends_on_plan_id" json:"reldependsonplanidpublicplandependencies,omitempty"` // Has many ModelPublicPlanDependencies
|
RelDependsOnPlanIDPublicPlanDependencies []*ModelPublicPlanDependencies `bun:"rel:has-many,join:id=depends_on_plan_id" json:"reldependsonplanidpublicplandependencies,omitempty"` // Has many ModelPublicPlanDependencies
|
||||||
RelPlanIDPublicPlanDependencies []*ModelPublicPlanDependencies `bun:"rel:has-many,join:id=plan_id" json:"relplanidpublicplandependencies,omitempty"` // Has many ModelPublicPlanDependencies
|
RelPlanIDPublicPlanDependencies []*ModelPublicPlanDependencies `bun:"rel:has-many,join:id=plan_id" json:"relplanidpublicplandependencies,omitempty"` // Has many ModelPublicPlanDependencies
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import (
|
|||||||
|
|
||||||
type ModelPublicProjectGuardrails struct {
|
type ModelPublicProjectGuardrails struct {
|
||||||
bun.BaseModel `bun:"table:public.project_guardrails,alias:project_guardrails"`
|
bun.BaseModel `bun:"table:public.project_guardrails,alias:project_guardrails"`
|
||||||
ID resolvespec_common.SqlInt32 `bun:"id,type:serial,pk,autoincrement," json:"id"`
|
ID resolvespec_common.SqlInt64 `bun:"id,type:bigserial,pk,autoincrement," json:"id"`
|
||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
||||||
GuardrailID resolvespec_common.SqlUUID `bun:"guardrail_id,type:uuid,notnull," json:"guardrail_id"`
|
GuardrailID int64 `bun:"guardrail_id,type:bigint,notnull," json:"guardrail_id"`
|
||||||
ProjectID resolvespec_common.SqlUUID `bun:"project_id,type:uuid,notnull," json:"project_id"`
|
ProjectID int64 `bun:"project_id,type:bigint,notnull," json:"project_id"`
|
||||||
RelGuardrailID *ModelPublicAgentGuardrails `bun:"rel:has-one,join:guardrail_id=id" json:"relguardrailid,omitempty"` // Has one ModelPublicAgentGuardrails
|
RelGuardrailID *ModelPublicAgentGuardrails `bun:"rel:has-one,join:guardrail_id=id" json:"relguardrailid,omitempty"` // Has one ModelPublicAgentGuardrails
|
||||||
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=guid" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=id" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName returns the table name for ModelPublicProjectGuardrails
|
// TableName returns the table name for ModelPublicProjectGuardrails
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import (
|
|||||||
|
|
||||||
type ModelPublicProjectSkills struct {
|
type ModelPublicProjectSkills struct {
|
||||||
bun.BaseModel `bun:"table:public.project_skills,alias:project_skills"`
|
bun.BaseModel `bun:"table:public.project_skills,alias:project_skills"`
|
||||||
ID resolvespec_common.SqlInt32 `bun:"id,type:serial,pk,autoincrement," json:"id"`
|
ID resolvespec_common.SqlInt64 `bun:"id,type:bigserial,pk,autoincrement," json:"id"`
|
||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
||||||
ProjectID resolvespec_common.SqlUUID `bun:"project_id,type:uuid,notnull," json:"project_id"`
|
ProjectID int64 `bun:"project_id,type:bigint,notnull," json:"project_id"`
|
||||||
SkillID resolvespec_common.SqlUUID `bun:"skill_id,type:uuid,notnull," json:"skill_id"`
|
SkillID int64 `bun:"skill_id,type:bigint,notnull," json:"skill_id"`
|
||||||
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=guid" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=id" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
||||||
RelSkillID *ModelPublicAgentSkills `bun:"rel:has-one,join:skill_id=id" json:"relskillid,omitempty"` // Has one ModelPublicAgentSkills
|
RelSkillID *ModelPublicAgentSkills `bun:"rel:has-one,join:skill_id=id" json:"relskillid,omitempty"` // Has one ModelPublicAgentSkills
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName returns the table name for ModelPublicProjectSkills
|
// TableName returns the table name for ModelPublicProjectSkills
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ type ModelPublicProjects struct {
|
|||||||
LastActiveAt resolvespec_common.SqlTimeStamp `bun:"last_active_at,type:timestamptz,default:now(),nullzero," json:"last_active_at"`
|
LastActiveAt resolvespec_common.SqlTimeStamp `bun:"last_active_at,type:timestamptz,default:now(),nullzero," json:"last_active_at"`
|
||||||
Name resolvespec_common.SqlString `bun:"name,type:text,notnull," json:"name"`
|
Name resolvespec_common.SqlString `bun:"name,type:text,notnull," json:"name"`
|
||||||
ThoughtCount resolvespec_common.SqlInt64 `bun:"thought_count,scanonly" json:"thought_count"`
|
ThoughtCount resolvespec_common.SqlInt64 `bun:"thought_count,scanonly" json:"thought_count"`
|
||||||
RelProjectIDPublicThoughts []*ModelPublicThoughts `bun:"rel:has-many,join:guid=project_id" json:"relprojectidpublicthoughts,omitempty"` // Has many ModelPublicThoughts
|
RelProjectIDPublicThoughts []*ModelPublicThoughts `bun:"rel:has-many,join:id=project_id" json:"relprojectidpublicthoughts,omitempty"` // Has many ModelPublicThoughts
|
||||||
RelProjectIDPublicStoredFiles []*ModelPublicStoredFiles `bun:"rel:has-many,join:guid=project_id" json:"relprojectidpublicstoredfiles,omitempty"` // Has many ModelPublicStoredFiles
|
RelProjectIDPublicStoredFiles []*ModelPublicStoredFiles `bun:"rel:has-many,join:id=project_id" json:"relprojectidpublicstoredfiles,omitempty"` // Has many ModelPublicStoredFiles
|
||||||
RelProjectIDPublicChatHistories []*ModelPublicChatHistories `bun:"rel:has-many,join:guid=project_id" json:"relprojectidpublicchathistories,omitempty"` // Has many ModelPublicChatHistories
|
RelProjectIDPublicChatHistories []*ModelPublicChatHistories `bun:"rel:has-many,join:id=project_id" json:"relprojectidpublicchathistories,omitempty"` // Has many ModelPublicChatHistories
|
||||||
RelProjectIDPublicLearnings []*ModelPublicLearnings `bun:"rel:has-many,join:guid=project_id" json:"relprojectidpubliclearnings,omitempty"` // Has many ModelPublicLearnings
|
RelProjectIDPublicLearnings []*ModelPublicLearnings `bun:"rel:has-many,join:id=project_id" json:"relprojectidpubliclearnings,omitempty"` // Has many ModelPublicLearnings
|
||||||
RelProjectIDPublicPlans []*ModelPublicPlans `bun:"rel:has-many,join:guid=project_id" json:"relprojectidpublicplans,omitempty"` // Has many ModelPublicPlans
|
RelProjectIDPublicPlans []*ModelPublicPlans `bun:"rel:has-many,join:id=project_id" json:"relprojectidpublicplans,omitempty"` // Has many ModelPublicPlans
|
||||||
RelProjectIDPublicProjectSkills []*ModelPublicProjectSkills `bun:"rel:has-many,join:guid=project_id" json:"relprojectidpublicprojectskills,omitempty"` // Has many ModelPublicProjectSkills
|
RelProjectIDPublicProjectSkills []*ModelPublicProjectSkills `bun:"rel:has-many,join:id=project_id" json:"relprojectidpublicprojectskills,omitempty"` // Has many ModelPublicProjectSkills
|
||||||
RelProjectIDPublicProjectGuardrails []*ModelPublicProjectGuardrails `bun:"rel:has-many,join:guid=project_id" json:"relprojectidpublicprojectguardrails,omitempty"` // Has many ModelPublicProjectGuardrails
|
RelProjectIDPublicProjectGuardrails []*ModelPublicProjectGuardrails `bun:"rel:has-many,join:id=project_id" json:"relprojectidpublicprojectguardrails,omitempty"` // Has many ModelPublicProjectGuardrails
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName returns the table name for ModelPublicProjects
|
// TableName returns the table name for ModelPublicProjects
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ type ModelPublicStoredFiles struct {
|
|||||||
Kind resolvespec_common.SqlString `bun:"kind,type:text,default:'file',notnull," json:"kind"`
|
Kind resolvespec_common.SqlString `bun:"kind,type:text,default:'file',notnull," json:"kind"`
|
||||||
MediaType resolvespec_common.SqlString `bun:"media_type,type:text,notnull," json:"media_type"`
|
MediaType resolvespec_common.SqlString `bun:"media_type,type:text,notnull," json:"media_type"`
|
||||||
Name resolvespec_common.SqlString `bun:"name,type:text,notnull," json:"name"`
|
Name resolvespec_common.SqlString `bun:"name,type:text,notnull," json:"name"`
|
||||||
ProjectID resolvespec_common.SqlUUID `bun:"project_id,type:uuid,nullzero," json:"project_id"`
|
ProjectID resolvespec_common.SqlInt64 `bun:"project_id,type:bigint,nullzero," json:"project_id"`
|
||||||
Sha256 resolvespec_common.SqlString `bun:"sha256,type:text,notnull," json:"sha256"`
|
Sha256 resolvespec_common.SqlString `bun:"sha256,type:text,notnull," json:"sha256"`
|
||||||
SizeBytes int64 `bun:"size_bytes,type:bigint,notnull," json:"size_bytes"`
|
SizeBytes int64 `bun:"size_bytes,type:bigint,notnull," json:"size_bytes"`
|
||||||
ThoughtID resolvespec_common.SqlUUID `bun:"thought_id,type:uuid,nullzero," json:"thought_id"`
|
ThoughtID resolvespec_common.SqlInt64 `bun:"thought_id,type:bigint,nullzero," json:"thought_id"`
|
||||||
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),notnull," json:"updated_at"`
|
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),notnull," json:"updated_at"`
|
||||||
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=guid" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=id" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
||||||
RelThoughtID *ModelPublicThoughts `bun:"rel:has-one,join:thought_id=guid" json:"relthoughtid,omitempty"` // Has one ModelPublicThoughts
|
RelThoughtID *ModelPublicThoughts `bun:"rel:has-one,join:thought_id=id" json:"relthoughtid,omitempty"` // Has one ModelPublicThoughts
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName returns the table name for ModelPublicStoredFiles
|
// TableName returns the table name for ModelPublicStoredFiles
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
type ModelPublicThoughtLinks struct {
|
type ModelPublicThoughtLinks struct {
|
||||||
bun.BaseModel `bun:"table:public.thought_links,alias:thought_links"`
|
bun.BaseModel `bun:"table:public.thought_links,alias:thought_links"`
|
||||||
ID resolvespec_common.SqlInt32 `bun:"id,type:serial,pk,autoincrement," json:"id"`
|
ID resolvespec_common.SqlInt64 `bun:"id,type:bigserial,pk,autoincrement," json:"id"`
|
||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),nullzero," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),nullzero," json:"created_at"`
|
||||||
FromID int64 `bun:"from_id,type:bigint,notnull," json:"from_id"`
|
FromID int64 `bun:"from_id,type:bigint,notnull," json:"from_id"`
|
||||||
Relation resolvespec_common.SqlString `bun:"relation,type:text,notnull," json:"relation"`
|
Relation resolvespec_common.SqlString `bun:"relation,type:text,notnull," json:"relation"`
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ type ModelPublicThoughts struct {
|
|||||||
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),nullzero," json:"created_at"`
|
CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),nullzero," json:"created_at"`
|
||||||
GUID resolvespec_common.SqlUUID `bun:"guid,type:uuid,default:gen_random_uuid(),notnull," json:"guid"`
|
GUID resolvespec_common.SqlUUID `bun:"guid,type:uuid,default:gen_random_uuid(),notnull," json:"guid"`
|
||||||
Metadata resolvespec_common.SqlJSONB `bun:"metadata,type:jsonb,default:'{}::jsonb',nullzero," json:"metadata"`
|
Metadata resolvespec_common.SqlJSONB `bun:"metadata,type:jsonb,default:'{}::jsonb',nullzero," json:"metadata"`
|
||||||
ProjectID resolvespec_common.SqlUUID `bun:"project_id,type:uuid,nullzero," json:"project_id"`
|
ProjectID resolvespec_common.SqlInt64 `bun:"project_id,type:bigint,nullzero," json:"project_id"`
|
||||||
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),nullzero," json:"updated_at"`
|
UpdatedAt resolvespec_common.SqlTimeStamp `bun:"updated_at,type:timestamptz,default:now(),nullzero," json:"updated_at"`
|
||||||
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=guid" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
RelProjectID *ModelPublicProjects `bun:"rel:has-one,join:project_id=id" json:"relprojectid,omitempty"` // Has one ModelPublicProjects
|
||||||
RelFromIDPublicThoughtLinks []*ModelPublicThoughtLinks `bun:"rel:has-many,join:id=from_id" json:"relfromidpublicthoughtlinks,omitempty"` // Has many ModelPublicThoughtLinks
|
RelFromIDPublicThoughtLinks []*ModelPublicThoughtLinks `bun:"rel:has-many,join:id=from_id" json:"relfromidpublicthoughtlinks,omitempty"` // Has many ModelPublicThoughtLinks
|
||||||
RelToIDPublicThoughtLinks []*ModelPublicThoughtLinks `bun:"rel:has-many,join:id=to_id" json:"reltoidpublicthoughtlinks,omitempty"` // Has many ModelPublicThoughtLinks
|
RelToIDPublicThoughtLinks []*ModelPublicThoughtLinks `bun:"rel:has-many,join:id=to_id" json:"reltoidpublicthoughtlinks,omitempty"` // Has many ModelPublicThoughtLinks
|
||||||
RelThoughtIDPublicEmbeddings []*ModelPublicEmbeddings `bun:"rel:has-many,join:guid=thought_id" json:"relthoughtidpublicembeddings,omitempty"` // Has many ModelPublicEmbeddings
|
RelThoughtIDPublicEmbeddings []*ModelPublicEmbeddings `bun:"rel:has-many,join:id=thought_id" json:"relthoughtidpublicembeddings,omitempty"` // Has many ModelPublicEmbeddings
|
||||||
RelThoughtIDPublicStoredFiles []*ModelPublicStoredFiles `bun:"rel:has-many,join:guid=thought_id" json:"relthoughtidpublicstoredfiles,omitempty"` // Has many ModelPublicStoredFiles
|
RelThoughtIDPublicStoredFiles []*ModelPublicStoredFiles `bun:"rel:has-many,join:id=thought_id" json:"relthoughtidpublicstoredfiles,omitempty"` // Has many ModelPublicStoredFiles
|
||||||
RelRelatedThoughtIDPublicLearnings []*ModelPublicLearnings `bun:"rel:has-many,join:guid=related_thought_id" json:"relrelatedthoughtidpubliclearnings,omitempty"` // Has many ModelPublicLearnings
|
RelRelatedThoughtIDPublicLearnings []*ModelPublicLearnings `bun:"rel:has-many,join:id=related_thought_id" json:"relrelatedthoughtidpubliclearnings,omitempty"` // Has many ModelPublicLearnings
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName returns the table name for ModelPublicThoughts
|
// TableName returns the table name for ModelPublicThoughts
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
||||||
@@ -28,7 +27,7 @@ func (db *DB) SaveChatHistory(ctx context.Context, h ext.ChatHistory) (ext.ChatH
|
|||||||
insert into chat_histories
|
insert into chat_histories
|
||||||
(session_id, title, channel, agent_id, project_id, messages, summary, metadata)
|
(session_id, title, channel, agent_id, project_id, messages, summary, metadata)
|
||||||
values ($1, $2, $3, $4, $5, $6, $7, $8)
|
values ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||||
returning id, created_at, updated_at
|
returning id, guid, created_at, updated_at
|
||||||
`,
|
`,
|
||||||
h.SessionID, nullStr(h.Title), nullStr(h.Channel), nullStr(h.AgentID),
|
h.SessionID, nullStr(h.Title), nullStr(h.Channel), nullStr(h.AgentID),
|
||||||
h.ProjectID, messages, nullStr(h.Summary), meta,
|
h.ProjectID, messages, nullStr(h.Summary), meta,
|
||||||
@@ -36,16 +35,17 @@ func (db *DB) SaveChatHistory(ctx context.Context, h ext.ChatHistory) (ext.ChatH
|
|||||||
|
|
||||||
created := h
|
created := h
|
||||||
var model generatedmodels.ModelPublicChatHistories
|
var model generatedmodels.ModelPublicChatHistories
|
||||||
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
if err := row.Scan(&model.ID, &model.GUID, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||||
return ext.ChatHistory{}, fmt.Errorf("insert chat history: %w", err)
|
return ext.ChatHistory{}, fmt.Errorf("insert chat history: %w", err)
|
||||||
}
|
}
|
||||||
created.ID = model.ID.UUID()
|
created.ID = model.ID.Int64()
|
||||||
|
created.GUID = model.GUID.UUID()
|
||||||
created.CreatedAt = model.CreatedAt.Time()
|
created.CreatedAt = model.CreatedAt.Time()
|
||||||
created.UpdatedAt = model.UpdatedAt.Time()
|
created.UpdatedAt = model.UpdatedAt.Time()
|
||||||
return created, nil
|
return created, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) GetChatHistory(ctx context.Context, id uuid.UUID) (ext.ChatHistory, bool, error) {
|
func (db *DB) GetChatHistory(ctx context.Context, id int64) (ext.ChatHistory, bool, error) {
|
||||||
row := db.pool.QueryRow(ctx, `
|
row := db.pool.QueryRow(ctx, `
|
||||||
select id, session_id, title, channel, agent_id, project_id,
|
select id, session_id, title, channel, agent_id, project_id,
|
||||||
messages, summary, metadata, created_at, updated_at
|
messages, summary, metadata, created_at, updated_at
|
||||||
@@ -81,7 +81,7 @@ func (db *DB) GetChatHistoryBySessionID(ctx context.Context, sessionID string) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ListChatHistoriesFilter struct {
|
type ListChatHistoriesFilter struct {
|
||||||
ProjectID *uuid.UUID
|
ProjectID *int64
|
||||||
Channel string
|
Channel string
|
||||||
AgentID string
|
AgentID string
|
||||||
SessionID string
|
SessionID string
|
||||||
@@ -149,7 +149,7 @@ func (db *DB) ListChatHistories(ctx context.Context, f ListChatHistoriesFilter)
|
|||||||
return result, rows.Err()
|
return result, rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) DeleteChatHistory(ctx context.Context, id uuid.UUID) (bool, error) {
|
func (db *DB) DeleteChatHistory(ctx context.Context, id int64) (bool, error) {
|
||||||
tag, err := db.pool.Exec(ctx, `delete from chat_histories where id = $1`, id)
|
tag, err := db.pool.Exec(ctx, `delete from chat_histories where id = $1`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("delete chat history: %w", err)
|
return false, fmt.Errorf("delete chat history: %w", err)
|
||||||
@@ -171,7 +171,8 @@ func scanChatHistory(row rowScanner) (ext.ChatHistory, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
h := ext.ChatHistory{
|
h := ext.ChatHistory{
|
||||||
ID: model.ID.UUID(),
|
ID: model.ID.Int64(),
|
||||||
|
GUID: model.GUID.UUID(),
|
||||||
SessionID: model.SessionID.String(),
|
SessionID: model.SessionID.String(),
|
||||||
Title: model.Title.String(),
|
Title: model.Title.String(),
|
||||||
Channel: model.Channel.String(),
|
Channel: model.Channel.String(),
|
||||||
@@ -181,7 +182,7 @@ func scanChatHistory(row rowScanner) (ext.ChatHistory, error) {
|
|||||||
UpdatedAt: model.UpdatedAt.Time(),
|
UpdatedAt: model.UpdatedAt.Time(),
|
||||||
}
|
}
|
||||||
if model.ProjectID.Valid {
|
if model.ProjectID.Valid {
|
||||||
id := model.ProjectID.UUID()
|
id := model.ProjectID.Int64()
|
||||||
h.ProjectID = &id
|
h.ProjectID = &id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,12 @@ func (db *DB) InsertStoredFile(ctx context.Context, file thoughttypes.StoredFile
|
|||||||
row := db.pool.QueryRow(ctx, `
|
row := db.pool.QueryRow(ctx, `
|
||||||
insert into stored_files (thought_id, project_id, name, media_type, kind, encoding, size_bytes, sha256, content)
|
insert into stored_files (thought_id, project_id, name, media_type, kind, encoding, size_bytes, sha256, content)
|
||||||
values ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
values ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||||
returning guid, thought_id, project_id, name, media_type, kind, encoding, size_bytes, sha256, created_at, updated_at
|
returning id, guid, thought_id, project_id, name, media_type, kind, encoding, size_bytes, sha256, created_at, updated_at
|
||||||
`, file.ThoughtID, file.ProjectID, file.Name, file.MediaType, file.Kind, file.Encoding, file.SizeBytes, file.SHA256, file.Content)
|
`, file.ThoughtID, file.ProjectID, file.Name, file.MediaType, file.Kind, file.Encoding, file.SizeBytes, file.SHA256, file.Content)
|
||||||
|
|
||||||
var model generatedmodels.ModelPublicStoredFiles
|
var model generatedmodels.ModelPublicStoredFiles
|
||||||
if err := row.Scan(
|
if err := row.Scan(
|
||||||
|
&model.ID,
|
||||||
&model.GUID,
|
&model.GUID,
|
||||||
&model.ThoughtID,
|
&model.ThoughtID,
|
||||||
&model.ProjectID,
|
&model.ProjectID,
|
||||||
@@ -42,13 +43,14 @@ func (db *DB) InsertStoredFile(ctx context.Context, file thoughttypes.StoredFile
|
|||||||
|
|
||||||
func (db *DB) GetStoredFile(ctx context.Context, id uuid.UUID) (thoughttypes.StoredFile, error) {
|
func (db *DB) GetStoredFile(ctx context.Context, id uuid.UUID) (thoughttypes.StoredFile, error) {
|
||||||
row := db.pool.QueryRow(ctx, `
|
row := db.pool.QueryRow(ctx, `
|
||||||
select guid, thought_id, project_id, name, media_type, kind, encoding, size_bytes, sha256, content, created_at, updated_at
|
select id, guid, thought_id, project_id, name, media_type, kind, encoding, size_bytes, sha256, content, created_at, updated_at
|
||||||
from stored_files
|
from stored_files
|
||||||
where guid = $1
|
where guid = $1
|
||||||
`, id)
|
`, id)
|
||||||
|
|
||||||
var model generatedmodels.ModelPublicStoredFiles
|
var model generatedmodels.ModelPublicStoredFiles
|
||||||
if err := row.Scan(
|
if err := row.Scan(
|
||||||
|
&model.ID,
|
||||||
&model.GUID,
|
&model.GUID,
|
||||||
&model.ThoughtID,
|
&model.ThoughtID,
|
||||||
&model.ProjectID,
|
&model.ProjectID,
|
||||||
@@ -89,7 +91,7 @@ func (db *DB) ListStoredFiles(ctx context.Context, filter thoughttypes.StoredFil
|
|||||||
}
|
}
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
select guid, thought_id, project_id, name, media_type, kind, encoding, size_bytes, sha256, created_at, updated_at
|
select id, guid, thought_id, project_id, name, media_type, kind, encoding, size_bytes, sha256, created_at, updated_at
|
||||||
from stored_files
|
from stored_files
|
||||||
`
|
`
|
||||||
if len(conditions) > 0 {
|
if len(conditions) > 0 {
|
||||||
@@ -109,6 +111,7 @@ func (db *DB) ListStoredFiles(ctx context.Context, filter thoughttypes.StoredFil
|
|||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var model generatedmodels.ModelPublicStoredFiles
|
var model generatedmodels.ModelPublicStoredFiles
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
|
&model.ID,
|
||||||
&model.GUID,
|
&model.GUID,
|
||||||
&model.ThoughtID,
|
&model.ThoughtID,
|
||||||
&model.ProjectID,
|
&model.ProjectID,
|
||||||
@@ -132,7 +135,7 @@ func (db *DB) ListStoredFiles(ctx context.Context, filter thoughttypes.StoredFil
|
|||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) AddThoughtAttachment(ctx context.Context, thoughtID uuid.UUID, attachment thoughttypes.ThoughtAttachment) error {
|
func (db *DB) AddThoughtAttachment(ctx context.Context, thoughtID int64, attachment thoughttypes.ThoughtAttachment) error {
|
||||||
tx, err := db.pool.Begin(ctx)
|
tx, err := db.pool.Begin(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("begin transaction: %w", err)
|
return fmt.Errorf("begin transaction: %w", err)
|
||||||
@@ -142,7 +145,7 @@ func (db *DB) AddThoughtAttachment(ctx context.Context, thoughtID uuid.UUID, att
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
var metadataBytes []byte
|
var metadataBytes []byte
|
||||||
if err := tx.QueryRow(ctx, `select metadata from thoughts where guid = $1 for update`, thoughtID).Scan(&metadataBytes); err != nil {
|
if err := tx.QueryRow(ctx, `select metadata from thoughts where id = $1 for update`, thoughtID).Scan(&metadataBytes); err != nil {
|
||||||
if err == pgx.ErrNoRows {
|
if err == pgx.ErrNoRows {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -177,7 +180,7 @@ func (db *DB) AddThoughtAttachment(ctx context.Context, thoughtID uuid.UUID, att
|
|||||||
update thoughts
|
update thoughts
|
||||||
set metadata = $2::jsonb,
|
set metadata = $2::jsonb,
|
||||||
updated_at = now()
|
updated_at = now()
|
||||||
where guid = $1
|
where id = $1
|
||||||
`, thoughtID, updatedMetadata)
|
`, thoughtID, updatedMetadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("update thought attachments: %w", err)
|
return fmt.Errorf("update thought attachments: %w", err)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
|
|
||||||
thoughttypes "git.warky.dev/wdevs/amcs/internal/types"
|
thoughttypes "git.warky.dev/wdevs/amcs/internal/types"
|
||||||
@@ -25,7 +24,7 @@ func (db *DB) CreateLearning(ctx context.Context, learning thoughttypes.Learning
|
|||||||
$13, $14, $15, $16,
|
$13, $14, $15, $16,
|
||||||
$17, $18
|
$17, $18
|
||||||
)
|
)
|
||||||
returning id, created_at, updated_at
|
returning id, guid, created_at, updated_at
|
||||||
`,
|
`,
|
||||||
strings.TrimSpace(learning.Summary),
|
strings.TrimSpace(learning.Summary),
|
||||||
strings.TrimSpace(learning.Details),
|
strings.TrimSpace(learning.Details),
|
||||||
@@ -49,16 +48,17 @@ func (db *DB) CreateLearning(ctx context.Context, learning thoughttypes.Learning
|
|||||||
|
|
||||||
created := learning
|
created := learning
|
||||||
var model generatedmodels.ModelPublicLearnings
|
var model generatedmodels.ModelPublicLearnings
|
||||||
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
if err := row.Scan(&model.ID, &model.GUID, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||||
return thoughttypes.Learning{}, fmt.Errorf("create learning: %w", err)
|
return thoughttypes.Learning{}, fmt.Errorf("create learning: %w", err)
|
||||||
}
|
}
|
||||||
created.ID = model.ID.UUID()
|
created.ID = model.ID.Int64()
|
||||||
|
created.GUID = model.GUID.UUID()
|
||||||
created.CreatedAt = model.CreatedAt.Time()
|
created.CreatedAt = model.CreatedAt.Time()
|
||||||
created.UpdatedAt = model.UpdatedAt.Time()
|
created.UpdatedAt = model.UpdatedAt.Time()
|
||||||
return created, nil
|
return created, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) GetLearning(ctx context.Context, id uuid.UUID) (thoughttypes.Learning, error) {
|
func (db *DB) GetLearning(ctx context.Context, id int64) (thoughttypes.Learning, error) {
|
||||||
row := db.pool.QueryRow(ctx, `
|
row := db.pool.QueryRow(ctx, `
|
||||||
select id, summary, details, category, area, status, priority, confidence,
|
select id, summary, details, category, area, status, priority, confidence,
|
||||||
action_required, source_type, source_ref, project_id, related_thought_id,
|
action_required, source_type, source_ref, project_id, related_thought_id,
|
||||||
@@ -71,7 +71,7 @@ func (db *DB) GetLearning(ctx context.Context, id uuid.UUID) (thoughttypes.Learn
|
|||||||
learning, err := scanLearning(row)
|
learning, err := scanLearning(row)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == pgx.ErrNoRows {
|
if err == pgx.ErrNoRows {
|
||||||
return thoughttypes.Learning{}, fmt.Errorf("learning not found: %s", id)
|
return thoughttypes.Learning{}, fmt.Errorf("learning not found: %d", id)
|
||||||
}
|
}
|
||||||
return thoughttypes.Learning{}, fmt.Errorf("get learning: %w", err)
|
return thoughttypes.Learning{}, fmt.Errorf("get learning: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ func (db *DB) InsertLink(ctx context.Context, link thoughttypes.ThoughtLink) err
|
|||||||
|
|
||||||
func (db *DB) LinkedThoughts(ctx context.Context, thoughtID uuid.UUID) ([]thoughttypes.LinkedThought, error) {
|
func (db *DB) LinkedThoughts(ctx context.Context, thoughtID uuid.UUID) ([]thoughttypes.LinkedThought, error) {
|
||||||
rows, err := db.pool.Query(ctx, `
|
rows, err := db.pool.Query(ctx, `
|
||||||
select t.guid, t.content, t.metadata, t.project_id, t.archived_at, t.created_at, t.updated_at, l.relation, 'outgoing' as direction, l.created_at
|
select t.id, t.guid, t.content, t.metadata, t.project_id, t.archived_at, t.created_at, t.updated_at, l.relation, 'outgoing' as direction, l.created_at
|
||||||
from thought_links l
|
from thought_links l
|
||||||
join thoughts t on t.id = l.to_id
|
join thoughts t on t.id = l.to_id
|
||||||
where l.from_id = (select id from thoughts where guid = $1)
|
where l.from_id = (select id from thoughts where guid = $1)
|
||||||
union all
|
union all
|
||||||
select t.guid, t.content, t.metadata, t.project_id, t.archived_at, t.created_at, t.updated_at, l.relation, 'incoming' as direction, l.created_at
|
select t.id, t.guid, t.content, t.metadata, t.project_id, t.archived_at, t.created_at, t.updated_at, l.relation, 'incoming' as direction, l.created_at
|
||||||
from thought_links l
|
from thought_links l
|
||||||
join thoughts t on t.id = l.from_id
|
join thoughts t on t.id = l.from_id
|
||||||
where l.to_id = (select id from thoughts where guid = $1)
|
where l.to_id = (select id from thoughts where guid = $1)
|
||||||
@@ -46,6 +46,7 @@ func (db *DB) LinkedThoughts(ctx context.Context, thoughtID uuid.UUID) ([]though
|
|||||||
var linked thoughttypes.LinkedThought
|
var linked thoughttypes.LinkedThought
|
||||||
var model generatedmodels.ModelPublicThoughts
|
var model generatedmodels.ModelPublicThoughts
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
|
&model.ID,
|
||||||
&model.GUID,
|
&model.GUID,
|
||||||
&model.Content,
|
&model.Content,
|
||||||
&model.Metadata,
|
&model.Metadata,
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
||||||
ext "git.warky.dev/wdevs/amcs/internal/types"
|
ext "git.warky.dev/wdevs/amcs/internal/types"
|
||||||
)
|
)
|
||||||
@@ -14,6 +12,7 @@ import (
|
|||||||
func projectFromModel(m generatedmodels.ModelPublicProjects) ext.Project {
|
func projectFromModel(m generatedmodels.ModelPublicProjects) ext.Project {
|
||||||
return ext.Project{
|
return ext.Project{
|
||||||
ID: m.GUID.UUID(),
|
ID: m.GUID.UUID(),
|
||||||
|
NumericID: m.ID.Int64(),
|
||||||
Name: m.Name.String(),
|
Name: m.Name.String(),
|
||||||
Description: m.Description.String(),
|
Description: m.Description.String(),
|
||||||
CreatedAt: m.CreatedAt.Time(),
|
CreatedAt: m.CreatedAt.Time(),
|
||||||
@@ -29,9 +28,9 @@ func thoughtFromModel(m generatedmodels.ModelPublicThoughts) (ext.Thought, error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if m.ProjectID.Valid {
|
if m.ProjectID.Valid {
|
||||||
id := m.ProjectID.UUID()
|
id := m.ProjectID.Int64()
|
||||||
projectID = &id
|
projectID = &id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +41,8 @@ func thoughtFromModel(m generatedmodels.ModelPublicThoughts) (ext.Thought, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ext.Thought{
|
return ext.Thought{
|
||||||
ID: m.GUID.UUID(),
|
ID: m.ID.Int64(),
|
||||||
|
GUID: m.GUID.UUID(),
|
||||||
Content: m.Content.String(),
|
Content: m.Content.String(),
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
ProjectID: projectID,
|
ProjectID: projectID,
|
||||||
@@ -53,20 +53,21 @@ func thoughtFromModel(m generatedmodels.ModelPublicThoughts) (ext.Thought, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func storedFileFromModel(m generatedmodels.ModelPublicStoredFiles) ext.StoredFile {
|
func storedFileFromModel(m generatedmodels.ModelPublicStoredFiles) ext.StoredFile {
|
||||||
var thoughtID *uuid.UUID
|
var thoughtID *int64
|
||||||
if m.ThoughtID.Valid {
|
if m.ThoughtID.Valid {
|
||||||
id := m.ThoughtID.UUID()
|
id := m.ThoughtID.Int64()
|
||||||
thoughtID = &id
|
thoughtID = &id
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if m.ProjectID.Valid {
|
if m.ProjectID.Valid {
|
||||||
id := m.ProjectID.UUID()
|
id := m.ProjectID.Int64()
|
||||||
projectID = &id
|
projectID = &id
|
||||||
}
|
}
|
||||||
|
|
||||||
return ext.StoredFile{
|
return ext.StoredFile{
|
||||||
ID: m.GUID.UUID(),
|
ID: m.ID.Int64(),
|
||||||
|
GUID: m.GUID.UUID(),
|
||||||
ThoughtID: thoughtID,
|
ThoughtID: thoughtID,
|
||||||
ProjectID: projectID,
|
ProjectID: projectID,
|
||||||
Name: m.Name.String(),
|
Name: m.Name.String(),
|
||||||
@@ -419,9 +420,9 @@ func storedFileFromModel(m generatedmodels.ModelPublicStoredFiles) ext.StoredFil
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
func planFromModel(m generatedmodels.ModelPublicPlans, tags []string) ext.Plan {
|
func planFromModel(m generatedmodels.ModelPublicPlans, tags []string) ext.Plan {
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if m.ProjectID.Valid {
|
if m.ProjectID.Valid {
|
||||||
id := m.ProjectID.UUID()
|
id := m.ProjectID.Int64()
|
||||||
projectID = &id
|
projectID = &id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,14 +444,15 @@ func planFromModel(m generatedmodels.ModelPublicPlans, tags []string) ext.Plan {
|
|||||||
lastReviewedAt = &t
|
lastReviewedAt = &t
|
||||||
}
|
}
|
||||||
|
|
||||||
var supersedesPlanID *uuid.UUID
|
var supersedesPlanID *int64
|
||||||
if m.SupersedesPlanID.Valid {
|
if m.SupersedesPlanID.Valid {
|
||||||
id := m.SupersedesPlanID.UUID()
|
id := m.SupersedesPlanID.Int64()
|
||||||
supersedesPlanID = &id
|
supersedesPlanID = &id
|
||||||
}
|
}
|
||||||
|
|
||||||
return ext.Plan{
|
return ext.Plan{
|
||||||
ID: m.ID.UUID(),
|
ID: m.ID.Int64(),
|
||||||
|
GUID: m.GUID.UUID(),
|
||||||
Title: m.Title.String(),
|
Title: m.Title.String(),
|
||||||
Description: m.Description.String(),
|
Description: m.Description.String(),
|
||||||
Status: ext.PlanStatus(m.Status.String()),
|
Status: ext.PlanStatus(m.Status.String()),
|
||||||
@@ -469,33 +471,33 @@ func planFromModel(m generatedmodels.ModelPublicPlans, tags []string) ext.Plan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func learningFromModel(m generatedmodels.ModelPublicLearnings, tags []string) ext.Learning {
|
func learningFromModel(m generatedmodels.ModelPublicLearnings, tags []string) ext.Learning {
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if m.ProjectID.Valid {
|
if m.ProjectID.Valid {
|
||||||
id := m.ProjectID.UUID()
|
id := m.ProjectID.Int64()
|
||||||
projectID = &id
|
projectID = &id
|
||||||
}
|
}
|
||||||
|
|
||||||
var relatedThoughtID *uuid.UUID
|
var relatedThoughtID *int64
|
||||||
if m.RelatedThoughtID.Valid {
|
if m.RelatedThoughtID.Valid {
|
||||||
id := m.RelatedThoughtID.UUID()
|
id := m.RelatedThoughtID.Int64()
|
||||||
relatedThoughtID = &id
|
relatedThoughtID = &id
|
||||||
}
|
}
|
||||||
|
|
||||||
var relatedSkillID *uuid.UUID
|
var relatedSkillID *int64
|
||||||
if m.RelatedSkillID.Valid {
|
if m.RelatedSkillID.Valid {
|
||||||
id := m.RelatedSkillID.UUID()
|
id := m.RelatedSkillID.Int64()
|
||||||
relatedSkillID = &id
|
relatedSkillID = &id
|
||||||
}
|
}
|
||||||
|
|
||||||
var duplicateOfLearningID *uuid.UUID
|
var duplicateOfLearningID *int64
|
||||||
if m.DuplicateOfLearningID.Valid {
|
if m.DuplicateOfLearningID.Valid {
|
||||||
id := m.DuplicateOfLearningID.UUID()
|
id := m.DuplicateOfLearningID.Int64()
|
||||||
duplicateOfLearningID = &id
|
duplicateOfLearningID = &id
|
||||||
}
|
}
|
||||||
|
|
||||||
var supersedesLearningID *uuid.UUID
|
var supersedesLearningID *int64
|
||||||
if m.SupersedesLearningID.Valid {
|
if m.SupersedesLearningID.Valid {
|
||||||
id := m.SupersedesLearningID.UUID()
|
id := m.SupersedesLearningID.Int64()
|
||||||
supersedesLearningID = &id
|
supersedesLearningID = &id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -512,7 +514,8 @@ func learningFromModel(m generatedmodels.ModelPublicLearnings, tags []string) ex
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ext.Learning{
|
return ext.Learning{
|
||||||
ID: m.ID.UUID(),
|
ID: m.ID.Int64(),
|
||||||
|
GUID: m.GUID.UUID(),
|
||||||
Summary: m.Summary.String(),
|
Summary: m.Summary.String(),
|
||||||
Details: m.Details.String(),
|
Details: m.Details.String(),
|
||||||
Category: m.Category.String(),
|
Category: m.Category.String(),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const planColumns = `
|
const planColumns = `
|
||||||
id, title, description, status, priority, project_id, owner, due_date,
|
id, guid, title, description, status, priority, project_id, owner, due_date,
|
||||||
completed_at, reviewed_by, last_reviewed_at, supersedes_plan_id, tags::text[], created_at, updated_at`
|
completed_at, reviewed_by, last_reviewed_at, supersedes_plan_id, tags::text[], created_at, updated_at`
|
||||||
|
|
||||||
func (db *DB) CreatePlan(ctx context.Context, plan ext.Plan) (ext.Plan, error) {
|
func (db *DB) CreatePlan(ctx context.Context, plan ext.Plan) (ext.Plan, error) {
|
||||||
@@ -37,19 +37,19 @@ func (db *DB) CreatePlan(ctx context.Context, plan ext.Plan) (ext.Plan, error) {
|
|||||||
return scanPlan(row)
|
return scanPlan(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) GetPlan(ctx context.Context, id uuid.UUID) (ext.Plan, error) {
|
func (db *DB) GetPlan(ctx context.Context, id int64) (ext.Plan, error) {
|
||||||
row := db.pool.QueryRow(ctx, `select`+planColumns+` from plans where id = $1`, id)
|
row := db.pool.QueryRow(ctx, `select`+planColumns+` from plans where id = $1`, id)
|
||||||
plan, err := scanPlan(row)
|
plan, err := scanPlan(row)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == pgx.ErrNoRows {
|
if err == pgx.ErrNoRows {
|
||||||
return ext.Plan{}, fmt.Errorf("plan not found: %s", id)
|
return ext.Plan{}, fmt.Errorf("plan not found: %d", id)
|
||||||
}
|
}
|
||||||
return ext.Plan{}, fmt.Errorf("get plan: %w", err)
|
return ext.Plan{}, fmt.Errorf("get plan: %w", err)
|
||||||
}
|
}
|
||||||
return plan, nil
|
return plan, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) GetPlanDetail(ctx context.Context, id uuid.UUID) (ext.PlanDetail, error) {
|
func (db *DB) GetPlanDetail(ctx context.Context, id int64) (ext.PlanDetail, error) {
|
||||||
plan, err := db.GetPlan(ctx, id)
|
plan, err := db.GetPlan(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ext.PlanDetail{}, err
|
return ext.PlanDetail{}, err
|
||||||
@@ -105,7 +105,7 @@ func (db *DB) GetPlanDetail(ctx context.Context, id uuid.UUID) (ext.PlanDetail,
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) UpdatePlan(ctx context.Context, id uuid.UUID, u ext.PlanUpdate) (ext.Plan, error) {
|
func (db *DB) UpdatePlan(ctx context.Context, id int64, u ext.PlanUpdate) (ext.Plan, error) {
|
||||||
sets := []string{"updated_at = now()"}
|
sets := []string{"updated_at = now()"}
|
||||||
args := []any{}
|
args := []any{}
|
||||||
|
|
||||||
@@ -169,14 +169,14 @@ func (db *DB) UpdatePlan(ctx context.Context, id uuid.UUID, u ext.PlanUpdate) (e
|
|||||||
plan, err := scanPlan(row)
|
plan, err := scanPlan(row)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == pgx.ErrNoRows {
|
if err == pgx.ErrNoRows {
|
||||||
return ext.Plan{}, fmt.Errorf("plan not found: %s", id)
|
return ext.Plan{}, fmt.Errorf("plan not found: %d", id)
|
||||||
}
|
}
|
||||||
return ext.Plan{}, fmt.Errorf("update plan: %w", err)
|
return ext.Plan{}, fmt.Errorf("update plan: %w", err)
|
||||||
}
|
}
|
||||||
return plan, nil
|
return plan, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) DeletePlan(ctx context.Context, id uuid.UUID) error {
|
func (db *DB) DeletePlan(ctx context.Context, id int64) error {
|
||||||
tag, err := db.pool.Exec(ctx, `delete from plans where id = $1`, id)
|
tag, err := db.pool.Exec(ctx, `delete from plans where id = $1`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("delete plan: %w", err)
|
return fmt.Errorf("delete plan: %w", err)
|
||||||
@@ -232,7 +232,7 @@ func (db *DB) ListPlans(ctx context.Context, filter ext.PlanFilter) ([]ext.Plan,
|
|||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
|
|
||||||
func (db *DB) AddPlanDependency(ctx context.Context, planID, dependsOnPlanID uuid.UUID) error {
|
func (db *DB) AddPlanDependency(ctx context.Context, planID, dependsOnPlanID int64) error {
|
||||||
_, err := db.pool.Exec(ctx, `
|
_, err := db.pool.Exec(ctx, `
|
||||||
insert into plan_dependencies (plan_id, depends_on_plan_id)
|
insert into plan_dependencies (plan_id, depends_on_plan_id)
|
||||||
values ($1, $2)
|
values ($1, $2)
|
||||||
@@ -244,7 +244,7 @@ func (db *DB) AddPlanDependency(ctx context.Context, planID, dependsOnPlanID uui
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) RemovePlanDependency(ctx context.Context, planID, dependsOnPlanID uuid.UUID) error {
|
func (db *DB) RemovePlanDependency(ctx context.Context, planID, dependsOnPlanID int64) error {
|
||||||
tag, err := db.pool.Exec(ctx, `
|
tag, err := db.pool.Exec(ctx, `
|
||||||
delete from plan_dependencies where plan_id = $1 and depends_on_plan_id = $2
|
delete from plan_dependencies where plan_id = $1 and depends_on_plan_id = $2
|
||||||
`, planID, dependsOnPlanID)
|
`, planID, dependsOnPlanID)
|
||||||
@@ -259,7 +259,7 @@ func (db *DB) RemovePlanDependency(ctx context.Context, planID, dependsOnPlanID
|
|||||||
|
|
||||||
// Related Plans
|
// Related Plans
|
||||||
|
|
||||||
func (db *DB) AddRelatedPlan(ctx context.Context, planAID, planBID uuid.UUID) error {
|
func (db *DB) AddRelatedPlan(ctx context.Context, planAID, planBID int64) error {
|
||||||
a, b := canonicalPlanPair(planAID, planBID)
|
a, b := canonicalPlanPair(planAID, planBID)
|
||||||
_, err := db.pool.Exec(ctx, `
|
_, err := db.pool.Exec(ctx, `
|
||||||
insert into plan_related_plans (plan_a_id, plan_b_id)
|
insert into plan_related_plans (plan_a_id, plan_b_id)
|
||||||
@@ -272,7 +272,7 @@ func (db *DB) AddRelatedPlan(ctx context.Context, planAID, planBID uuid.UUID) er
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) RemoveRelatedPlan(ctx context.Context, planAID, planBID uuid.UUID) error {
|
func (db *DB) RemoveRelatedPlan(ctx context.Context, planAID, planBID int64) error {
|
||||||
a, b := canonicalPlanPair(planAID, planBID)
|
a, b := canonicalPlanPair(planAID, planBID)
|
||||||
tag, err := db.pool.Exec(ctx, `
|
tag, err := db.pool.Exec(ctx, `
|
||||||
delete from plan_related_plans where plan_a_id = $1 and plan_b_id = $2
|
delete from plan_related_plans where plan_a_id = $1 and plan_b_id = $2
|
||||||
@@ -288,7 +288,7 @@ func (db *DB) RemoveRelatedPlan(ctx context.Context, planAID, planBID uuid.UUID)
|
|||||||
|
|
||||||
// Plan Skills
|
// Plan Skills
|
||||||
|
|
||||||
func (db *DB) AddPlanSkill(ctx context.Context, planID, skillID uuid.UUID) error {
|
func (db *DB) AddPlanSkill(ctx context.Context, planID, skillID int64) error {
|
||||||
_, err := db.pool.Exec(ctx, `
|
_, err := db.pool.Exec(ctx, `
|
||||||
insert into plan_skills (plan_id, skill_id) values ($1, $2) on conflict do nothing
|
insert into plan_skills (plan_id, skill_id) values ($1, $2) on conflict do nothing
|
||||||
`, planID, skillID)
|
`, planID, skillID)
|
||||||
@@ -298,7 +298,7 @@ func (db *DB) AddPlanSkill(ctx context.Context, planID, skillID uuid.UUID) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) RemovePlanSkill(ctx context.Context, planID, skillID uuid.UUID) error {
|
func (db *DB) RemovePlanSkill(ctx context.Context, planID, skillID int64) error {
|
||||||
tag, err := db.pool.Exec(ctx, `
|
tag, err := db.pool.Exec(ctx, `
|
||||||
delete from plan_skills where plan_id = $1 and skill_id = $2
|
delete from plan_skills where plan_id = $1 and skill_id = $2
|
||||||
`, planID, skillID)
|
`, planID, skillID)
|
||||||
@@ -311,7 +311,7 @@ func (db *DB) RemovePlanSkill(ctx context.Context, planID, skillID uuid.UUID) er
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) ListPlanSkills(ctx context.Context, planID uuid.UUID) ([]ext.AgentSkill, error) {
|
func (db *DB) ListPlanSkills(ctx context.Context, planID int64) ([]ext.AgentSkill, error) {
|
||||||
rows, err := db.pool.Query(ctx, `
|
rows, err := db.pool.Query(ctx, `
|
||||||
select s.id, s.name, s.description, s.content, s.tags::text[], s.created_at, s.updated_at
|
select s.id, s.name, s.description, s.content, s.tags::text[], s.created_at, s.updated_at
|
||||||
from agent_skills s
|
from agent_skills s
|
||||||
@@ -332,7 +332,7 @@ func (db *DB) ListPlanSkills(ctx context.Context, planID uuid.UUID) ([]ext.Agent
|
|||||||
return nil, fmt.Errorf("scan plan skill: %w", err)
|
return nil, fmt.Errorf("scan plan skill: %w", err)
|
||||||
}
|
}
|
||||||
s := ext.AgentSkill{
|
s := ext.AgentSkill{
|
||||||
ID: model.ID.UUID(),
|
ID: model.ID.Int64(),
|
||||||
Name: model.Name.String(),
|
Name: model.Name.String(),
|
||||||
Description: model.Description.String(),
|
Description: model.Description.String(),
|
||||||
Content: model.Content.String(),
|
Content: model.Content.String(),
|
||||||
@@ -350,7 +350,7 @@ func (db *DB) ListPlanSkills(ctx context.Context, planID uuid.UUID) ([]ext.Agent
|
|||||||
|
|
||||||
// Plan Guardrails
|
// Plan Guardrails
|
||||||
|
|
||||||
func (db *DB) AddPlanGuardrail(ctx context.Context, planID, guardrailID uuid.UUID) error {
|
func (db *DB) AddPlanGuardrail(ctx context.Context, planID, guardrailID int64) error {
|
||||||
_, err := db.pool.Exec(ctx, `
|
_, err := db.pool.Exec(ctx, `
|
||||||
insert into plan_guardrails (plan_id, guardrail_id) values ($1, $2) on conflict do nothing
|
insert into plan_guardrails (plan_id, guardrail_id) values ($1, $2) on conflict do nothing
|
||||||
`, planID, guardrailID)
|
`, planID, guardrailID)
|
||||||
@@ -360,7 +360,7 @@ func (db *DB) AddPlanGuardrail(ctx context.Context, planID, guardrailID uuid.UUI
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) RemovePlanGuardrail(ctx context.Context, planID, guardrailID uuid.UUID) error {
|
func (db *DB) RemovePlanGuardrail(ctx context.Context, planID, guardrailID int64) error {
|
||||||
tag, err := db.pool.Exec(ctx, `
|
tag, err := db.pool.Exec(ctx, `
|
||||||
delete from plan_guardrails where plan_id = $1 and guardrail_id = $2
|
delete from plan_guardrails where plan_id = $1 and guardrail_id = $2
|
||||||
`, planID, guardrailID)
|
`, planID, guardrailID)
|
||||||
@@ -373,7 +373,7 @@ func (db *DB) RemovePlanGuardrail(ctx context.Context, planID, guardrailID uuid.
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) ListPlanGuardrails(ctx context.Context, planID uuid.UUID) ([]ext.AgentGuardrail, error) {
|
func (db *DB) ListPlanGuardrails(ctx context.Context, planID int64) ([]ext.AgentGuardrail, error) {
|
||||||
rows, err := db.pool.Query(ctx, `
|
rows, err := db.pool.Query(ctx, `
|
||||||
select g.id, g.name, g.description, g.content, g.severity, g.tags::text[], g.created_at, g.updated_at
|
select g.id, g.name, g.description, g.content, g.severity, g.tags::text[], g.created_at, g.updated_at
|
||||||
from agent_guardrails g
|
from agent_guardrails g
|
||||||
@@ -394,7 +394,7 @@ func (db *DB) ListPlanGuardrails(ctx context.Context, planID uuid.UUID) ([]ext.A
|
|||||||
return nil, fmt.Errorf("scan plan guardrail: %w", err)
|
return nil, fmt.Errorf("scan plan guardrail: %w", err)
|
||||||
}
|
}
|
||||||
g := ext.AgentGuardrail{
|
g := ext.AgentGuardrail{
|
||||||
ID: model.ID.UUID(),
|
ID: model.ID.Int64(),
|
||||||
Name: model.Name.String(),
|
Name: model.Name.String(),
|
||||||
Description: model.Description.String(),
|
Description: model.Description.String(),
|
||||||
Content: model.Content.String(),
|
Content: model.Content.String(),
|
||||||
@@ -422,6 +422,7 @@ func scanPlan(row planScanner) (ext.Plan, error) {
|
|||||||
var tags []string
|
var tags []string
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
&model.ID,
|
&model.ID,
|
||||||
|
&model.GUID,
|
||||||
&model.Title,
|
&model.Title,
|
||||||
&model.Description,
|
&model.Description,
|
||||||
&model.Status,
|
&model.Status,
|
||||||
@@ -467,9 +468,9 @@ func (db *DB) listPlansByQuery(ctx context.Context, query string, args ...any) (
|
|||||||
return plans, nil
|
return plans, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// canonicalPlanPair ensures the smaller UUID is always plan_a_id to prevent duplicates.
|
// canonicalPlanPair ensures the smaller ID is always plan_a_id to prevent duplicates.
|
||||||
func canonicalPlanPair(a, b uuid.UUID) (uuid.UUID, uuid.UUID) {
|
func canonicalPlanPair(a, b int64) (int64, int64) {
|
||||||
if strings.Compare(a.String(), b.String()) <= 0 {
|
if a <= b {
|
||||||
return a, b
|
return a, b
|
||||||
}
|
}
|
||||||
return b, a
|
return b, a
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ func (db *DB) CreateProject(ctx context.Context, name, description string) (thou
|
|||||||
row := db.pool.QueryRow(ctx, `
|
row := db.pool.QueryRow(ctx, `
|
||||||
insert into projects (name, description)
|
insert into projects (name, description)
|
||||||
values ($1, $2)
|
values ($1, $2)
|
||||||
returning guid, name, description, created_at, last_active_at
|
returning id, guid, name, description, created_at, last_active_at
|
||||||
`, name, description)
|
`, name, description)
|
||||||
|
|
||||||
var model generatedmodels.ModelPublicProjects
|
var model generatedmodels.ModelPublicProjects
|
||||||
if err := row.Scan(&model.GUID, &model.Name, &model.Description, &model.CreatedAt, &model.LastActiveAt); err != nil {
|
if err := row.Scan(&model.ID, &model.GUID, &model.Name, &model.Description, &model.CreatedAt, &model.LastActiveAt); err != nil {
|
||||||
return thoughttypes.Project{}, fmt.Errorf("create project: %w", err)
|
return thoughttypes.Project{}, fmt.Errorf("create project: %w", err)
|
||||||
}
|
}
|
||||||
return projectFromModel(model), nil
|
return projectFromModel(model), nil
|
||||||
@@ -46,7 +46,7 @@ func (db *DB) GetProject(ctx context.Context, nameOrID string) (thoughttypes.Pro
|
|||||||
|
|
||||||
func (db *DB) getProjectByGUID(ctx context.Context, id uuid.UUID) (thoughttypes.Project, error) {
|
func (db *DB) getProjectByGUID(ctx context.Context, id uuid.UUID) (thoughttypes.Project, error) {
|
||||||
row := db.pool.QueryRow(ctx, `
|
row := db.pool.QueryRow(ctx, `
|
||||||
select guid, name, description, created_at, last_active_at
|
select id, guid, name, description, created_at, last_active_at
|
||||||
from projects
|
from projects
|
||||||
where guid = $1
|
where guid = $1
|
||||||
`, id)
|
`, id)
|
||||||
@@ -55,7 +55,7 @@ func (db *DB) getProjectByGUID(ctx context.Context, id uuid.UUID) (thoughttypes.
|
|||||||
|
|
||||||
func (db *DB) getProjectByName(ctx context.Context, name string) (thoughttypes.Project, error) {
|
func (db *DB) getProjectByName(ctx context.Context, name string) (thoughttypes.Project, error) {
|
||||||
row := db.pool.QueryRow(ctx, `
|
row := db.pool.QueryRow(ctx, `
|
||||||
select guid, name, description, created_at, last_active_at
|
select id, guid, name, description, created_at, last_active_at
|
||||||
from projects
|
from projects
|
||||||
where name = $1
|
where name = $1
|
||||||
`, name)
|
`, name)
|
||||||
@@ -64,7 +64,7 @@ func (db *DB) getProjectByName(ctx context.Context, name string) (thoughttypes.P
|
|||||||
|
|
||||||
func scanProject(row pgx.Row) (thoughttypes.Project, error) {
|
func scanProject(row pgx.Row) (thoughttypes.Project, error) {
|
||||||
var model generatedmodels.ModelPublicProjects
|
var model generatedmodels.ModelPublicProjects
|
||||||
if err := row.Scan(&model.GUID, &model.Name, &model.Description, &model.CreatedAt, &model.LastActiveAt); err != nil {
|
if err := row.Scan(&model.ID, &model.GUID, &model.Name, &model.Description, &model.CreatedAt, &model.LastActiveAt); err != nil {
|
||||||
if err == pgx.ErrNoRows {
|
if err == pgx.ErrNoRows {
|
||||||
return thoughttypes.Project{}, err
|
return thoughttypes.Project{}, err
|
||||||
}
|
}
|
||||||
@@ -75,10 +75,10 @@ func scanProject(row pgx.Row) (thoughttypes.Project, error) {
|
|||||||
|
|
||||||
func (db *DB) ListProjects(ctx context.Context) ([]thoughttypes.ProjectSummary, error) {
|
func (db *DB) ListProjects(ctx context.Context) ([]thoughttypes.ProjectSummary, error) {
|
||||||
rows, err := db.pool.Query(ctx, `
|
rows, err := db.pool.Query(ctx, `
|
||||||
select p.guid, p.name, p.description, p.created_at, p.last_active_at, count(t.id) as thought_count
|
select p.id, p.guid, p.name, p.description, p.created_at, p.last_active_at, count(t.id) as thought_count
|
||||||
from projects p
|
from projects p
|
||||||
left join thoughts t on t.project_id = p.guid and t.archived_at is null
|
left join thoughts t on t.project_id = p.id and t.archived_at is null
|
||||||
group by p.guid, p.name, p.description, p.created_at, p.last_active_at
|
group by p.id, p.guid, p.name, p.description, p.created_at, p.last_active_at
|
||||||
order by p.last_active_at desc, p.created_at desc
|
order by p.last_active_at desc, p.created_at desc
|
||||||
`)
|
`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -90,7 +90,7 @@ func (db *DB) ListProjects(ctx context.Context) ([]thoughttypes.ProjectSummary,
|
|||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var model generatedmodels.ModelPublicProjects
|
var model generatedmodels.ModelPublicProjects
|
||||||
var thoughtCount int
|
var thoughtCount int
|
||||||
if err := rows.Scan(&model.GUID, &model.Name, &model.Description, &model.CreatedAt, &model.LastActiveAt, &thoughtCount); err != nil {
|
if err := rows.Scan(&model.ID, &model.GUID, &model.Name, &model.Description, &model.CreatedAt, &model.LastActiveAt, &thoughtCount); err != nil {
|
||||||
return nil, fmt.Errorf("scan project summary: %w", err)
|
return nil, fmt.Errorf("scan project summary: %w", err)
|
||||||
}
|
}
|
||||||
projects = append(projects, thoughttypes.ProjectSummary{
|
projects = append(projects, thoughttypes.ProjectSummary{
|
||||||
@@ -104,8 +104,8 @@ func (db *DB) ListProjects(ctx context.Context) ([]thoughttypes.ProjectSummary,
|
|||||||
return projects, nil
|
return projects, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) TouchProject(ctx context.Context, id uuid.UUID) error {
|
func (db *DB) TouchProject(ctx context.Context, id int64) error {
|
||||||
tag, err := db.pool.Exec(ctx, `update projects set last_active_at = now() where guid = $1`, id)
|
tag, err := db.pool.Exec(ctx, `update projects set last_active_at = now() where id = $1`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("touch project: %w", err)
|
return fmt.Errorf("touch project: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
||||||
ext "git.warky.dev/wdevs/amcs/internal/types"
|
ext "git.warky.dev/wdevs/amcs/internal/types"
|
||||||
)
|
)
|
||||||
@@ -20,21 +18,22 @@ func (db *DB) AddSkill(ctx context.Context, skill ext.AgentSkill) (ext.AgentSkil
|
|||||||
row := db.pool.QueryRow(ctx, `
|
row := db.pool.QueryRow(ctx, `
|
||||||
insert into agent_skills (name, description, content, tags)
|
insert into agent_skills (name, description, content, tags)
|
||||||
values ($1, $2, $3, $4)
|
values ($1, $2, $3, $4)
|
||||||
returning id, created_at, updated_at
|
returning id, guid, created_at, updated_at
|
||||||
`, skill.Name, skill.Description, skill.Content, skill.Tags)
|
`, skill.Name, skill.Description, skill.Content, skill.Tags)
|
||||||
|
|
||||||
created := skill
|
created := skill
|
||||||
var model generatedmodels.ModelPublicAgentSkills
|
var model generatedmodels.ModelPublicAgentSkills
|
||||||
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
if err := row.Scan(&model.ID, &model.GUID, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||||
return ext.AgentSkill{}, fmt.Errorf("insert agent skill: %w", err)
|
return ext.AgentSkill{}, fmt.Errorf("insert agent skill: %w", err)
|
||||||
}
|
}
|
||||||
created.ID = model.ID.UUID()
|
created.ID = model.ID.Int64()
|
||||||
|
created.GUID = model.GUID.UUID()
|
||||||
created.CreatedAt = model.CreatedAt.Time()
|
created.CreatedAt = model.CreatedAt.Time()
|
||||||
created.UpdatedAt = model.UpdatedAt.Time()
|
created.UpdatedAt = model.UpdatedAt.Time()
|
||||||
return created, nil
|
return created, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) RemoveSkill(ctx context.Context, id uuid.UUID) error {
|
func (db *DB) RemoveSkill(ctx context.Context, id int64) error {
|
||||||
tag, err := db.pool.Exec(ctx, `delete from agent_skills where id = $1`, id)
|
tag, err := db.pool.Exec(ctx, `delete from agent_skills where id = $1`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("delete agent skill: %w", err)
|
return fmt.Errorf("delete agent skill: %w", err)
|
||||||
@@ -68,7 +67,7 @@ func (db *DB) ListSkills(ctx context.Context, tag string) ([]ext.AgentSkill, err
|
|||||||
return nil, fmt.Errorf("scan agent skill: %w", err)
|
return nil, fmt.Errorf("scan agent skill: %w", err)
|
||||||
}
|
}
|
||||||
s := ext.AgentSkill{
|
s := ext.AgentSkill{
|
||||||
ID: model.ID.UUID(),
|
ID: model.ID.Int64(),
|
||||||
Name: model.Name.String(),
|
Name: model.Name.String(),
|
||||||
Description: model.Description.String(),
|
Description: model.Description.String(),
|
||||||
Content: model.Content.String(),
|
Content: model.Content.String(),
|
||||||
@@ -84,7 +83,7 @@ func (db *DB) ListSkills(ctx context.Context, tag string) ([]ext.AgentSkill, err
|
|||||||
return skills, rows.Err()
|
return skills, rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) GetSkill(ctx context.Context, id uuid.UUID) (ext.AgentSkill, error) {
|
func (db *DB) GetSkill(ctx context.Context, id int64) (ext.AgentSkill, error) {
|
||||||
row := db.pool.QueryRow(ctx, `
|
row := db.pool.QueryRow(ctx, `
|
||||||
select id, name, description, content, tags::text[], created_at, updated_at
|
select id, name, description, content, tags::text[], created_at, updated_at
|
||||||
from agent_skills where id = $1
|
from agent_skills where id = $1
|
||||||
@@ -96,7 +95,7 @@ func (db *DB) GetSkill(ctx context.Context, id uuid.UUID) (ext.AgentSkill, error
|
|||||||
return ext.AgentSkill{}, fmt.Errorf("get agent skill: %w", err)
|
return ext.AgentSkill{}, fmt.Errorf("get agent skill: %w", err)
|
||||||
}
|
}
|
||||||
s := ext.AgentSkill{
|
s := ext.AgentSkill{
|
||||||
ID: model.ID.UUID(),
|
ID: model.ID.Int64(),
|
||||||
Name: model.Name.String(),
|
Name: model.Name.String(),
|
||||||
Description: model.Description.String(),
|
Description: model.Description.String(),
|
||||||
Content: model.Content.String(),
|
Content: model.Content.String(),
|
||||||
@@ -122,21 +121,22 @@ func (db *DB) AddGuardrail(ctx context.Context, g ext.AgentGuardrail) (ext.Agent
|
|||||||
row := db.pool.QueryRow(ctx, `
|
row := db.pool.QueryRow(ctx, `
|
||||||
insert into agent_guardrails (name, description, content, severity, tags)
|
insert into agent_guardrails (name, description, content, severity, tags)
|
||||||
values ($1, $2, $3, $4, $5)
|
values ($1, $2, $3, $4, $5)
|
||||||
returning id, created_at, updated_at
|
returning id, guid, created_at, updated_at
|
||||||
`, g.Name, g.Description, g.Content, g.Severity, g.Tags)
|
`, g.Name, g.Description, g.Content, g.Severity, g.Tags)
|
||||||
|
|
||||||
created := g
|
created := g
|
||||||
var model generatedmodels.ModelPublicAgentGuardrails
|
var model generatedmodels.ModelPublicAgentGuardrails
|
||||||
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
if err := row.Scan(&model.ID, &model.GUID, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||||
return ext.AgentGuardrail{}, fmt.Errorf("insert agent guardrail: %w", err)
|
return ext.AgentGuardrail{}, fmt.Errorf("insert agent guardrail: %w", err)
|
||||||
}
|
}
|
||||||
created.ID = model.ID.UUID()
|
created.ID = model.ID.Int64()
|
||||||
|
created.GUID = model.GUID.UUID()
|
||||||
created.CreatedAt = model.CreatedAt.Time()
|
created.CreatedAt = model.CreatedAt.Time()
|
||||||
created.UpdatedAt = model.UpdatedAt.Time()
|
created.UpdatedAt = model.UpdatedAt.Time()
|
||||||
return created, nil
|
return created, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) RemoveGuardrail(ctx context.Context, id uuid.UUID) error {
|
func (db *DB) RemoveGuardrail(ctx context.Context, id int64) error {
|
||||||
tag, err := db.pool.Exec(ctx, `delete from agent_guardrails where id = $1`, id)
|
tag, err := db.pool.Exec(ctx, `delete from agent_guardrails where id = $1`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("delete agent guardrail: %w", err)
|
return fmt.Errorf("delete agent guardrail: %w", err)
|
||||||
@@ -180,7 +180,7 @@ func (db *DB) ListGuardrails(ctx context.Context, tag, severity string) ([]ext.A
|
|||||||
return nil, fmt.Errorf("scan agent guardrail: %w", err)
|
return nil, fmt.Errorf("scan agent guardrail: %w", err)
|
||||||
}
|
}
|
||||||
g := ext.AgentGuardrail{
|
g := ext.AgentGuardrail{
|
||||||
ID: model.ID.UUID(),
|
ID: model.ID.Int64(),
|
||||||
Name: model.Name.String(),
|
Name: model.Name.String(),
|
||||||
Description: model.Description.String(),
|
Description: model.Description.String(),
|
||||||
Content: model.Content.String(),
|
Content: model.Content.String(),
|
||||||
@@ -197,7 +197,7 @@ func (db *DB) ListGuardrails(ctx context.Context, tag, severity string) ([]ext.A
|
|||||||
return guardrails, rows.Err()
|
return guardrails, rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) GetGuardrail(ctx context.Context, id uuid.UUID) (ext.AgentGuardrail, error) {
|
func (db *DB) GetGuardrail(ctx context.Context, id int64) (ext.AgentGuardrail, error) {
|
||||||
row := db.pool.QueryRow(ctx, `
|
row := db.pool.QueryRow(ctx, `
|
||||||
select id, name, description, content, severity, tags::text[], created_at, updated_at
|
select id, name, description, content, severity, tags::text[], created_at, updated_at
|
||||||
from agent_guardrails where id = $1
|
from agent_guardrails where id = $1
|
||||||
@@ -209,7 +209,7 @@ func (db *DB) GetGuardrail(ctx context.Context, id uuid.UUID) (ext.AgentGuardrai
|
|||||||
return ext.AgentGuardrail{}, fmt.Errorf("get agent guardrail: %w", err)
|
return ext.AgentGuardrail{}, fmt.Errorf("get agent guardrail: %w", err)
|
||||||
}
|
}
|
||||||
g := ext.AgentGuardrail{
|
g := ext.AgentGuardrail{
|
||||||
ID: model.ID.UUID(),
|
ID: model.ID.Int64(),
|
||||||
Name: model.Name.String(),
|
Name: model.Name.String(),
|
||||||
Description: model.Description.String(),
|
Description: model.Description.String(),
|
||||||
Content: model.Content.String(),
|
Content: model.Content.String(),
|
||||||
@@ -226,7 +226,7 @@ func (db *DB) GetGuardrail(ctx context.Context, id uuid.UUID) (ext.AgentGuardrai
|
|||||||
|
|
||||||
// Project Skills
|
// Project Skills
|
||||||
|
|
||||||
func (db *DB) AddProjectSkill(ctx context.Context, projectID, skillID uuid.UUID) error {
|
func (db *DB) AddProjectSkill(ctx context.Context, projectID, skillID int64) error {
|
||||||
_, err := db.pool.Exec(ctx, `
|
_, err := db.pool.Exec(ctx, `
|
||||||
insert into project_skills (project_id, skill_id)
|
insert into project_skills (project_id, skill_id)
|
||||||
values ($1, $2)
|
values ($1, $2)
|
||||||
@@ -238,7 +238,7 @@ func (db *DB) AddProjectSkill(ctx context.Context, projectID, skillID uuid.UUID)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) RemoveProjectSkill(ctx context.Context, projectID, skillID uuid.UUID) error {
|
func (db *DB) RemoveProjectSkill(ctx context.Context, projectID, skillID int64) error {
|
||||||
tag, err := db.pool.Exec(ctx, `
|
tag, err := db.pool.Exec(ctx, `
|
||||||
delete from project_skills where project_id = $1 and skill_id = $2
|
delete from project_skills where project_id = $1 and skill_id = $2
|
||||||
`, projectID, skillID)
|
`, projectID, skillID)
|
||||||
@@ -251,7 +251,7 @@ func (db *DB) RemoveProjectSkill(ctx context.Context, projectID, skillID uuid.UU
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) ListProjectSkills(ctx context.Context, projectID uuid.UUID) ([]ext.AgentSkill, error) {
|
func (db *DB) ListProjectSkills(ctx context.Context, projectID int64) ([]ext.AgentSkill, error) {
|
||||||
rows, err := db.pool.Query(ctx, `
|
rows, err := db.pool.Query(ctx, `
|
||||||
select s.id, s.name, s.description, s.content, s.tags::text[], s.created_at, s.updated_at
|
select s.id, s.name, s.description, s.content, s.tags::text[], s.created_at, s.updated_at
|
||||||
from agent_skills s
|
from agent_skills s
|
||||||
@@ -272,7 +272,7 @@ func (db *DB) ListProjectSkills(ctx context.Context, projectID uuid.UUID) ([]ext
|
|||||||
return nil, fmt.Errorf("scan project skill: %w", err)
|
return nil, fmt.Errorf("scan project skill: %w", err)
|
||||||
}
|
}
|
||||||
s := ext.AgentSkill{
|
s := ext.AgentSkill{
|
||||||
ID: model.ID.UUID(),
|
ID: model.ID.Int64(),
|
||||||
Name: model.Name.String(),
|
Name: model.Name.String(),
|
||||||
Description: model.Description.String(),
|
Description: model.Description.String(),
|
||||||
Content: model.Content.String(),
|
Content: model.Content.String(),
|
||||||
@@ -290,7 +290,7 @@ func (db *DB) ListProjectSkills(ctx context.Context, projectID uuid.UUID) ([]ext
|
|||||||
|
|
||||||
// Project Guardrails
|
// Project Guardrails
|
||||||
|
|
||||||
func (db *DB) AddProjectGuardrail(ctx context.Context, projectID, guardrailID uuid.UUID) error {
|
func (db *DB) AddProjectGuardrail(ctx context.Context, projectID, guardrailID int64) error {
|
||||||
_, err := db.pool.Exec(ctx, `
|
_, err := db.pool.Exec(ctx, `
|
||||||
insert into project_guardrails (project_id, guardrail_id)
|
insert into project_guardrails (project_id, guardrail_id)
|
||||||
values ($1, $2)
|
values ($1, $2)
|
||||||
@@ -302,7 +302,7 @@ func (db *DB) AddProjectGuardrail(ctx context.Context, projectID, guardrailID uu
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) RemoveProjectGuardrail(ctx context.Context, projectID, guardrailID uuid.UUID) error {
|
func (db *DB) RemoveProjectGuardrail(ctx context.Context, projectID, guardrailID int64) error {
|
||||||
tag, err := db.pool.Exec(ctx, `
|
tag, err := db.pool.Exec(ctx, `
|
||||||
delete from project_guardrails where project_id = $1 and guardrail_id = $2
|
delete from project_guardrails where project_id = $1 and guardrail_id = $2
|
||||||
`, projectID, guardrailID)
|
`, projectID, guardrailID)
|
||||||
@@ -315,7 +315,7 @@ func (db *DB) RemoveProjectGuardrail(ctx context.Context, projectID, guardrailID
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) ListProjectGuardrails(ctx context.Context, projectID uuid.UUID) ([]ext.AgentGuardrail, error) {
|
func (db *DB) ListProjectGuardrails(ctx context.Context, projectID int64) ([]ext.AgentGuardrail, error) {
|
||||||
rows, err := db.pool.Query(ctx, `
|
rows, err := db.pool.Query(ctx, `
|
||||||
select g.id, g.name, g.description, g.content, g.severity, g.tags::text[], g.created_at, g.updated_at
|
select g.id, g.name, g.description, g.content, g.severity, g.tags::text[], g.created_at, g.updated_at
|
||||||
from agent_guardrails g
|
from agent_guardrails g
|
||||||
@@ -336,7 +336,7 @@ func (db *DB) ListProjectGuardrails(ctx context.Context, projectID uuid.UUID) ([
|
|||||||
return nil, fmt.Errorf("scan project guardrail: %w", err)
|
return nil, fmt.Errorf("scan project guardrail: %w", err)
|
||||||
}
|
}
|
||||||
g := ext.AgentGuardrail{
|
g := ext.AgentGuardrail{
|
||||||
ID: model.ID.UUID(),
|
ID: model.ID.Int64(),
|
||||||
Name: model.Name.String(),
|
Name: model.Name.String(),
|
||||||
Description: model.Description.String(),
|
Description: model.Description.String(),
|
||||||
Content: model.Content.String(),
|
Content: model.Content.String(),
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ func (db *DB) InsertThought(ctx context.Context, thought thoughttypes.Thought, e
|
|||||||
row := tx.QueryRow(ctx, `
|
row := tx.QueryRow(ctx, `
|
||||||
insert into thoughts (content, metadata, project_id)
|
insert into thoughts (content, metadata, project_id)
|
||||||
values ($1, $2::jsonb, $3)
|
values ($1, $2::jsonb, $3)
|
||||||
returning guid, created_at, updated_at
|
returning id, guid, created_at, updated_at
|
||||||
`, thought.Content, metadata, thought.ProjectID)
|
`, thought.Content, metadata, thought.ProjectID)
|
||||||
|
|
||||||
created := thought
|
created := thought
|
||||||
created.Embedding = nil
|
created.Embedding = nil
|
||||||
if err := row.Scan(&created.ID, &created.CreatedAt, &created.UpdatedAt); err != nil {
|
if err := row.Scan(&created.ID, &created.GUID, &created.CreatedAt, &created.UpdatedAt); err != nil {
|
||||||
return thoughttypes.Thought{}, fmt.Errorf("insert thought: %w", err)
|
return thoughttypes.Thought{}, fmt.Errorf("insert thought: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ func (db *DB) ListThoughts(ctx context.Context, filter thoughttypes.ListFilter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
select guid, content, metadata, project_id, archived_at, created_at, updated_at
|
select id, guid, content, metadata, project_id, archived_at, created_at, updated_at
|
||||||
from thoughts
|
from thoughts
|
||||||
`
|
`
|
||||||
if len(conditions) > 0 {
|
if len(conditions) > 0 {
|
||||||
@@ -151,7 +151,7 @@ func (db *DB) ListThoughts(ctx context.Context, filter thoughttypes.ListFilter)
|
|||||||
thoughts := make([]thoughttypes.Thought, 0, filter.Limit)
|
thoughts := make([]thoughttypes.Thought, 0, filter.Limit)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var model generatedmodels.ModelPublicThoughts
|
var model generatedmodels.ModelPublicThoughts
|
||||||
if err := rows.Scan(&model.GUID, &model.Content, &model.Metadata, &model.ProjectID, &model.ArchivedAt, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
if err := rows.Scan(&model.ID, &model.GUID, &model.Content, &model.Metadata, &model.ProjectID, &model.ArchivedAt, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||||
return nil, fmt.Errorf("scan listed thought: %w", err)
|
return nil, fmt.Errorf("scan listed thought: %w", err)
|
||||||
}
|
}
|
||||||
thought, err := thoughtFromModel(model)
|
thought, err := thoughtFromModel(model)
|
||||||
@@ -218,13 +218,13 @@ func (db *DB) Stats(ctx context.Context) (thoughttypes.ThoughtStats, error) {
|
|||||||
|
|
||||||
func (db *DB) GetThought(ctx context.Context, id uuid.UUID) (thoughttypes.Thought, error) {
|
func (db *DB) GetThought(ctx context.Context, id uuid.UUID) (thoughttypes.Thought, error) {
|
||||||
row := db.pool.QueryRow(ctx, `
|
row := db.pool.QueryRow(ctx, `
|
||||||
select guid, content, metadata, project_id, archived_at, created_at, updated_at
|
select id, guid, content, metadata, project_id, archived_at, created_at, updated_at
|
||||||
from thoughts
|
from thoughts
|
||||||
where guid = $1
|
where guid = $1
|
||||||
`, id)
|
`, id)
|
||||||
|
|
||||||
var model generatedmodels.ModelPublicThoughts
|
var model generatedmodels.ModelPublicThoughts
|
||||||
if err := row.Scan(&model.GUID, &model.Content, &model.Metadata, &model.ProjectID, &model.ArchivedAt, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
if err := row.Scan(&model.ID, &model.GUID, &model.Content, &model.Metadata, &model.ProjectID, &model.ArchivedAt, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||||
if err == pgx.ErrNoRows {
|
if err == pgx.ErrNoRows {
|
||||||
return thoughttypes.Thought{}, err
|
return thoughttypes.Thought{}, err
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,30 @@ func (db *DB) GetThought(ctx context.Context, id uuid.UUID) (thoughttypes.Though
|
|||||||
return thought, nil
|
return thought, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) UpdateThought(ctx context.Context, id uuid.UUID, content string, embedding []float32, embeddingModel string, metadata thoughttypes.ThoughtMetadata, projectID *uuid.UUID) (thoughttypes.Thought, error) {
|
func (db *DB) GetThoughtByID(ctx context.Context, id int64) (thoughttypes.Thought, error) {
|
||||||
|
row := db.pool.QueryRow(ctx, `
|
||||||
|
select id, guid, content, metadata, project_id, archived_at, created_at, updated_at
|
||||||
|
from thoughts
|
||||||
|
where id = $1
|
||||||
|
`, id)
|
||||||
|
|
||||||
|
var model generatedmodels.ModelPublicThoughts
|
||||||
|
if err := row.Scan(&model.ID, &model.GUID, &model.Content, &model.Metadata, &model.ProjectID, &model.ArchivedAt, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||||
|
if err == pgx.ErrNoRows {
|
||||||
|
return thoughttypes.Thought{}, err
|
||||||
|
}
|
||||||
|
return thoughttypes.Thought{}, fmt.Errorf("get thought by id: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
thought, err := thoughtFromModel(model)
|
||||||
|
if err != nil {
|
||||||
|
return thoughttypes.Thought{}, fmt.Errorf("map thought: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return thought, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) UpdateThought(ctx context.Context, id uuid.UUID, content string, embedding []float32, embeddingModel string, metadata thoughttypes.ThoughtMetadata, projectID *int64) (thoughttypes.Thought, error) {
|
||||||
metadataBytes, err := json.Marshal(metadata)
|
metadataBytes, err := json.Marshal(metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return thoughttypes.Thought{}, fmt.Errorf("marshal updated metadata: %w", err)
|
return thoughttypes.Thought{}, fmt.Errorf("marshal updated metadata: %w", err)
|
||||||
@@ -271,7 +294,7 @@ func (db *DB) UpdateThought(ctx context.Context, id uuid.UUID, content string, e
|
|||||||
if len(embedding) > 0 && embeddingModel != "" {
|
if len(embedding) > 0 && embeddingModel != "" {
|
||||||
if _, err := tx.Exec(ctx, `
|
if _, err := tx.Exec(ctx, `
|
||||||
insert into embeddings (thought_id, model, dim, embedding)
|
insert into embeddings (thought_id, model, dim, embedding)
|
||||||
values ($1, $2, $3, $4)
|
select id, $2, $3, $4 from thoughts where guid = $1
|
||||||
on conflict (thought_id, model) do update
|
on conflict (thought_id, model) do update
|
||||||
set embedding = excluded.embedding,
|
set embedding = excluded.embedding,
|
||||||
dim = excluded.dim,
|
dim = excluded.dim,
|
||||||
@@ -288,7 +311,7 @@ func (db *DB) UpdateThought(ctx context.Context, id uuid.UUID, content string, e
|
|||||||
return db.GetThought(ctx, id)
|
return db.GetThought(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) UpdateThoughtMetadata(ctx context.Context, id uuid.UUID, metadata thoughttypes.ThoughtMetadata) (thoughttypes.Thought, error) {
|
func (db *DB) UpdateThoughtMetadata(ctx context.Context, id int64, metadata thoughttypes.ThoughtMetadata) (thoughttypes.Thought, error) {
|
||||||
metadataBytes, err := json.Marshal(metadata)
|
metadataBytes, err := json.Marshal(metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return thoughttypes.Thought{}, fmt.Errorf("marshal updated metadata: %w", err)
|
return thoughttypes.Thought{}, fmt.Errorf("marshal updated metadata: %w", err)
|
||||||
@@ -298,7 +321,7 @@ func (db *DB) UpdateThoughtMetadata(ctx context.Context, id uuid.UUID, metadata
|
|||||||
update thoughts
|
update thoughts
|
||||||
set metadata = $2::jsonb,
|
set metadata = $2::jsonb,
|
||||||
updated_at = now()
|
updated_at = now()
|
||||||
where guid = $1
|
where id = $1
|
||||||
`, id, metadataBytes)
|
`, id, metadataBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return thoughttypes.Thought{}, fmt.Errorf("update thought metadata: %w", err)
|
return thoughttypes.Thought{}, fmt.Errorf("update thought metadata: %w", err)
|
||||||
@@ -307,7 +330,7 @@ func (db *DB) UpdateThoughtMetadata(ctx context.Context, id uuid.UUID, metadata
|
|||||||
return thoughttypes.Thought{}, pgx.ErrNoRows
|
return thoughttypes.Thought{}, pgx.ErrNoRows
|
||||||
}
|
}
|
||||||
|
|
||||||
return db.GetThought(ctx, id)
|
return db.GetThoughtByID(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) DeleteThought(ctx context.Context, id uuid.UUID) error {
|
func (db *DB) DeleteThought(ctx context.Context, id uuid.UUID) error {
|
||||||
@@ -332,7 +355,7 @@ func (db *DB) ArchiveThought(ctx context.Context, id uuid.UUID) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) RecentThoughts(ctx context.Context, projectID *uuid.UUID, limit int, days int) ([]thoughttypes.Thought, error) {
|
func (db *DB) RecentThoughts(ctx context.Context, projectID *int64, limit int, days int) ([]thoughttypes.Thought, error) {
|
||||||
filter := thoughttypes.ListFilter{
|
filter := thoughttypes.ListFilter{
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
ProjectID: projectID,
|
ProjectID: projectID,
|
||||||
@@ -342,7 +365,7 @@ func (db *DB) RecentThoughts(ctx context.Context, projectID *uuid.UUID, limit in
|
|||||||
return db.ListThoughts(ctx, filter)
|
return db.ListThoughts(ctx, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) ListThoughtsPendingMetadataRetry(ctx context.Context, limit int, projectID *uuid.UUID, includeArchived bool, olderThanDays int) ([]thoughttypes.Thought, error) {
|
func (db *DB) ListThoughtsPendingMetadataRetry(ctx context.Context, limit int, projectID *int64, includeArchived bool, olderThanDays int) ([]thoughttypes.Thought, error) {
|
||||||
args := make([]any, 0, 4)
|
args := make([]any, 0, 4)
|
||||||
conditions := []string{
|
conditions := []string{
|
||||||
"(metadata->>'metadata_status' = 'pending' or metadata->>'metadata_status' = 'failed')",
|
"(metadata->>'metadata_status' = 'pending' or metadata->>'metadata_status' = 'failed')",
|
||||||
@@ -361,7 +384,7 @@ func (db *DB) ListThoughtsPendingMetadataRetry(ctx context.Context, limit int, p
|
|||||||
}
|
}
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
select guid, content, metadata, project_id, archived_at, created_at, updated_at
|
select id, guid, content, metadata, project_id, archived_at, created_at, updated_at
|
||||||
from thoughts
|
from thoughts
|
||||||
where ` + strings.Join(conditions, " and ")
|
where ` + strings.Join(conditions, " and ")
|
||||||
|
|
||||||
@@ -376,12 +399,12 @@ func (db *DB) ListThoughtsPendingMetadataRetry(ctx context.Context, limit int, p
|
|||||||
|
|
||||||
thoughts := make([]thoughttypes.Thought, 0, limit)
|
thoughts := make([]thoughttypes.Thought, 0, limit)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var thought thoughttypes.Thought
|
var model generatedmodels.ModelPublicThoughts
|
||||||
var metadataBytes []byte
|
if err := rows.Scan(&model.ID, &model.GUID, &model.Content, &model.Metadata, &model.ProjectID, &model.ArchivedAt, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||||
if err := rows.Scan(&thought.ID, &thought.Content, &metadataBytes, &thought.ProjectID, &thought.ArchivedAt, &thought.CreatedAt, &thought.UpdatedAt); err != nil {
|
|
||||||
return nil, fmt.Errorf("scan pending metadata retry thought: %w", err)
|
return nil, fmt.Errorf("scan pending metadata retry thought: %w", err)
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(metadataBytes, &thought.Metadata); err != nil {
|
thought, err := thoughtFromModel(model)
|
||||||
|
if err != nil {
|
||||||
return nil, fmt.Errorf("decode pending metadata retry thought: %w", err)
|
return nil, fmt.Errorf("decode pending metadata retry thought: %w", err)
|
||||||
}
|
}
|
||||||
thoughts = append(thoughts, thought)
|
thoughts = append(thoughts, thought)
|
||||||
@@ -394,7 +417,7 @@ func (db *DB) ListThoughtsPendingMetadataRetry(ctx context.Context, limit int, p
|
|||||||
return thoughts, nil
|
return thoughts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) SearchSimilarThoughts(ctx context.Context, embedding []float32, embeddingModel string, threshold float64, limit int, projectID *uuid.UUID, excludeID *uuid.UUID) ([]thoughttypes.SearchResult, error) {
|
func (db *DB) SearchSimilarThoughts(ctx context.Context, embedding []float32, embeddingModel string, threshold float64, limit int, projectID *int64, excludeID *uuid.UUID) ([]thoughttypes.SearchResult, error) {
|
||||||
args := []any{pgvector.NewVector(embedding), threshold, embeddingModel}
|
args := []any{pgvector.NewVector(embedding), threshold, embeddingModel}
|
||||||
conditions := []string{
|
conditions := []string{
|
||||||
"t.archived_at is null",
|
"t.archived_at is null",
|
||||||
@@ -412,9 +435,9 @@ func (db *DB) SearchSimilarThoughts(ctx context.Context, embedding []float32, em
|
|||||||
args = append(args, limit)
|
args = append(args, limit)
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
select t.guid, t.content, t.metadata, 1 - (e.embedding <=> $1) as similarity, t.created_at
|
select t.id, t.content, t.metadata, 1 - (e.embedding <=> $1) as similarity, t.created_at
|
||||||
from thoughts t
|
from thoughts t
|
||||||
join embeddings e on e.thought_id = t.guid
|
join embeddings e on e.thought_id = t.id
|
||||||
where ` + strings.Join(conditions, " and ") + fmt.Sprintf(`
|
where ` + strings.Join(conditions, " and ") + fmt.Sprintf(`
|
||||||
order by e.embedding <=> $1
|
order by e.embedding <=> $1
|
||||||
limit $%d`, len(args))
|
limit $%d`, len(args))
|
||||||
@@ -443,7 +466,7 @@ func (db *DB) SearchSimilarThoughts(ctx context.Context, embedding []float32, em
|
|||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) HasEmbeddingsForModel(ctx context.Context, model string, projectID *uuid.UUID) (bool, error) {
|
func (db *DB) HasEmbeddingsForModel(ctx context.Context, model string, projectID *int64) (bool, error) {
|
||||||
args := []any{model}
|
args := []any{model}
|
||||||
conditions := []string{
|
conditions := []string{
|
||||||
"e.model = $1",
|
"e.model = $1",
|
||||||
@@ -454,7 +477,7 @@ func (db *DB) HasEmbeddingsForModel(ctx context.Context, model string, projectID
|
|||||||
conditions = append(conditions, fmt.Sprintf("t.project_id = $%d", len(args)))
|
conditions = append(conditions, fmt.Sprintf("t.project_id = $%d", len(args)))
|
||||||
}
|
}
|
||||||
|
|
||||||
query := `select exists(select 1 from embeddings e join thoughts t on t.guid = e.thought_id where ` +
|
query := `select exists(select 1 from embeddings e join thoughts t on t.id = e.thought_id where ` +
|
||||||
strings.Join(conditions, " and ") + `)`
|
strings.Join(conditions, " and ") + `)`
|
||||||
|
|
||||||
var exists bool
|
var exists bool
|
||||||
@@ -464,7 +487,7 @@ func (db *DB) HasEmbeddingsForModel(ctx context.Context, model string, projectID
|
|||||||
return exists, nil
|
return exists, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) ListThoughtsMissingEmbedding(ctx context.Context, model string, limit int, projectID *uuid.UUID, includeArchived bool, olderThanDays int) ([]thoughttypes.Thought, error) {
|
func (db *DB) ListThoughtsMissingEmbedding(ctx context.Context, model string, limit int, projectID *int64, includeArchived bool, olderThanDays int) ([]thoughttypes.Thought, error) {
|
||||||
args := []any{model}
|
args := []any{model}
|
||||||
conditions := []string{"e.id is null"}
|
conditions := []string{"e.id is null"}
|
||||||
|
|
||||||
@@ -482,9 +505,9 @@ func (db *DB) ListThoughtsMissingEmbedding(ctx context.Context, model string, li
|
|||||||
args = append(args, limit)
|
args = append(args, limit)
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
select t.guid, t.content, t.metadata, t.project_id, t.archived_at, t.created_at, t.updated_at
|
select t.id, t.guid, t.content, t.metadata, t.project_id, t.archived_at, t.created_at, t.updated_at
|
||||||
from thoughts t
|
from thoughts t
|
||||||
left join embeddings e on e.thought_id = t.guid and e.model = $1
|
left join embeddings e on e.thought_id = t.id and e.model = $1
|
||||||
where ` + strings.Join(conditions, " and ") + `
|
where ` + strings.Join(conditions, " and ") + `
|
||||||
order by t.created_at asc
|
order by t.created_at asc
|
||||||
limit $` + fmt.Sprintf("%d", len(args))
|
limit $` + fmt.Sprintf("%d", len(args))
|
||||||
@@ -497,12 +520,12 @@ func (db *DB) ListThoughtsMissingEmbedding(ctx context.Context, model string, li
|
|||||||
|
|
||||||
thoughts := make([]thoughttypes.Thought, 0, limit)
|
thoughts := make([]thoughttypes.Thought, 0, limit)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var thought thoughttypes.Thought
|
var model generatedmodels.ModelPublicThoughts
|
||||||
var metadataBytes []byte
|
if err := rows.Scan(&model.ID, &model.GUID, &model.Content, &model.Metadata, &model.ProjectID, &model.ArchivedAt, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||||
if err := rows.Scan(&thought.ID, &thought.Content, &metadataBytes, &thought.ProjectID, &thought.ArchivedAt, &thought.CreatedAt, &thought.UpdatedAt); err != nil {
|
|
||||||
return nil, fmt.Errorf("scan missing-embedding thought: %w", err)
|
return nil, fmt.Errorf("scan missing-embedding thought: %w", err)
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(metadataBytes, &thought.Metadata); err != nil {
|
thought, err := thoughtFromModel(model)
|
||||||
|
if err != nil {
|
||||||
return nil, fmt.Errorf("decode missing-embedding metadata: %w", err)
|
return nil, fmt.Errorf("decode missing-embedding metadata: %w", err)
|
||||||
}
|
}
|
||||||
thoughts = append(thoughts, thought)
|
thoughts = append(thoughts, thought)
|
||||||
@@ -513,7 +536,7 @@ func (db *DB) ListThoughtsMissingEmbedding(ctx context.Context, model string, li
|
|||||||
return thoughts, nil
|
return thoughts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) ListThoughtsForMetadataReparse(ctx context.Context, limit int, projectID *uuid.UUID, includeArchived bool, olderThanDays int) ([]thoughttypes.Thought, error) {
|
func (db *DB) ListThoughtsForMetadataReparse(ctx context.Context, limit int, projectID *int64, includeArchived bool, olderThanDays int) ([]thoughttypes.Thought, error) {
|
||||||
args := make([]any, 0, 3)
|
args := make([]any, 0, 3)
|
||||||
conditions := make([]string, 0, 4)
|
conditions := make([]string, 0, 4)
|
||||||
|
|
||||||
@@ -531,7 +554,7 @@ func (db *DB) ListThoughtsForMetadataReparse(ctx context.Context, limit int, pro
|
|||||||
args = append(args, limit)
|
args = append(args, limit)
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
select guid, content, metadata, project_id, archived_at, created_at, updated_at
|
select id, guid, content, metadata, project_id, archived_at, created_at, updated_at
|
||||||
from thoughts
|
from thoughts
|
||||||
`
|
`
|
||||||
if len(conditions) > 0 {
|
if len(conditions) > 0 {
|
||||||
@@ -547,12 +570,12 @@ func (db *DB) ListThoughtsForMetadataReparse(ctx context.Context, limit int, pro
|
|||||||
|
|
||||||
thoughts := make([]thoughttypes.Thought, 0, limit)
|
thoughts := make([]thoughttypes.Thought, 0, limit)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var thought thoughttypes.Thought
|
var model generatedmodels.ModelPublicThoughts
|
||||||
var metadataBytes []byte
|
if err := rows.Scan(&model.ID, &model.GUID, &model.Content, &model.Metadata, &model.ProjectID, &model.ArchivedAt, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||||
if err := rows.Scan(&thought.ID, &thought.Content, &metadataBytes, &thought.ProjectID, &thought.ArchivedAt, &thought.CreatedAt, &thought.UpdatedAt); err != nil {
|
|
||||||
return nil, fmt.Errorf("scan metadata-reparse thought: %w", err)
|
return nil, fmt.Errorf("scan metadata-reparse thought: %w", err)
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(metadataBytes, &thought.Metadata); err != nil {
|
thought, err := thoughtFromModel(model)
|
||||||
|
if err != nil {
|
||||||
return nil, fmt.Errorf("decode metadata-reparse thought metadata: %w", err)
|
return nil, fmt.Errorf("decode metadata-reparse thought metadata: %w", err)
|
||||||
}
|
}
|
||||||
thoughts = append(thoughts, thought)
|
thoughts = append(thoughts, thought)
|
||||||
@@ -564,7 +587,7 @@ func (db *DB) ListThoughtsForMetadataReparse(ctx context.Context, limit int, pro
|
|||||||
return thoughts, nil
|
return thoughts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) UpsertEmbedding(ctx context.Context, thoughtID uuid.UUID, model string, embedding []float32) error {
|
func (db *DB) UpsertEmbedding(ctx context.Context, thoughtID int64, model string, embedding []float32) error {
|
||||||
_, err := db.pool.Exec(ctx, `
|
_, err := db.pool.Exec(ctx, `
|
||||||
insert into embeddings (thought_id, model, dim, embedding)
|
insert into embeddings (thought_id, model, dim, embedding)
|
||||||
values ($1, $2, $3, $4)
|
values ($1, $2, $3, $4)
|
||||||
@@ -579,7 +602,7 @@ func (db *DB) UpsertEmbedding(ctx context.Context, thoughtID uuid.UUID, model st
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) SearchThoughtsText(ctx context.Context, query string, limit int, projectID *uuid.UUID, excludeID *uuid.UUID) ([]thoughttypes.SearchResult, error) {
|
func (db *DB) SearchThoughtsText(ctx context.Context, query string, limit int, projectID *int64, excludeID *uuid.UUID) ([]thoughttypes.SearchResult, error) {
|
||||||
args := []any{query}
|
args := []any{query}
|
||||||
conditions := []string{
|
conditions := []string{
|
||||||
"t.archived_at is null",
|
"t.archived_at is null",
|
||||||
@@ -596,11 +619,11 @@ func (db *DB) SearchThoughtsText(ctx context.Context, query string, limit int, p
|
|||||||
args = append(args, limit)
|
args = append(args, limit)
|
||||||
|
|
||||||
q := `
|
q := `
|
||||||
select t.guid, t.content, t.metadata,
|
select t.id, t.content, t.metadata,
|
||||||
ts_rank_cd(to_tsvector('simple', t.content) || to_tsvector('simple', coalesce(p.name, '')), websearch_to_tsquery('simple', $1)) as similarity,
|
ts_rank_cd(to_tsvector('simple', t.content) || to_tsvector('simple', coalesce(p.name, '')), websearch_to_tsquery('simple', $1)) as similarity,
|
||||||
t.created_at
|
t.created_at
|
||||||
from thoughts t
|
from thoughts t
|
||||||
left join projects p on t.project_id = p.guid
|
left join projects p on t.project_id = p.id
|
||||||
where ` + strings.Join(conditions, " and ") + `
|
where ` + strings.Join(conditions, " and ") + `
|
||||||
order by similarity desc
|
order by similarity desc
|
||||||
limit $` + fmt.Sprintf("%d", len(args))
|
limit $` + fmt.Sprintf("%d", len(args))
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package tools
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
"golang.org/x/sync/semaphore"
|
"golang.org/x/sync/semaphore"
|
||||||
|
|
||||||
@@ -53,11 +53,12 @@ func NewBackfillTool(db *store.DB, embeddings *ai.EmbeddingRunner, sessions *ses
|
|||||||
|
|
||||||
// QueueThought queues a single thought for background embedding generation.
|
// QueueThought queues a single thought for background embedding generation.
|
||||||
// It is used by capture when the embedding provider is temporarily unavailable.
|
// It is used by capture when the embedding provider is temporarily unavailable.
|
||||||
func (t *BackfillTool) QueueThought(ctx context.Context, id uuid.UUID, content string) {
|
func (t *BackfillTool) QueueThought(ctx context.Context, id int64, content string) {
|
||||||
go func() {
|
go func() {
|
||||||
started := time.Now()
|
started := time.Now()
|
||||||
|
idStr := fmt.Sprint(id)
|
||||||
t.logger.Info("background embedding started",
|
t.logger.Info("background embedding started",
|
||||||
slog.String("thought_id", id.String()),
|
slog.String("thought_id", idStr),
|
||||||
slog.String("provider", t.embeddings.PrimaryProvider()),
|
slog.String("provider", t.embeddings.PrimaryProvider()),
|
||||||
slog.String("model", t.embeddings.PrimaryModel()),
|
slog.String("model", t.embeddings.PrimaryModel()),
|
||||||
)
|
)
|
||||||
@@ -65,7 +66,7 @@ func (t *BackfillTool) QueueThought(ctx context.Context, id uuid.UUID, content s
|
|||||||
result, err := t.embeddings.Embed(ctx, content)
|
result, err := t.embeddings.Embed(ctx, content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.logger.Warn("background embedding error",
|
t.logger.Warn("background embedding error",
|
||||||
slog.String("thought_id", id.String()),
|
slog.String("thought_id", idStr),
|
||||||
slog.String("provider", t.embeddings.PrimaryProvider()),
|
slog.String("provider", t.embeddings.PrimaryProvider()),
|
||||||
slog.String("model", t.embeddings.PrimaryModel()),
|
slog.String("model", t.embeddings.PrimaryModel()),
|
||||||
slog.String("stage", "embed"),
|
slog.String("stage", "embed"),
|
||||||
@@ -76,7 +77,7 @@ func (t *BackfillTool) QueueThought(ctx context.Context, id uuid.UUID, content s
|
|||||||
}
|
}
|
||||||
if err := t.store.UpsertEmbedding(ctx, id, result.Model, result.Vector); err != nil {
|
if err := t.store.UpsertEmbedding(ctx, id, result.Model, result.Vector); err != nil {
|
||||||
t.logger.Warn("background embedding error",
|
t.logger.Warn("background embedding error",
|
||||||
slog.String("thought_id", id.String()),
|
slog.String("thought_id", idStr),
|
||||||
slog.String("provider", t.embeddings.PrimaryProvider()),
|
slog.String("provider", t.embeddings.PrimaryProvider()),
|
||||||
slog.String("model", result.Model),
|
slog.String("model", result.Model),
|
||||||
slog.String("stage", "upsert"),
|
slog.String("stage", "upsert"),
|
||||||
@@ -86,7 +87,7 @@ func (t *BackfillTool) QueueThought(ctx context.Context, id uuid.UUID, content s
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.logger.Info("background embedding complete",
|
t.logger.Info("background embedding complete",
|
||||||
slog.String("thought_id", id.String()),
|
slog.String("thought_id", idStr),
|
||||||
slog.String("provider", t.embeddings.PrimaryProvider()),
|
slog.String("provider", t.embeddings.PrimaryProvider()),
|
||||||
slog.String("model", result.Model),
|
slog.String("model", result.Model),
|
||||||
slog.Duration("duration", time.Since(started)),
|
slog.Duration("duration", time.Since(started)),
|
||||||
@@ -105,9 +106,9 @@ func (t *BackfillTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in
|
|||||||
return nil, BackfillOutput{}, err
|
return nil, BackfillOutput{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if project != nil {
|
if project != nil {
|
||||||
projectID = &project.ID
|
projectID = &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
primaryModel := t.embeddings.PrimaryModel()
|
primaryModel := t.embeddings.PrimaryModel()
|
||||||
@@ -140,24 +141,25 @@ func (t *BackfillTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(id uuid.UUID, content string) {
|
go func(id int64, content string) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
defer sem.Release(1)
|
defer sem.Release(1)
|
||||||
|
|
||||||
|
idStr := fmt.Sprint(id)
|
||||||
result, embedErr := t.embeddings.Embed(ctx, content)
|
result, embedErr := t.embeddings.Embed(ctx, content)
|
||||||
if embedErr != nil {
|
if embedErr != nil {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
out.Failures = append(out.Failures, BackfillFailure{ID: id.String(), Error: embedErr.Error()})
|
out.Failures = append(out.Failures, BackfillFailure{ID: idStr, Error: embedErr.Error()})
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
t.logger.Warn("backfill embed failed", slog.String("thought_id", id.String()), slog.String("error", embedErr.Error()))
|
t.logger.Warn("backfill embed failed", slog.String("thought_id", idStr), slog.String("error", embedErr.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if upsertErr := t.store.UpsertEmbedding(ctx, id, result.Model, result.Vector); upsertErr != nil {
|
if upsertErr := t.store.UpsertEmbedding(ctx, id, result.Model, result.Vector); upsertErr != nil {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
out.Failures = append(out.Failures, BackfillFailure{ID: id.String(), Error: upsertErr.Error()})
|
out.Failures = append(out.Failures, BackfillFailure{ID: idStr, Error: upsertErr.Error()})
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
t.logger.Warn("backfill upsert failed", slog.String("thought_id", id.String()), slog.String("error", upsertErr.Error()))
|
t.logger.Warn("backfill upsert failed", slog.String("thought_id", idStr), slog.String("error", upsertErr.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/ai"
|
"git.warky.dev/wdevs/amcs/internal/ai"
|
||||||
@@ -17,13 +16,13 @@ import (
|
|||||||
|
|
||||||
// EmbeddingQueuer queues a thought for background embedding generation.
|
// EmbeddingQueuer queues a thought for background embedding generation.
|
||||||
type EmbeddingQueuer interface {
|
type EmbeddingQueuer interface {
|
||||||
QueueThought(ctx context.Context, id uuid.UUID, content string)
|
QueueThought(ctx context.Context, id int64, content string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MetadataQueuer queues a thought for background metadata retry. Both
|
// MetadataQueuer queues a thought for background metadata retry. Both
|
||||||
// MetadataRetryer and EnrichmentRetryer satisfy this.
|
// MetadataRetryer and EnrichmentRetryer satisfy this.
|
||||||
type MetadataQueuer interface {
|
type MetadataQueuer interface {
|
||||||
QueueThought(id uuid.UUID)
|
QueueThought(id int64)
|
||||||
}
|
}
|
||||||
|
|
||||||
type CaptureTool struct {
|
type CaptureTool struct {
|
||||||
@@ -66,7 +65,7 @@ func (t *CaptureTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in C
|
|||||||
Metadata: rawMetadata,
|
Metadata: rawMetadata,
|
||||||
}
|
}
|
||||||
if project != nil {
|
if project != nil {
|
||||||
thought.ProjectID = &project.ID
|
thought.ProjectID = &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
created, err := t.store.InsertThought(ctx, thought, t.embeddings.PrimaryModel())
|
created, err := t.store.InsertThought(ctx, thought, t.embeddings.PrimaryModel())
|
||||||
@@ -74,7 +73,7 @@ func (t *CaptureTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in C
|
|||||||
return nil, CaptureOutput{}, err
|
return nil, CaptureOutput{}, err
|
||||||
}
|
}
|
||||||
if project != nil {
|
if project != nil {
|
||||||
_ = t.store.TouchProject(ctx, project.ID)
|
_ = t.store.TouchProject(ctx, project.NumericID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.retryer != nil {
|
if t.retryer != nil {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/session"
|
"git.warky.dev/wdevs/amcs/internal/session"
|
||||||
@@ -64,7 +63,7 @@ func (t *ChatHistoryTool) SaveChatHistory(ctx context.Context, req *mcp.CallTool
|
|||||||
h.Metadata = map[string]any{}
|
h.Metadata = map[string]any{}
|
||||||
}
|
}
|
||||||
if project != nil {
|
if project != nil {
|
||||||
h.ProjectID = &project.ID
|
h.ProjectID = &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
saved, err := t.store.SaveChatHistory(ctx, h)
|
saved, err := t.store.SaveChatHistory(ctx, h)
|
||||||
@@ -77,7 +76,7 @@ func (t *ChatHistoryTool) SaveChatHistory(ctx context.Context, req *mcp.CallTool
|
|||||||
// get_chat_history
|
// get_chat_history
|
||||||
|
|
||||||
type GetChatHistoryInput struct {
|
type GetChatHistoryInput struct {
|
||||||
ID string `json:"id,omitempty" jsonschema:"UUID of the saved chat history"`
|
ID string `json:"id,omitempty" jsonschema:"numeric id of the saved chat history"`
|
||||||
SessionID string `json:"session_id,omitempty" jsonschema:"original session_id — returns the most recent history for that session"`
|
SessionID string `json:"session_id,omitempty" jsonschema:"original session_id — returns the most recent history for that session"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,9 +90,9 @@ func (t *ChatHistoryTool) GetChatHistory(ctx context.Context, _ *mcp.CallToolReq
|
|||||||
}
|
}
|
||||||
|
|
||||||
if in.ID != "" {
|
if in.ID != "" {
|
||||||
id, err := uuid.Parse(in.ID)
|
id, err := parseID(in.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, GetChatHistoryOutput{}, errInvalidField("id", "invalid id", "must be a valid UUID")
|
return nil, GetChatHistoryOutput{}, errInvalidField("id", "invalid id", "must be a valid numeric id")
|
||||||
}
|
}
|
||||||
h, found, err := t.store.GetChatHistory(ctx, id)
|
h, found, err := t.store.GetChatHistory(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -145,7 +144,7 @@ func (t *ChatHistoryTool) ListChatHistories(ctx context.Context, req *mcp.CallTo
|
|||||||
return nil, ListChatHistoriesOutput{}, err
|
return nil, ListChatHistoriesOutput{}, err
|
||||||
}
|
}
|
||||||
if project != nil {
|
if project != nil {
|
||||||
filter.ProjectID = &project.ID
|
filter.ProjectID = &project.NumericID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +161,7 @@ func (t *ChatHistoryTool) ListChatHistories(ctx context.Context, req *mcp.CallTo
|
|||||||
// delete_chat_history
|
// delete_chat_history
|
||||||
|
|
||||||
type DeleteChatHistoryInput struct {
|
type DeleteChatHistoryInput struct {
|
||||||
ID uuid.UUID `json:"id" jsonschema:"UUID of the chat history to delete"`
|
ID string `json:"id" jsonschema:"numeric id of the chat history to delete"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeleteChatHistoryOutput struct {
|
type DeleteChatHistoryOutput struct {
|
||||||
@@ -170,7 +169,11 @@ type DeleteChatHistoryOutput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ChatHistoryTool) DeleteChatHistory(ctx context.Context, _ *mcp.CallToolRequest, in DeleteChatHistoryInput) (*mcp.CallToolResult, DeleteChatHistoryOutput, error) {
|
func (t *ChatHistoryTool) DeleteChatHistory(ctx context.Context, _ *mcp.CallToolRequest, in DeleteChatHistoryInput) (*mcp.CallToolResult, DeleteChatHistoryOutput, error) {
|
||||||
deleted, err := t.store.DeleteChatHistory(ctx, in.ID)
|
id, err := parseID(in.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, DeleteChatHistoryOutput{}, errInvalidField("id", "invalid id", "must be a valid numeric id")
|
||||||
|
}
|
||||||
|
deleted, err := t.store.DeleteChatHistory(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, DeleteChatHistoryOutput{}, err
|
return nil, DeleteChatHistoryOutput{}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func (t *ContextTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in P
|
|||||||
}
|
}
|
||||||
|
|
||||||
limit := normalizeLimit(in.Limit, t.search)
|
limit := normalizeLimit(in.Limit, t.search)
|
||||||
recent, err := t.store.RecentThoughts(ctx, &project.ID, limit, 0)
|
recent, err := t.store.RecentThoughts(ctx, &project.NumericID, limit, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ProjectContextOutput{}, err
|
return nil, ProjectContextOutput{}, err
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ func (t *ContextTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in P
|
|||||||
items := make([]ContextItem, 0, limit*2)
|
items := make([]ContextItem, 0, limit*2)
|
||||||
seen := map[string]struct{}{}
|
seen := map[string]struct{}{}
|
||||||
for _, thought := range recent {
|
for _, thought := range recent {
|
||||||
key := thought.ID.String()
|
key := fmt.Sprint(thought.ID)
|
||||||
seen[key] = struct{}{}
|
seen[key] = struct{}{}
|
||||||
items = append(items, ContextItem{
|
items = append(items, ContextItem{
|
||||||
ID: key,
|
ID: key,
|
||||||
@@ -72,12 +72,12 @@ func (t *ContextTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in P
|
|||||||
|
|
||||||
query := strings.TrimSpace(in.Query)
|
query := strings.TrimSpace(in.Query)
|
||||||
if query != "" {
|
if query != "" {
|
||||||
semantic, err := semanticSearch(ctx, t.store, t.embeddings, t.search, query, limit, t.search.DefaultThreshold, &project.ID, nil)
|
semantic, err := semanticSearch(ctx, t.store, t.embeddings, t.search, query, limit, t.search.DefaultThreshold, &project.NumericID, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ProjectContextOutput{}, err
|
return nil, ProjectContextOutput{}, err
|
||||||
}
|
}
|
||||||
for _, result := range semantic {
|
for _, result := range semantic {
|
||||||
key := result.ID.String()
|
key := fmt.Sprint(result.ID)
|
||||||
if _, ok := seen[key]; ok {
|
if _, ok := seen[key]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ func (t *ContextTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in P
|
|||||||
lines = append(lines, thoughtContextLine(i, item.Content, item.Metadata, item.Similarity))
|
lines = append(lines, thoughtContextLine(i, item.Content, item.Metadata, item.Similarity))
|
||||||
}
|
}
|
||||||
contextBlock := formatContextBlock(fmt.Sprintf("Project context for %s", project.Name), lines)
|
contextBlock := formatContextBlock(fmt.Sprintf("Project context for %s", project.Name), lines)
|
||||||
_ = t.store.TouchProject(ctx, project.ID)
|
_ = t.store.TouchProject(ctx, project.NumericID)
|
||||||
|
|
||||||
return nil, ProjectContextOutput{
|
return nil, ProjectContextOutput{
|
||||||
Project: *project,
|
Project: *project,
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package tools
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
"golang.org/x/sync/semaphore"
|
"golang.org/x/sync/semaphore"
|
||||||
|
|
||||||
@@ -89,18 +89,19 @@ func (t *RetryEnrichmentTool) Handle(ctx context.Context, req *mcp.CallToolReque
|
|||||||
return t.retryer.Handle(ctx, req, in)
|
return t.retryer.Handle(ctx, req, in)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *EnrichmentRetryer) QueueThought(id uuid.UUID) {
|
func (r *EnrichmentRetryer) QueueThought(id int64) {
|
||||||
go func() {
|
go func() {
|
||||||
started := time.Now()
|
started := time.Now()
|
||||||
|
idStr := fmt.Sprint(id)
|
||||||
r.logger.Info("background metadata started",
|
r.logger.Info("background metadata started",
|
||||||
slog.String("thought_id", id.String()),
|
slog.String("thought_id", idStr),
|
||||||
slog.String("provider", r.metadata.PrimaryProvider()),
|
slog.String("provider", r.metadata.PrimaryProvider()),
|
||||||
slog.String("model", r.metadata.PrimaryModel()),
|
slog.String("model", r.metadata.PrimaryModel()),
|
||||||
)
|
)
|
||||||
updated, err := r.retryOne(r.backgroundCtx, id)
|
updated, err := r.retryOne(r.backgroundCtx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Warn("background metadata error",
|
r.logger.Warn("background metadata error",
|
||||||
slog.String("thought_id", id.String()),
|
slog.String("thought_id", idStr),
|
||||||
slog.String("provider", r.metadata.PrimaryProvider()),
|
slog.String("provider", r.metadata.PrimaryProvider()),
|
||||||
slog.String("model", r.metadata.PrimaryModel()),
|
slog.String("model", r.metadata.PrimaryModel()),
|
||||||
slog.Duration("duration", time.Since(started)),
|
slog.Duration("duration", time.Since(started)),
|
||||||
@@ -109,7 +110,7 @@ func (r *EnrichmentRetryer) QueueThought(id uuid.UUID) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.logger.Info("background metadata complete",
|
r.logger.Info("background metadata complete",
|
||||||
slog.String("thought_id", id.String()),
|
slog.String("thought_id", idStr),
|
||||||
slog.String("provider", r.metadata.PrimaryProvider()),
|
slog.String("provider", r.metadata.PrimaryProvider()),
|
||||||
slog.String("model", r.metadata.PrimaryModel()),
|
slog.String("model", r.metadata.PrimaryModel()),
|
||||||
slog.Bool("updated", updated),
|
slog.Bool("updated", updated),
|
||||||
@@ -129,9 +130,9 @@ func (r *EnrichmentRetryer) Handle(ctx context.Context, req *mcp.CallToolRequest
|
|||||||
return nil, RetryEnrichmentOutput{}, err
|
return nil, RetryEnrichmentOutput{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if project != nil {
|
if project != nil {
|
||||||
projectID = &project.ID
|
projectID = &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
thoughts, err := r.store.ListThoughtsPendingMetadataRetry(ctx, limit, projectID, in.IncludeArchived, in.OlderThanDays)
|
thoughts, err := r.store.ListThoughtsPendingMetadataRetry(ctx, limit, projectID, in.IncludeArchived, in.OlderThanDays)
|
||||||
@@ -168,7 +169,7 @@ func (r *EnrichmentRetryer) Handle(ctx context.Context, req *mcp.CallToolRequest
|
|||||||
updated, err := r.retryOne(ctx, thought.ID)
|
updated, err := r.retryOne(ctx, thought.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
out.Failures = append(out.Failures, RetryEnrichmentFailure{ID: thought.ID.String(), Error: err.Error()})
|
out.Failures = append(out.Failures, RetryEnrichmentFailure{ID: fmt.Sprint(thought.ID), Error: err.Error()})
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -191,8 +192,8 @@ func (r *EnrichmentRetryer) Handle(ctx context.Context, req *mcp.CallToolRequest
|
|||||||
return nil, out, nil
|
return nil, out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *EnrichmentRetryer) retryOne(ctx context.Context, id uuid.UUID) (bool, error) {
|
func (r *EnrichmentRetryer) retryOne(ctx context.Context, id int64) (bool, error) {
|
||||||
thought, err := r.store.GetThought(ctx, id)
|
thought, err := r.store.GetThoughtByID(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -148,7 +149,7 @@ func (t *FilesTool) Upload(ctx context.Context, req *mcp.CallToolRequest, in Upl
|
|||||||
return nil, UploadFileOutput{}, err
|
return nil, UploadFileOutput{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
uri := fileURIPrefix + out.File.ID.String()
|
uri := fileURIPrefix + fmt.Sprint(out.File.ID)
|
||||||
return nil, UploadFileOutput{File: out.File, URI: uri}, nil
|
return nil, UploadFileOutput{File: out.File, URI: uri}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +248,7 @@ func (t *FilesTool) Load(ctx context.Context, _ *mcp.CallToolRequest, in LoadFil
|
|||||||
return nil, LoadFileOutput{}, err
|
return nil, LoadFileOutput{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
uri := fileURIPrefix + file.ID.String()
|
uri := fileURIPrefix + fmt.Sprint(file.ID)
|
||||||
result := &mcp.CallToolResult{
|
result := &mcp.CallToolResult{
|
||||||
Content: []mcp.Content{
|
Content: []mcp.Content{
|
||||||
&mcp.EmbeddedResource{
|
&mcp.EmbeddedResource{
|
||||||
@@ -294,7 +295,7 @@ func (t *FilesTool) List(ctx context.Context, req *mcp.CallToolRequest, in ListF
|
|||||||
return nil, ListFilesOutput{}, err
|
return nil, ListFilesOutput{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var thoughtID *uuid.UUID
|
var thoughtID *int64
|
||||||
if rawThoughtID := strings.TrimSpace(in.ThoughtID); rawThoughtID != "" {
|
if rawThoughtID := strings.TrimSpace(in.ThoughtID); rawThoughtID != "" {
|
||||||
parsedThoughtID, err := parseUUID(rawThoughtID)
|
parsedThoughtID, err := parseUUID(rawThoughtID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -304,12 +305,12 @@ func (t *FilesTool) List(ctx context.Context, req *mcp.CallToolRequest, in ListF
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ListFilesOutput{}, err
|
return nil, ListFilesOutput{}, err
|
||||||
}
|
}
|
||||||
thoughtID = &parsedThoughtID
|
thoughtID = &thought.ID
|
||||||
if project != nil && thought.ProjectID != nil && *thought.ProjectID != project.ID {
|
if project != nil && thought.ProjectID != nil && *thought.ProjectID != project.NumericID {
|
||||||
return nil, ListFilesOutput{}, errInvalidInput("project does not match the linked thought's project")
|
return nil, ListFilesOutput{}, errInvalidInput("project does not match the linked thought's project")
|
||||||
}
|
}
|
||||||
if project == nil && thought.ProjectID != nil {
|
if project == nil && thought.ProjectID != nil {
|
||||||
project = &thoughttypes.Project{ID: *thought.ProjectID}
|
project = &thoughttypes.Project{NumericID: *thought.ProjectID}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +324,7 @@ func (t *FilesTool) List(ctx context.Context, req *mcp.CallToolRequest, in ListF
|
|||||||
return nil, ListFilesOutput{}, err
|
return nil, ListFilesOutput{}, err
|
||||||
}
|
}
|
||||||
if project != nil {
|
if project != nil {
|
||||||
_ = t.store.TouchProject(ctx, project.ID)
|
_ = t.store.TouchProject(ctx, project.NumericID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, ListFilesOutput{Files: files}, nil
|
return nil, ListFilesOutput{Files: files}, nil
|
||||||
@@ -343,7 +344,7 @@ func (t *FilesTool) SaveDecoded(ctx context.Context, req *mcp.CallToolRequest, i
|
|||||||
return SaveFileOutput{}, err
|
return SaveFileOutput{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var thoughtID *uuid.UUID
|
var thoughtNumericID *int64
|
||||||
var projectID = projectIDPtr(project)
|
var projectID = projectIDPtr(project)
|
||||||
if rawThoughtID := strings.TrimSpace(in.ThoughtID); rawThoughtID != "" {
|
if rawThoughtID := strings.TrimSpace(in.ThoughtID); rawThoughtID != "" {
|
||||||
parsedThoughtID, err := parseUUID(rawThoughtID)
|
parsedThoughtID, err := parseUUID(rawThoughtID)
|
||||||
@@ -354,9 +355,9 @@ func (t *FilesTool) SaveDecoded(ctx context.Context, req *mcp.CallToolRequest, i
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return SaveFileOutput{}, err
|
return SaveFileOutput{}, err
|
||||||
}
|
}
|
||||||
thoughtID = &parsedThoughtID
|
thoughtNumericID = &thought.ID
|
||||||
projectID = thought.ProjectID
|
projectID = thought.ProjectID
|
||||||
if project != nil && thought.ProjectID != nil && *thought.ProjectID != project.ID {
|
if project != nil && thought.ProjectID != nil && *thought.ProjectID != project.NumericID {
|
||||||
return SaveFileOutput{}, errInvalidInput("project does not match the linked thought's project")
|
return SaveFileOutput{}, errInvalidInput("project does not match the linked thought's project")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -374,9 +375,7 @@ func (t *FilesTool) SaveDecoded(ctx context.Context, req *mcp.CallToolRequest, i
|
|||||||
SHA256: hex.EncodeToString(sum[:]),
|
SHA256: hex.EncodeToString(sum[:]),
|
||||||
Content: in.Content,
|
Content: in.Content,
|
||||||
ProjectID: projectID,
|
ProjectID: projectID,
|
||||||
}
|
ThoughtID: thoughtNumericID,
|
||||||
if thoughtID != nil {
|
|
||||||
file.ThoughtID = thoughtID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
created, err := t.store.InsertStoredFile(ctx, file)
|
created, err := t.store.InsertStoredFile(ctx, file)
|
||||||
@@ -398,7 +397,7 @@ func (t *FilesTool) SaveDecoded(ctx context.Context, req *mcp.CallToolRequest, i
|
|||||||
|
|
||||||
func thoughtAttachmentFromFile(file thoughttypes.StoredFile) thoughttypes.ThoughtAttachment {
|
func thoughtAttachmentFromFile(file thoughttypes.StoredFile) thoughttypes.ThoughtAttachment {
|
||||||
return thoughttypes.ThoughtAttachment{
|
return thoughttypes.ThoughtAttachment{
|
||||||
FileID: file.ID,
|
FileID: file.GUID,
|
||||||
Name: file.Name,
|
Name: file.Name,
|
||||||
MediaType: file.MediaType,
|
MediaType: file.MediaType,
|
||||||
Kind: file.Kind,
|
Kind: file.Kind,
|
||||||
@@ -498,11 +497,11 @@ func normalizeFileKind(explicit string, mediaType string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func projectIDPtr(project *thoughttypes.Project) *uuid.UUID {
|
func projectIDPtr(project *thoughttypes.Project) *int64 {
|
||||||
if project == nil {
|
if project == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &project.ID
|
return &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeFileLimit(limit int) int {
|
func normalizeFileLimit(limit int) int {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package tools
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@@ -34,6 +35,14 @@ func parseUUID(id string) (uuid.UUID, error) {
|
|||||||
return parsed, nil
|
return parsed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseID(id string) (int64, error) {
|
||||||
|
n, err := strconv.ParseInt(strings.TrimSpace(id), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("invalid numeric id %q", id)
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
func sessionID(req *mcp.CallToolRequest) (string, error) {
|
func sessionID(req *mcp.CallToolRequest) (string, error) {
|
||||||
if req == nil || req.Session == nil || req.Session.ID() == "" {
|
if req == nil || req.Session == nil || req.Session.ID() == "" {
|
||||||
return "", newMCPError(
|
return "", newMCPError(
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/config"
|
"git.warky.dev/wdevs/amcs/internal/config"
|
||||||
@@ -31,11 +30,11 @@ type AddLearningInput struct {
|
|||||||
SourceType string `json:"source_type,omitempty"`
|
SourceType string `json:"source_type,omitempty"`
|
||||||
SourceRef string `json:"source_ref,omitempty"`
|
SourceRef string `json:"source_ref,omitempty"`
|
||||||
Project string `json:"project,omitempty" jsonschema:"project name or id; falls back to active session project"`
|
Project string `json:"project,omitempty" jsonschema:"project name or id; falls back to active session project"`
|
||||||
RelatedThoughtID *uuid.UUID `json:"related_thought_id,omitempty"`
|
RelatedThoughtID *int64 `json:"related_thought_id,omitempty"`
|
||||||
RelatedSkillID *uuid.UUID `json:"related_skill_id,omitempty"`
|
RelatedSkillID *int64 `json:"related_skill_id,omitempty"`
|
||||||
ReviewedBy *string `json:"reviewed_by,omitempty"`
|
ReviewedBy *string `json:"reviewed_by,omitempty"`
|
||||||
DuplicateOfLearningID *uuid.UUID `json:"duplicate_of_learning_id,omitempty"`
|
DuplicateOfLearningID *int64 `json:"duplicate_of_learning_id,omitempty"`
|
||||||
SupersedesLearningID *uuid.UUID `json:"supersedes_learning_id,omitempty"`
|
SupersedesLearningID *int64 `json:"supersedes_learning_id,omitempty"`
|
||||||
Tags []string `json:"tags,omitempty"`
|
Tags []string `json:"tags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +43,7 @@ type AddLearningOutput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GetLearningInput struct {
|
type GetLearningInput struct {
|
||||||
ID uuid.UUID `json:"id" jsonschema:"learning id"`
|
ID int64 `json:"id" jsonschema:"learning id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetLearningOutput struct {
|
type GetLearningOutput struct {
|
||||||
@@ -105,7 +104,7 @@ func (t *LearningsTool) Add(ctx context.Context, req *mcp.CallToolRequest, in Ad
|
|||||||
learning.ActionRequired = *in.ActionRequired
|
learning.ActionRequired = *in.ActionRequired
|
||||||
}
|
}
|
||||||
if project != nil {
|
if project != nil {
|
||||||
learning.ProjectID = &project.ID
|
learning.ProjectID = &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
created, err := t.store.CreateLearning(ctx, learning)
|
created, err := t.store.CreateLearning(ctx, learning)
|
||||||
@@ -147,7 +146,7 @@ func (t *LearningsTool) List(ctx context.Context, req *mcp.CallToolRequest, in L
|
|||||||
Query: strings.TrimSpace(in.Query),
|
Query: strings.TrimSpace(in.Query),
|
||||||
}
|
}
|
||||||
if project != nil {
|
if project != nil {
|
||||||
filter.ProjectID = &project.ID
|
filter.ProjectID = &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
items, err := t.store.ListLearnings(ctx, filter)
|
items, err := t.store.ListLearnings(ctx, filter)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/mcperrors"
|
"git.warky.dev/wdevs/amcs/internal/mcperrors"
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLearningsAddRequiresSummary(t *testing.T) {
|
func TestLearningsAddRequiresSummary(t *testing.T) {
|
||||||
@@ -37,7 +36,7 @@ func TestLearningsMethodsRequireConfiguredStore(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get", func(t *testing.T) {
|
t.Run("get", func(t *testing.T) {
|
||||||
_, _, err := tool.Get(context.Background(), nil, GetLearningInput{ID: uuid.New()})
|
_, _, err := tool.Get(context.Background(), nil, GetLearningInput{ID: 0})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("Get() error = nil, want error")
|
t.Fatal("Get() error = nil, want error")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package tools
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
@@ -97,9 +98,9 @@ func (t *LinksTool) Related(ctx context.Context, _ *mcp.CallToolRequest, in Rela
|
|||||||
}
|
}
|
||||||
|
|
||||||
related := make([]RelatedThought, 0, len(linked)+t.search.DefaultLimit)
|
related := make([]RelatedThought, 0, len(linked)+t.search.DefaultLimit)
|
||||||
seen := map[string]struct{}{thought.ID.String(): {}}
|
seen := map[string]struct{}{fmt.Sprint(thought.ID): {}}
|
||||||
for _, item := range linked {
|
for _, item := range linked {
|
||||||
key := item.Thought.ID.String()
|
key := fmt.Sprint(item.Thought.ID)
|
||||||
seen[key] = struct{}{}
|
seen[key] = struct{}{}
|
||||||
related = append(related, RelatedThought{
|
related = append(related, RelatedThought{
|
||||||
ID: key,
|
ID: key,
|
||||||
@@ -117,12 +118,12 @@ func (t *LinksTool) Related(ctx context.Context, _ *mcp.CallToolRequest, in Rela
|
|||||||
}
|
}
|
||||||
|
|
||||||
if includeSemantic {
|
if includeSemantic {
|
||||||
semantic, err := semanticSearch(ctx, t.store, t.embeddings, t.search, thought.Content, t.search.DefaultLimit, t.search.DefaultThreshold, thought.ProjectID, &thought.ID)
|
semantic, err := semanticSearch(ctx, t.store, t.embeddings, t.search, thought.Content, t.search.DefaultLimit, t.search.DefaultThreshold, thought.ProjectID, &thought.GUID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, RelatedOutput{}, err
|
return nil, RelatedOutput{}, err
|
||||||
}
|
}
|
||||||
for _, item := range semantic {
|
for _, item := range semantic {
|
||||||
key := item.ID.String()
|
key := fmt.Sprint(item.ID)
|
||||||
if _, ok := seen[key]; ok {
|
if _, ok := seen[key]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/config"
|
"git.warky.dev/wdevs/amcs/internal/config"
|
||||||
@@ -43,9 +42,9 @@ func (t *ListTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in List
|
|||||||
return nil, ListOutput{}, err
|
return nil, ListOutput{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if project != nil {
|
if project != nil {
|
||||||
projectID = &project.ID
|
projectID = &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
thoughts, err := t.store.ListThoughts(ctx, thoughttypes.ListFilter{
|
thoughts, err := t.store.ListThoughts(ctx, thoughttypes.ListFilter{
|
||||||
@@ -61,7 +60,7 @@ func (t *ListTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in List
|
|||||||
return nil, ListOutput{}, err
|
return nil, ListOutput{}, err
|
||||||
}
|
}
|
||||||
if project != nil {
|
if project != nil {
|
||||||
_ = t.store.TouchProject(ctx, project.ID)
|
_ = t.store.TouchProject(ctx, project.NumericID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, ListOutput{Thoughts: thoughts}, nil
|
return nil, ListOutput{Thoughts: thoughts}, nil
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package tools
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
"golang.org/x/sync/semaphore"
|
"golang.org/x/sync/semaphore"
|
||||||
|
|
||||||
@@ -37,18 +37,18 @@ type RetryMetadataTool struct {
|
|||||||
|
|
||||||
type RetryLocker struct {
|
type RetryLocker struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
locks map[uuid.UUID]time.Time
|
locks map[int64]time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRetryLocker() *RetryLocker {
|
func NewRetryLocker() *RetryLocker {
|
||||||
return &RetryLocker{locks: map[uuid.UUID]time.Time{}}
|
return &RetryLocker{locks: map[int64]time.Time{}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *RetryLocker) Acquire(id uuid.UUID, ttl time.Duration) bool {
|
func (l *RetryLocker) Acquire(id int64, ttl time.Duration) bool {
|
||||||
l.mu.Lock()
|
l.mu.Lock()
|
||||||
defer l.mu.Unlock()
|
defer l.mu.Unlock()
|
||||||
if l.locks == nil {
|
if l.locks == nil {
|
||||||
l.locks = map[uuid.UUID]time.Time{}
|
l.locks = map[int64]time.Time{}
|
||||||
}
|
}
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
if exp, ok := l.locks[id]; ok && exp.After(now) {
|
if exp, ok := l.locks[id]; ok && exp.After(now) {
|
||||||
@@ -58,7 +58,7 @@ func (l *RetryLocker) Acquire(id uuid.UUID, ttl time.Duration) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *RetryLocker) Release(id uuid.UUID) {
|
func (l *RetryLocker) Release(id int64) {
|
||||||
l.mu.Lock()
|
l.mu.Lock()
|
||||||
defer l.mu.Unlock()
|
defer l.mu.Unlock()
|
||||||
delete(l.locks, id)
|
delete(l.locks, id)
|
||||||
@@ -111,23 +111,24 @@ func (t *RetryMetadataTool) Handle(ctx context.Context, req *mcp.CallToolRequest
|
|||||||
return t.retryer.Handle(ctx, req, in)
|
return t.retryer.Handle(ctx, req, in)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *MetadataRetryer) QueueThought(id uuid.UUID) {
|
func (r *MetadataRetryer) QueueThought(id int64) {
|
||||||
go func() {
|
go func() {
|
||||||
started := time.Now()
|
started := time.Now()
|
||||||
|
idStr := fmt.Sprint(id)
|
||||||
if !r.lock.Acquire(id, 15*time.Minute) {
|
if !r.lock.Acquire(id, 15*time.Minute) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer r.lock.Release(id)
|
defer r.lock.Release(id)
|
||||||
|
|
||||||
r.logger.Info("background metadata started",
|
r.logger.Info("background metadata started",
|
||||||
slog.String("thought_id", id.String()),
|
slog.String("thought_id", idStr),
|
||||||
slog.String("provider", r.metadata.PrimaryProvider()),
|
slog.String("provider", r.metadata.PrimaryProvider()),
|
||||||
slog.String("model", r.metadata.PrimaryModel()),
|
slog.String("model", r.metadata.PrimaryModel()),
|
||||||
)
|
)
|
||||||
updated, err := r.retryOne(r.backgroundCtx, id)
|
updated, err := r.retryOne(r.backgroundCtx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Warn("background metadata error",
|
r.logger.Warn("background metadata error",
|
||||||
slog.String("thought_id", id.String()),
|
slog.String("thought_id", idStr),
|
||||||
slog.String("provider", r.metadata.PrimaryProvider()),
|
slog.String("provider", r.metadata.PrimaryProvider()),
|
||||||
slog.String("model", r.metadata.PrimaryModel()),
|
slog.String("model", r.metadata.PrimaryModel()),
|
||||||
slog.Duration("duration", time.Since(started)),
|
slog.Duration("duration", time.Since(started)),
|
||||||
@@ -136,7 +137,7 @@ func (r *MetadataRetryer) QueueThought(id uuid.UUID) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.logger.Info("background metadata complete",
|
r.logger.Info("background metadata complete",
|
||||||
slog.String("thought_id", id.String()),
|
slog.String("thought_id", idStr),
|
||||||
slog.String("provider", r.metadata.PrimaryProvider()),
|
slog.String("provider", r.metadata.PrimaryProvider()),
|
||||||
slog.String("model", r.metadata.PrimaryModel()),
|
slog.String("model", r.metadata.PrimaryModel()),
|
||||||
slog.Bool("updated", updated),
|
slog.Bool("updated", updated),
|
||||||
@@ -156,9 +157,9 @@ func (r *MetadataRetryer) Handle(ctx context.Context, req *mcp.CallToolRequest,
|
|||||||
return nil, RetryMetadataOutput{}, err
|
return nil, RetryMetadataOutput{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if project != nil {
|
if project != nil {
|
||||||
projectID = &project.ID
|
projectID = &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
thoughts, err := r.store.ListThoughtsPendingMetadataRetry(ctx, limit, projectID, in.IncludeArchived, in.OlderThanDays)
|
thoughts, err := r.store.ListThoughtsPendingMetadataRetry(ctx, limit, projectID, in.IncludeArchived, in.OlderThanDays)
|
||||||
@@ -205,7 +206,7 @@ func (r *MetadataRetryer) Handle(ctx context.Context, req *mcp.CallToolRequest,
|
|||||||
r.lock.Release(thought.ID)
|
r.lock.Release(thought.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
out.Failures = append(out.Failures, RetryMetadataFailure{ID: thought.ID.String(), Error: err.Error()})
|
out.Failures = append(out.Failures, RetryMetadataFailure{ID: fmt.Sprint(thought.ID), Error: err.Error()})
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -228,8 +229,8 @@ func (r *MetadataRetryer) Handle(ctx context.Context, req *mcp.CallToolRequest,
|
|||||||
return nil, out, nil
|
return nil, out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *MetadataRetryer) retryOne(ctx context.Context, id uuid.UUID) (bool, error) {
|
func (r *MetadataRetryer) retryOne(ctx context.Context, id int64) (bool, error) {
|
||||||
thought, err := r.store.GetThought(ctx, id)
|
thought, err := r.store.GetThoughtByID(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/config"
|
"git.warky.dev/wdevs/amcs/internal/config"
|
||||||
@@ -27,15 +26,15 @@ func NewPlansTool(db *store.DB, sessions *session.ActiveProjects, cfg config.Sea
|
|||||||
// --- I/O types ---
|
// --- I/O types ---
|
||||||
|
|
||||||
type CreatePlanInput struct {
|
type CreatePlanInput struct {
|
||||||
Title string `json:"title" jsonschema:"plan title"`
|
Title string `json:"title" jsonschema:"plan title"`
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
Status string `json:"status,omitempty" jsonschema:"draft|active|blocked|completed|cancelled|superseded"`
|
Status string `json:"status,omitempty" jsonschema:"draft|active|blocked|completed|cancelled|superseded"`
|
||||||
Priority string `json:"priority,omitempty" jsonschema:"low|medium|high|critical"`
|
Priority string `json:"priority,omitempty" jsonschema:"low|medium|high|critical"`
|
||||||
Project string `json:"project,omitempty" jsonschema:"project name or id; falls back to active session project"`
|
Project string `json:"project,omitempty" jsonschema:"project name or id; falls back to active session project"`
|
||||||
Owner string `json:"owner,omitempty"`
|
Owner string `json:"owner,omitempty"`
|
||||||
DueDate string `json:"due_date,omitempty" jsonschema:"RFC3339 timestamp"`
|
DueDate string `json:"due_date,omitempty" jsonschema:"RFC3339 timestamp"`
|
||||||
SupersedesPlanID *uuid.UUID `json:"supersedes_plan_id,omitempty"`
|
SupersedesPlanID *int64 `json:"supersedes_plan_id,omitempty"`
|
||||||
Tags []string `json:"tags,omitempty"`
|
Tags []string `json:"tags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreatePlanOutput struct {
|
type CreatePlanOutput struct {
|
||||||
@@ -43,7 +42,7 @@ type CreatePlanOutput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GetPlanInput struct {
|
type GetPlanInput struct {
|
||||||
ID uuid.UUID `json:"id" jsonschema:"plan id"`
|
ID int64 `json:"id" jsonschema:"plan id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetPlanOutput struct {
|
type GetPlanOutput struct {
|
||||||
@@ -51,21 +50,21 @@ type GetPlanOutput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UpdatePlanInput struct {
|
type UpdatePlanInput struct {
|
||||||
ID uuid.UUID `json:"id" jsonschema:"plan id"`
|
ID int64 `json:"id" jsonschema:"plan id"`
|
||||||
Title string `json:"title,omitempty"`
|
Title string `json:"title,omitempty"`
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
Status string `json:"status,omitempty" jsonschema:"draft|active|blocked|completed|cancelled|superseded"`
|
Status string `json:"status,omitempty" jsonschema:"draft|active|blocked|completed|cancelled|superseded"`
|
||||||
Priority string `json:"priority,omitempty" jsonschema:"low|medium|high|critical"`
|
Priority string `json:"priority,omitempty" jsonschema:"low|medium|high|critical"`
|
||||||
Owner *string `json:"owner,omitempty" jsonschema:"empty string clears the owner"`
|
Owner *string `json:"owner,omitempty" jsonschema:"empty string clears the owner"`
|
||||||
DueDate string `json:"due_date,omitempty" jsonschema:"RFC3339; omit to keep, 'clear' to remove"`
|
DueDate string `json:"due_date,omitempty" jsonschema:"RFC3339; omit to keep, 'clear' to remove"`
|
||||||
ClearDueDate bool `json:"clear_due_date,omitempty"`
|
ClearDueDate bool `json:"clear_due_date,omitempty"`
|
||||||
CompletedAt string `json:"completed_at,omitempty" jsonschema:"RFC3339; omit to keep, 'clear' to remove"`
|
CompletedAt string `json:"completed_at,omitempty" jsonschema:"RFC3339; omit to keep, 'clear' to remove"`
|
||||||
ClearCompletedAt bool `json:"clear_completed_at,omitempty"`
|
ClearCompletedAt bool `json:"clear_completed_at,omitempty"`
|
||||||
ReviewedBy *string `json:"reviewed_by,omitempty" jsonschema:"empty string clears the reviewer"`
|
ReviewedBy *string `json:"reviewed_by,omitempty" jsonschema:"empty string clears the reviewer"`
|
||||||
MarkReviewed bool `json:"mark_reviewed,omitempty" jsonschema:"set last_reviewed_at to now"`
|
MarkReviewed bool `json:"mark_reviewed,omitempty" jsonschema:"set last_reviewed_at to now"`
|
||||||
SupersedesPlanID *uuid.UUID `json:"supersedes_plan_id,omitempty"`
|
SupersedesPlanID *int64 `json:"supersedes_plan_id,omitempty"`
|
||||||
ClearSupersedesPlanID bool `json:"clear_supersedes_plan_id,omitempty"`
|
ClearSupersedesPlanID bool `json:"clear_supersedes_plan_id,omitempty"`
|
||||||
Tags *[]string `json:"tags,omitempty" jsonschema:"replaces all tags when provided; pass [] to clear"`
|
Tags *[]string `json:"tags,omitempty" jsonschema:"replaces all tags when provided; pass [] to clear"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdatePlanOutput struct {
|
type UpdatePlanOutput struct {
|
||||||
@@ -73,7 +72,7 @@ type UpdatePlanOutput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DeletePlanInput struct {
|
type DeletePlanInput struct {
|
||||||
ID uuid.UUID `json:"id" jsonschema:"plan id"`
|
ID int64 `json:"id" jsonschema:"plan id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeletePlanOutput struct {
|
type DeletePlanOutput struct {
|
||||||
@@ -95,13 +94,13 @@ type ListPlansOutput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PlanDependencyInput struct {
|
type PlanDependencyInput struct {
|
||||||
PlanID uuid.UUID `json:"plan_id" jsonschema:"the plan that depends on another"`
|
PlanID int64 `json:"plan_id" jsonschema:"the plan that depends on another"`
|
||||||
DependsOnPlanID uuid.UUID `json:"depends_on_plan_id" jsonschema:"the plan that must complete first"`
|
DependsOnPlanID int64 `json:"depends_on_plan_id" jsonschema:"the plan that must complete first"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlanRelatedInput struct {
|
type PlanRelatedInput struct {
|
||||||
PlanAID uuid.UUID `json:"plan_a_id"`
|
PlanAID int64 `json:"plan_a_id"`
|
||||||
PlanBID uuid.UUID `json:"plan_b_id"`
|
PlanBID int64 `json:"plan_b_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlanLinkOutput struct {
|
type PlanLinkOutput struct {
|
||||||
@@ -109,12 +108,12 @@ type PlanLinkOutput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PlanSkillInput struct {
|
type PlanSkillInput struct {
|
||||||
PlanID uuid.UUID `json:"plan_id"`
|
PlanID int64 `json:"plan_id"`
|
||||||
SkillID uuid.UUID `json:"skill_id"`
|
SkillID int64 `json:"skill_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListPlanSkillsInput struct {
|
type ListPlanSkillsInput struct {
|
||||||
PlanID uuid.UUID `json:"plan_id"`
|
PlanID int64 `json:"plan_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListPlanSkillsOutput struct {
|
type ListPlanSkillsOutput struct {
|
||||||
@@ -122,12 +121,12 @@ type ListPlanSkillsOutput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PlanGuardrailInput struct {
|
type PlanGuardrailInput struct {
|
||||||
PlanID uuid.UUID `json:"plan_id"`
|
PlanID int64 `json:"plan_id"`
|
||||||
GuardrailID uuid.UUID `json:"guardrail_id"`
|
GuardrailID int64 `json:"guardrail_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListPlanGuardrailsInput struct {
|
type ListPlanGuardrailsInput struct {
|
||||||
PlanID uuid.UUID `json:"plan_id"`
|
PlanID int64 `json:"plan_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListPlanGuardrailsOutput struct {
|
type ListPlanGuardrailsOutput struct {
|
||||||
@@ -157,7 +156,7 @@ func (t *PlansTool) Create(ctx context.Context, req *mcp.CallToolRequest, in Cre
|
|||||||
Tags: normalizeStringSlice(in.Tags),
|
Tags: normalizeStringSlice(in.Tags),
|
||||||
}
|
}
|
||||||
if project != nil {
|
if project != nil {
|
||||||
plan.ProjectID = &project.ID
|
plan.ProjectID = &project.NumericID
|
||||||
}
|
}
|
||||||
if v := strings.TrimSpace(in.DueDate); v != "" {
|
if v := strings.TrimSpace(in.DueDate); v != "" {
|
||||||
t, err := time.Parse(time.RFC3339, v)
|
t, err := time.Parse(time.RFC3339, v)
|
||||||
@@ -249,7 +248,7 @@ func (t *PlansTool) List(ctx context.Context, req *mcp.CallToolRequest, in ListP
|
|||||||
Query: strings.TrimSpace(in.Query),
|
Query: strings.TrimSpace(in.Query),
|
||||||
}
|
}
|
||||||
if project != nil {
|
if project != nil {
|
||||||
filter.ProjectID = &project.ID
|
filter.ProjectID = &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
plans, err := t.store.ListPlans(ctx, filter)
|
plans, err := t.store.ListPlans(ctx, filter)
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ func (t *ProjectsTool) SetActive(ctx context.Context, req *mcp.CallToolRequest,
|
|||||||
return nil, SetActiveProjectOutput{}, err
|
return nil, SetActiveProjectOutput{}, err
|
||||||
}
|
}
|
||||||
t.sessions.Set(sid, project.ID)
|
t.sessions.Set(sid, project.ID)
|
||||||
_ = t.store.TouchProject(ctx, project.ID)
|
_ = t.store.TouchProject(ctx, project.NumericID)
|
||||||
return nil, SetActiveProjectOutput{Project: *project}, nil
|
return nil, SetActiveProjectOutput{Project: *project}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/ai"
|
"git.warky.dev/wdevs/amcs/internal/ai"
|
||||||
@@ -49,9 +48,9 @@ func (t *RecallTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in Re
|
|||||||
|
|
||||||
limit := normalizeLimit(in.Limit, t.search)
|
limit := normalizeLimit(in.Limit, t.search)
|
||||||
|
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if project != nil {
|
if project != nil {
|
||||||
projectID = &project.ID
|
projectID = &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
semantic, err := semanticSearch(ctx, t.store, t.embeddings, t.search, query, limit, t.search.DefaultThreshold, projectID, nil)
|
semantic, err := semanticSearch(ctx, t.store, t.embeddings, t.search, query, limit, t.search.DefaultThreshold, projectID, nil)
|
||||||
@@ -66,7 +65,7 @@ func (t *RecallTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in Re
|
|||||||
items := make([]ContextItem, 0, limit*2)
|
items := make([]ContextItem, 0, limit*2)
|
||||||
seen := map[string]struct{}{}
|
seen := map[string]struct{}{}
|
||||||
for _, result := range semantic {
|
for _, result := range semantic {
|
||||||
key := result.ID.String()
|
key := fmt.Sprint(result.ID)
|
||||||
seen[key] = struct{}{}
|
seen[key] = struct{}{}
|
||||||
items = append(items, ContextItem{
|
items = append(items, ContextItem{
|
||||||
ID: key,
|
ID: key,
|
||||||
@@ -77,7 +76,7 @@ func (t *RecallTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in Re
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
for _, thought := range recent {
|
for _, thought := range recent {
|
||||||
key := thought.ID.String()
|
key := fmt.Sprint(thought.ID)
|
||||||
if _, ok := seen[key]; ok {
|
if _, ok := seen[key]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -97,7 +96,7 @@ func (t *RecallTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in Re
|
|||||||
header := "Recalled context"
|
header := "Recalled context"
|
||||||
if project != nil {
|
if project != nil {
|
||||||
header = fmt.Sprintf("Recalled context for %s", project.Name)
|
header = fmt.Sprintf("Recalled context for %s", project.Name)
|
||||||
_ = t.store.TouchProject(ctx, project.ID)
|
_ = t.store.TouchProject(ctx, project.NumericID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, RecallOutput{
|
return nil, RecallOutput{
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package tools
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
"golang.org/x/sync/semaphore"
|
"golang.org/x/sync/semaphore"
|
||||||
|
|
||||||
@@ -68,9 +68,9 @@ func (t *ReparseMetadataTool) Handle(ctx context.Context, req *mcp.CallToolReque
|
|||||||
return nil, ReparseMetadataOutput{}, err
|
return nil, ReparseMetadataOutput{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if project != nil {
|
if project != nil {
|
||||||
projectID = &project.ID
|
projectID = &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
thoughts, err := t.store.ListThoughtsForMetadataReparse(ctx, limit, projectID, in.IncludeArchived, in.OlderThanDays)
|
thoughts, err := t.store.ListThoughtsForMetadataReparse(ctx, limit, projectID, in.IncludeArchived, in.OlderThanDays)
|
||||||
@@ -114,7 +114,7 @@ func (t *ReparseMetadataTool) Handle(ctx context.Context, req *mcp.CallToolReque
|
|||||||
mu.Lock()
|
mu.Lock()
|
||||||
out.Normalized++
|
out.Normalized++
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
t.logger.Warn("metadata reparse extract failed, using normalized existing metadata", slog.String("thought_id", thought.ID.String()), slog.String("error", extractErr.Error()))
|
t.logger.Warn("metadata reparse extract failed, using normalized existing metadata", slog.String("thought_id", fmt.Sprint(thought.ID)), slog.String("error", extractErr.Error()))
|
||||||
} else {
|
} else {
|
||||||
normalizedTarget = metadata.MarkMetadataComplete(metadata.SanitizeExtracted(extracted), t.capture, attemptedAt)
|
normalizedTarget = metadata.MarkMetadataComplete(metadata.SanitizeExtracted(extracted), t.capture, attemptedAt)
|
||||||
normalizedTarget.Attachments = thought.Metadata.Attachments
|
normalizedTarget.Attachments = thought.Metadata.Attachments
|
||||||
@@ -130,11 +130,11 @@ func (t *ReparseMetadataTool) Handle(ctx context.Context, req *mcp.CallToolReque
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, updateErr := t.store.UpdateThought(ctx, thought.ID, thought.Content, nil, "", normalizedTarget, thought.ProjectID); updateErr != nil {
|
if _, updateErr := t.store.UpdateThought(ctx, thought.GUID, thought.Content, nil, "", normalizedTarget, thought.ProjectID); updateErr != nil {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
out.Failures = append(out.Failures, ReparseMetadataFailure{ID: thought.ID.String(), Error: updateErr.Error()})
|
out.Failures = append(out.Failures, ReparseMetadataFailure{ID: fmt.Sprint(thought.ID), Error: updateErr.Error()})
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
t.logger.Warn("metadata reparse update failed", slog.String("thought_id", thought.ID.String()), slog.String("error", updateErr.Error()))
|
t.logger.Warn("metadata reparse update failed", slog.String("thought_id", fmt.Sprint(thought.ID)), slog.String("error", updateErr.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func semanticSearch(
|
|||||||
query string,
|
query string,
|
||||||
limit int,
|
limit int,
|
||||||
threshold float64,
|
threshold float64,
|
||||||
projectID *uuid.UUID,
|
projectID *int64,
|
||||||
excludeID *uuid.UUID,
|
excludeID *uuid.UUID,
|
||||||
) ([]thoughttypes.SearchResult, error) {
|
) ([]thoughttypes.SearchResult, error) {
|
||||||
model := embeddings.PrimaryModel()
|
model := embeddings.PrimaryModel()
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/ai"
|
"git.warky.dev/wdevs/amcs/internal/ai"
|
||||||
@@ -50,10 +49,10 @@ func (t *SearchTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in Se
|
|||||||
return nil, SearchOutput{}, err
|
return nil, SearchOutput{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if project != nil {
|
if project != nil {
|
||||||
projectID = &project.ID
|
projectID = &project.NumericID
|
||||||
_ = t.store.TouchProject(ctx, project.ID)
|
_ = t.store.TouchProject(ctx, project.NumericID)
|
||||||
}
|
}
|
||||||
|
|
||||||
results, err := semanticSearch(ctx, t.store, t.embeddings, t.search, query, limit, threshold, projectID, nil)
|
results, err := semanticSearch(ctx, t.store, t.embeddings, t.search, query, limit, threshold, projectID, nil)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/session"
|
"git.warky.dev/wdevs/amcs/internal/session"
|
||||||
@@ -59,7 +58,7 @@ func (t *SkillsTool) AddSkill(ctx context.Context, _ *mcp.CallToolRequest, in Ad
|
|||||||
// remove_skill
|
// remove_skill
|
||||||
|
|
||||||
type RemoveSkillInput struct {
|
type RemoveSkillInput struct {
|
||||||
ID uuid.UUID `json:"id" jsonschema:"skill id to remove"`
|
ID int64 `json:"id" jsonschema:"skill id to remove"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoveSkillOutput struct {
|
type RemoveSkillOutput struct {
|
||||||
@@ -147,7 +146,7 @@ func (t *SkillsTool) AddGuardrail(ctx context.Context, _ *mcp.CallToolRequest, i
|
|||||||
// remove_guardrail
|
// remove_guardrail
|
||||||
|
|
||||||
type RemoveGuardrailInput struct {
|
type RemoveGuardrailInput struct {
|
||||||
ID uuid.UUID `json:"id" jsonschema:"guardrail id to remove"`
|
ID int64 `json:"id" jsonschema:"guardrail id to remove"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoveGuardrailOutput struct {
|
type RemoveGuardrailOutput struct {
|
||||||
@@ -186,13 +185,13 @@ func (t *SkillsTool) ListGuardrails(ctx context.Context, _ *mcp.CallToolRequest,
|
|||||||
// add_project_skill
|
// add_project_skill
|
||||||
|
|
||||||
type AddProjectSkillInput struct {
|
type AddProjectSkillInput struct {
|
||||||
Project string `json:"project,omitempty" jsonschema:"project name or id (uses active project if omitted)"`
|
Project string `json:"project,omitempty" jsonschema:"project name or id (uses active project if omitted)"`
|
||||||
SkillID uuid.UUID `json:"skill_id" jsonschema:"skill id to link"`
|
SkillID int64 `json:"skill_id" jsonschema:"skill id to link"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddProjectSkillOutput struct {
|
type AddProjectSkillOutput struct {
|
||||||
ProjectID uuid.UUID `json:"project_id"`
|
ProjectID int64 `json:"project_id"`
|
||||||
SkillID uuid.UUID `json:"skill_id"`
|
SkillID int64 `json:"skill_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *SkillsTool) AddProjectSkill(ctx context.Context, req *mcp.CallToolRequest, in AddProjectSkillInput) (*mcp.CallToolResult, AddProjectSkillOutput, error) {
|
func (t *SkillsTool) AddProjectSkill(ctx context.Context, req *mcp.CallToolRequest, in AddProjectSkillInput) (*mcp.CallToolResult, AddProjectSkillOutput, error) {
|
||||||
@@ -200,17 +199,17 @@ func (t *SkillsTool) AddProjectSkill(ctx context.Context, req *mcp.CallToolReque
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, AddProjectSkillOutput{}, err
|
return nil, AddProjectSkillOutput{}, err
|
||||||
}
|
}
|
||||||
if err := t.store.AddProjectSkill(ctx, project.ID, in.SkillID); err != nil {
|
if err := t.store.AddProjectSkill(ctx, project.NumericID, in.SkillID); err != nil {
|
||||||
return nil, AddProjectSkillOutput{}, err
|
return nil, AddProjectSkillOutput{}, err
|
||||||
}
|
}
|
||||||
return nil, AddProjectSkillOutput{ProjectID: project.ID, SkillID: in.SkillID}, nil
|
return nil, AddProjectSkillOutput{ProjectID: project.NumericID, SkillID: in.SkillID}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove_project_skill
|
// remove_project_skill
|
||||||
|
|
||||||
type RemoveProjectSkillInput struct {
|
type RemoveProjectSkillInput struct {
|
||||||
Project string `json:"project,omitempty" jsonschema:"project name or id (uses active project if omitted)"`
|
Project string `json:"project,omitempty" jsonschema:"project name or id (uses active project if omitted)"`
|
||||||
SkillID uuid.UUID `json:"skill_id" jsonschema:"skill id to unlink"`
|
SkillID int64 `json:"skill_id" jsonschema:"skill id to unlink"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoveProjectSkillOutput struct {
|
type RemoveProjectSkillOutput struct {
|
||||||
@@ -222,7 +221,7 @@ func (t *SkillsTool) RemoveProjectSkill(ctx context.Context, req *mcp.CallToolRe
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, RemoveProjectSkillOutput{}, err
|
return nil, RemoveProjectSkillOutput{}, err
|
||||||
}
|
}
|
||||||
if err := t.store.RemoveProjectSkill(ctx, project.ID, in.SkillID); err != nil {
|
if err := t.store.RemoveProjectSkill(ctx, project.NumericID, in.SkillID); err != nil {
|
||||||
return nil, RemoveProjectSkillOutput{}, err
|
return nil, RemoveProjectSkillOutput{}, err
|
||||||
}
|
}
|
||||||
return nil, RemoveProjectSkillOutput{Removed: true}, nil
|
return nil, RemoveProjectSkillOutput{Removed: true}, nil
|
||||||
@@ -235,7 +234,7 @@ type ListProjectSkillsInput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ListProjectSkillsOutput struct {
|
type ListProjectSkillsOutput struct {
|
||||||
ProjectID uuid.UUID `json:"project_id"`
|
ProjectID int64 `json:"project_id"`
|
||||||
Skills []ext.AgentSkill `json:"skills"`
|
Skills []ext.AgentSkill `json:"skills"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,26 +243,26 @@ func (t *SkillsTool) ListProjectSkills(ctx context.Context, req *mcp.CallToolReq
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ListProjectSkillsOutput{}, err
|
return nil, ListProjectSkillsOutput{}, err
|
||||||
}
|
}
|
||||||
skills, err := t.store.ListProjectSkills(ctx, project.ID)
|
skills, err := t.store.ListProjectSkills(ctx, project.NumericID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ListProjectSkillsOutput{}, err
|
return nil, ListProjectSkillsOutput{}, err
|
||||||
}
|
}
|
||||||
if skills == nil {
|
if skills == nil {
|
||||||
skills = []ext.AgentSkill{}
|
skills = []ext.AgentSkill{}
|
||||||
}
|
}
|
||||||
return nil, ListProjectSkillsOutput{ProjectID: project.ID, Skills: skills}, nil
|
return nil, ListProjectSkillsOutput{ProjectID: project.NumericID, Skills: skills}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// add_project_guardrail
|
// add_project_guardrail
|
||||||
|
|
||||||
type AddProjectGuardrailInput struct {
|
type AddProjectGuardrailInput struct {
|
||||||
Project string `json:"project,omitempty" jsonschema:"project name or id (uses active project if omitted)"`
|
Project string `json:"project,omitempty" jsonschema:"project name or id (uses active project if omitted)"`
|
||||||
GuardrailID uuid.UUID `json:"guardrail_id" jsonschema:"guardrail id to link"`
|
GuardrailID int64 `json:"guardrail_id" jsonschema:"guardrail id to link"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddProjectGuardrailOutput struct {
|
type AddProjectGuardrailOutput struct {
|
||||||
ProjectID uuid.UUID `json:"project_id"`
|
ProjectID int64 `json:"project_id"`
|
||||||
GuardrailID uuid.UUID `json:"guardrail_id"`
|
GuardrailID int64 `json:"guardrail_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *SkillsTool) AddProjectGuardrail(ctx context.Context, req *mcp.CallToolRequest, in AddProjectGuardrailInput) (*mcp.CallToolResult, AddProjectGuardrailOutput, error) {
|
func (t *SkillsTool) AddProjectGuardrail(ctx context.Context, req *mcp.CallToolRequest, in AddProjectGuardrailInput) (*mcp.CallToolResult, AddProjectGuardrailOutput, error) {
|
||||||
@@ -271,17 +270,17 @@ func (t *SkillsTool) AddProjectGuardrail(ctx context.Context, req *mcp.CallToolR
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, AddProjectGuardrailOutput{}, err
|
return nil, AddProjectGuardrailOutput{}, err
|
||||||
}
|
}
|
||||||
if err := t.store.AddProjectGuardrail(ctx, project.ID, in.GuardrailID); err != nil {
|
if err := t.store.AddProjectGuardrail(ctx, project.NumericID, in.GuardrailID); err != nil {
|
||||||
return nil, AddProjectGuardrailOutput{}, err
|
return nil, AddProjectGuardrailOutput{}, err
|
||||||
}
|
}
|
||||||
return nil, AddProjectGuardrailOutput{ProjectID: project.ID, GuardrailID: in.GuardrailID}, nil
|
return nil, AddProjectGuardrailOutput{ProjectID: project.NumericID, GuardrailID: in.GuardrailID}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove_project_guardrail
|
// remove_project_guardrail
|
||||||
|
|
||||||
type RemoveProjectGuardrailInput struct {
|
type RemoveProjectGuardrailInput struct {
|
||||||
Project string `json:"project,omitempty" jsonschema:"project name or id (uses active project if omitted)"`
|
Project string `json:"project,omitempty" jsonschema:"project name or id (uses active project if omitted)"`
|
||||||
GuardrailID uuid.UUID `json:"guardrail_id" jsonschema:"guardrail id to unlink"`
|
GuardrailID int64 `json:"guardrail_id" jsonschema:"guardrail id to unlink"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoveProjectGuardrailOutput struct {
|
type RemoveProjectGuardrailOutput struct {
|
||||||
@@ -293,7 +292,7 @@ func (t *SkillsTool) RemoveProjectGuardrail(ctx context.Context, req *mcp.CallTo
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, RemoveProjectGuardrailOutput{}, err
|
return nil, RemoveProjectGuardrailOutput{}, err
|
||||||
}
|
}
|
||||||
if err := t.store.RemoveProjectGuardrail(ctx, project.ID, in.GuardrailID); err != nil {
|
if err := t.store.RemoveProjectGuardrail(ctx, project.NumericID, in.GuardrailID); err != nil {
|
||||||
return nil, RemoveProjectGuardrailOutput{}, err
|
return nil, RemoveProjectGuardrailOutput{}, err
|
||||||
}
|
}
|
||||||
return nil, RemoveProjectGuardrailOutput{Removed: true}, nil
|
return nil, RemoveProjectGuardrailOutput{Removed: true}, nil
|
||||||
@@ -306,7 +305,7 @@ type ListProjectGuardrailsInput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ListProjectGuardrailsOutput struct {
|
type ListProjectGuardrailsOutput struct {
|
||||||
ProjectID uuid.UUID `json:"project_id"`
|
ProjectID int64 `json:"project_id"`
|
||||||
Guardrails []ext.AgentGuardrail `json:"guardrails"`
|
Guardrails []ext.AgentGuardrail `json:"guardrails"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,12 +314,12 @@ func (t *SkillsTool) ListProjectGuardrails(ctx context.Context, req *mcp.CallToo
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ListProjectGuardrailsOutput{}, err
|
return nil, ListProjectGuardrailsOutput{}, err
|
||||||
}
|
}
|
||||||
guardrails, err := t.store.ListProjectGuardrails(ctx, project.ID)
|
guardrails, err := t.store.ListProjectGuardrails(ctx, project.NumericID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ListProjectGuardrailsOutput{}, err
|
return nil, ListProjectGuardrailsOutput{}, err
|
||||||
}
|
}
|
||||||
if guardrails == nil {
|
if guardrails == nil {
|
||||||
guardrails = []ext.AgentGuardrail{}
|
guardrails = []ext.AgentGuardrail{}
|
||||||
}
|
}
|
||||||
return nil, ListProjectGuardrailsOutput{ProjectID: project.ID, Guardrails: guardrails}, nil
|
return nil, ListProjectGuardrailsOutput{ProjectID: project.NumericID, Guardrails: guardrails}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
|
|
||||||
"git.warky.dev/wdevs/amcs/internal/ai"
|
"git.warky.dev/wdevs/amcs/internal/ai"
|
||||||
@@ -49,9 +48,9 @@ func (t *SummarizeTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in
|
|||||||
count := 0
|
count := 0
|
||||||
|
|
||||||
if query != "" {
|
if query != "" {
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if project != nil {
|
if project != nil {
|
||||||
projectID = &project.ID
|
projectID = &project.NumericID
|
||||||
}
|
}
|
||||||
results, err := semanticSearch(ctx, t.store, t.embeddings, t.search, query, limit, t.search.DefaultThreshold, projectID, nil)
|
results, err := semanticSearch(ctx, t.store, t.embeddings, t.search, query, limit, t.search.DefaultThreshold, projectID, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -62,9 +61,9 @@ func (t *SummarizeTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in
|
|||||||
}
|
}
|
||||||
count = len(results)
|
count = len(results)
|
||||||
} else {
|
} else {
|
||||||
var projectID *uuid.UUID
|
var projectID *int64
|
||||||
if project != nil {
|
if project != nil {
|
||||||
projectID = &project.ID
|
projectID = &project.NumericID
|
||||||
}
|
}
|
||||||
thoughts, err := t.store.RecentThoughts(ctx, projectID, limit, in.Days)
|
thoughts, err := t.store.RecentThoughts(ctx, projectID, limit, in.Days)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -83,7 +82,7 @@ func (t *SummarizeTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in
|
|||||||
return nil, SummarizeOutput{}, err
|
return nil, SummarizeOutput{}, err
|
||||||
}
|
}
|
||||||
if project != nil {
|
if project != nil {
|
||||||
_ = t.store.TouchProject(ctx, project.ID)
|
_ = t.store.TouchProject(ctx, project.NumericID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, SummarizeOutput{Summary: summary, Count: count}, nil
|
return nil, SummarizeOutput{Summary: summary, Count: count}, nil
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ func (t *UpdateTool) Handle(ctx context.Context, _ *mcp.CallToolRequest, in Upda
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, UpdateOutput{}, err
|
return nil, UpdateOutput{}, err
|
||||||
}
|
}
|
||||||
projectID = &project.ID
|
projectID = &project.NumericID
|
||||||
}
|
}
|
||||||
|
|
||||||
updated, err := t.store.UpdateThought(ctx, id, content, embedding, embeddingModel, mergedMetadata, projectID)
|
updated, err := t.store.UpdateThought(ctx, id, content, embedding, embeddingModel, mergedMetadata, projectID)
|
||||||
|
|||||||
@@ -217,7 +217,8 @@ type ContactHistory struct {
|
|||||||
// Agent Skills & Guardrails
|
// Agent Skills & Guardrails
|
||||||
|
|
||||||
type AgentSkill struct {
|
type AgentSkill struct {
|
||||||
ID uuid.UUID `json:"id"`
|
ID int64 `json:"id"`
|
||||||
|
GUID uuid.UUID `json:"guid"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
@@ -227,7 +228,8 @@ type AgentSkill struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AgentGuardrail struct {
|
type AgentGuardrail struct {
|
||||||
ID uuid.UUID `json:"id"`
|
ID int64 `json:"id"`
|
||||||
|
GUID uuid.UUID `json:"guid"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
@@ -245,12 +247,13 @@ type ChatMessage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ChatHistory struct {
|
type ChatHistory struct {
|
||||||
ID uuid.UUID `json:"id"`
|
ID int64 `json:"id"`
|
||||||
|
GUID uuid.UUID `json:"guid"`
|
||||||
SessionID string `json:"session_id"`
|
SessionID string `json:"session_id"`
|
||||||
Title string `json:"title,omitempty"`
|
Title string `json:"title,omitempty"`
|
||||||
Channel string `json:"channel,omitempty"`
|
Channel string `json:"channel,omitempty"`
|
||||||
AgentID string `json:"agent_id,omitempty"`
|
AgentID string `json:"agent_id,omitempty"`
|
||||||
ProjectID *uuid.UUID `json:"project_id,omitempty"`
|
ProjectID *int64 `json:"project_id,omitempty"`
|
||||||
Messages []ChatMessage `json:"messages"`
|
Messages []ChatMessage `json:"messages"`
|
||||||
Summary string `json:"summary,omitempty"`
|
Summary string `json:"summary,omitempty"`
|
||||||
Metadata map[string]any `json:"metadata"`
|
Metadata map[string]any `json:"metadata"`
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Learning struct {
|
type Learning struct {
|
||||||
ID uuid.UUID `json:"id"`
|
ID int64 `json:"id"`
|
||||||
|
GUID uuid.UUID `json:"guid"`
|
||||||
Summary string `json:"summary"`
|
Summary string `json:"summary"`
|
||||||
Details string `json:"details"`
|
Details string `json:"details"`
|
||||||
Category string `json:"category"`
|
Category string `json:"category"`
|
||||||
@@ -44,13 +45,13 @@ type Learning struct {
|
|||||||
ActionRequired bool `json:"action_required"`
|
ActionRequired bool `json:"action_required"`
|
||||||
SourceType string `json:"source_type,omitempty"`
|
SourceType string `json:"source_type,omitempty"`
|
||||||
SourceRef string `json:"source_ref,omitempty"`
|
SourceRef string `json:"source_ref,omitempty"`
|
||||||
ProjectID *uuid.UUID `json:"project_id,omitempty"`
|
ProjectID *int64 `json:"project_id,omitempty"`
|
||||||
RelatedThoughtID *uuid.UUID `json:"related_thought_id,omitempty"`
|
RelatedThoughtID *int64 `json:"related_thought_id,omitempty"`
|
||||||
RelatedSkillID *uuid.UUID `json:"related_skill_id,omitempty"`
|
RelatedSkillID *int64 `json:"related_skill_id,omitempty"`
|
||||||
ReviewedBy *string `json:"reviewed_by,omitempty"`
|
ReviewedBy *string `json:"reviewed_by,omitempty"`
|
||||||
ReviewedAt *time.Time `json:"reviewed_at,omitempty"`
|
ReviewedAt *time.Time `json:"reviewed_at,omitempty"`
|
||||||
DuplicateOfLearningID *uuid.UUID `json:"duplicate_of_learning_id,omitempty"`
|
DuplicateOfLearningID *int64 `json:"duplicate_of_learning_id,omitempty"`
|
||||||
SupersedesLearningID *uuid.UUID `json:"supersedes_learning_id,omitempty"`
|
SupersedesLearningID *int64 `json:"supersedes_learning_id,omitempty"`
|
||||||
Tags []string `json:"tags"`
|
Tags []string `json:"tags"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
@@ -58,7 +59,7 @@ type Learning struct {
|
|||||||
|
|
||||||
type LearningFilter struct {
|
type LearningFilter struct {
|
||||||
Limit int
|
Limit int
|
||||||
ProjectID *uuid.UUID
|
ProjectID *int64
|
||||||
Category string
|
Category string
|
||||||
Area string
|
Area string
|
||||||
Status string
|
Status string
|
||||||
|
|||||||
@@ -27,18 +27,19 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Plan struct {
|
type Plan struct {
|
||||||
ID uuid.UUID `json:"id"`
|
ID int64 `json:"id"`
|
||||||
|
GUID uuid.UUID `json:"guid"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Status PlanStatus `json:"status"`
|
Status PlanStatus `json:"status"`
|
||||||
Priority PlanPriority `json:"priority"`
|
Priority PlanPriority `json:"priority"`
|
||||||
ProjectID *uuid.UUID `json:"project_id,omitempty"`
|
ProjectID *int64 `json:"project_id,omitempty"`
|
||||||
Owner string `json:"owner,omitempty"`
|
Owner string `json:"owner,omitempty"`
|
||||||
DueDate *time.Time `json:"due_date,omitempty"`
|
DueDate *time.Time `json:"due_date,omitempty"`
|
||||||
CompletedAt *time.Time `json:"completed_at,omitempty"`
|
CompletedAt *time.Time `json:"completed_at,omitempty"`
|
||||||
ReviewedBy string `json:"reviewed_by,omitempty"`
|
ReviewedBy string `json:"reviewed_by,omitempty"`
|
||||||
LastReviewedAt *time.Time `json:"last_reviewed_at,omitempty"`
|
LastReviewedAt *time.Time `json:"last_reviewed_at,omitempty"`
|
||||||
SupersedesPlanID *uuid.UUID `json:"supersedes_plan_id,omitempty"`
|
SupersedesPlanID *int64 `json:"supersedes_plan_id,omitempty"`
|
||||||
Tags []string `json:"tags"`
|
Tags []string `json:"tags"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
@@ -56,7 +57,7 @@ type PlanDetail struct {
|
|||||||
|
|
||||||
type PlanFilter struct {
|
type PlanFilter struct {
|
||||||
Limit int
|
Limit int
|
||||||
ProjectID *uuid.UUID
|
ProjectID *int64
|
||||||
Status string
|
Status string
|
||||||
Priority string
|
Priority string
|
||||||
Owner string
|
Owner string
|
||||||
@@ -77,7 +78,7 @@ type PlanUpdate struct {
|
|||||||
ClearCompletedAt bool
|
ClearCompletedAt bool
|
||||||
ReviewedBy *string // "" to clear
|
ReviewedBy *string // "" to clear
|
||||||
MarkReviewed bool // sets last_reviewed_at = now()
|
MarkReviewed bool // sets last_reviewed_at = now()
|
||||||
SupersedesPlanID *uuid.UUID
|
SupersedesPlanID *int64
|
||||||
ClearSupersedesPlanID bool
|
ClearSupersedesPlanID bool
|
||||||
Tags *[]string // nil = no change; replace when non-nil
|
Tags *[]string // nil = no change; replace when non-nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ import (
|
|||||||
type ThoughtPatch struct {
|
type ThoughtPatch struct {
|
||||||
Content *string `json:"content,omitempty"`
|
Content *string `json:"content,omitempty"`
|
||||||
Metadata ThoughtMetadata `json:"metadata,omitempty"`
|
Metadata ThoughtMetadata `json:"metadata,omitempty"`
|
||||||
Project *uuid.UUID `json:"project_id,omitempty"`
|
Project *int64 `json:"project_id,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Project struct {
|
type Project struct {
|
||||||
ID uuid.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
|
NumericID int64 `json:"-"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|||||||
@@ -30,9 +30,10 @@ type ThoughtAttachment struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type StoredFile struct {
|
type StoredFile struct {
|
||||||
ID uuid.UUID `json:"id"`
|
ID int64 `json:"id"`
|
||||||
ThoughtID *uuid.UUID `json:"thought_id,omitempty"`
|
GUID uuid.UUID `json:"guid"`
|
||||||
ProjectID *uuid.UUID `json:"project_id,omitempty"`
|
ThoughtID *int64 `json:"thought_id,omitempty"`
|
||||||
|
ProjectID *int64 `json:"project_id,omitempty"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
MediaType string `json:"media_type"`
|
MediaType string `json:"media_type"`
|
||||||
Kind string `json:"kind"`
|
Kind string `json:"kind"`
|
||||||
@@ -46,25 +47,26 @@ type StoredFile struct {
|
|||||||
|
|
||||||
type StoredFileFilter struct {
|
type StoredFileFilter struct {
|
||||||
Limit int
|
Limit int
|
||||||
ThoughtID *uuid.UUID
|
ThoughtID *int64
|
||||||
ProjectID *uuid.UUID
|
ProjectID *int64
|
||||||
Kind string
|
Kind string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Thought struct {
|
type Thought struct {
|
||||||
ID uuid.UUID `json:"id"`
|
ID int64 `json:"id"`
|
||||||
|
GUID uuid.UUID `json:"guid"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
Embedding []float32 `json:"embedding,omitempty"`
|
Embedding []float32 `json:"embedding,omitempty"`
|
||||||
EmbeddingStatus string `json:"embedding_status,omitempty"`
|
EmbeddingStatus string `json:"embedding_status,omitempty"`
|
||||||
Metadata ThoughtMetadata `json:"metadata"`
|
Metadata ThoughtMetadata `json:"metadata"`
|
||||||
ProjectID *uuid.UUID `json:"project_id,omitempty"`
|
ProjectID *int64 `json:"project_id,omitempty"`
|
||||||
ArchivedAt *time.Time `json:"archived_at,omitempty"`
|
ArchivedAt *time.Time `json:"archived_at,omitempty"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchResult struct {
|
type SearchResult struct {
|
||||||
ID uuid.UUID `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
Metadata ThoughtMetadata `json:"metadata"`
|
Metadata ThoughtMetadata `json:"metadata"`
|
||||||
Similarity float64 `json:"similarity"`
|
Similarity float64 `json:"similarity"`
|
||||||
@@ -77,7 +79,7 @@ type ListFilter struct {
|
|||||||
Topic string
|
Topic string
|
||||||
Person string
|
Person string
|
||||||
Days int
|
Days int
|
||||||
ProjectID *uuid.UUID
|
ProjectID *int64
|
||||||
IncludeArchived bool
|
IncludeArchived bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
338
migrations/015_bigserial_guid_migration.sql
Normal file
338
migrations/015_bigserial_guid_migration.sql
Normal file
@@ -0,0 +1,338 @@
|
|||||||
|
-- Migration: Convert uuid PKs to bigserial, rename old uuid id to guid, convert FK columns to bigint
|
||||||
|
-- Tables with uuid PK → bigserial: agent_skills, agent_guardrails, chat_histories, learnings, plans
|
||||||
|
-- Tables with serial → bigserial: thought_links, plan_dependencies, plan_related_plans, plan_skills, plan_guardrails, project_skills, project_guardrails
|
||||||
|
-- FK columns: all uuid FK columns converted to bigint referencing .id
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- STEP 1: Drop all FK constraints affected by this migration
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
ALTER TABLE public.thoughts DROP CONSTRAINT IF EXISTS thoughts_project_id_fkey;
|
||||||
|
ALTER TABLE public.embeddings DROP CONSTRAINT IF EXISTS embeddings_thought_id_fkey;
|
||||||
|
ALTER TABLE public.stored_files DROP CONSTRAINT IF EXISTS stored_files_thought_id_fkey;
|
||||||
|
ALTER TABLE public.stored_files DROP CONSTRAINT IF EXISTS stored_files_project_id_fkey;
|
||||||
|
ALTER TABLE public.project_skills DROP CONSTRAINT IF EXISTS project_skills_project_id_fkey;
|
||||||
|
ALTER TABLE public.project_skills DROP CONSTRAINT IF EXISTS project_skills_skill_id_fkey;
|
||||||
|
ALTER TABLE public.project_guardrails DROP CONSTRAINT IF EXISTS project_guardrails_project_id_fkey;
|
||||||
|
ALTER TABLE public.project_guardrails DROP CONSTRAINT IF EXISTS project_guardrails_guardrail_id_fkey;
|
||||||
|
ALTER TABLE public.chat_histories DROP CONSTRAINT IF EXISTS chat_histories_project_id_fkey;
|
||||||
|
ALTER TABLE public.learnings DROP CONSTRAINT IF EXISTS learnings_project_id_fkey;
|
||||||
|
ALTER TABLE public.learnings DROP CONSTRAINT IF EXISTS learnings_related_thought_id_fkey;
|
||||||
|
ALTER TABLE public.learnings DROP CONSTRAINT IF EXISTS learnings_related_skill_id_fkey;
|
||||||
|
ALTER TABLE public.learnings DROP CONSTRAINT IF EXISTS learnings_duplicate_of_learning_id_fkey;
|
||||||
|
ALTER TABLE public.learnings DROP CONSTRAINT IF EXISTS learnings_supersedes_learning_id_fkey;
|
||||||
|
ALTER TABLE public.plans DROP CONSTRAINT IF EXISTS plans_project_id_fkey;
|
||||||
|
ALTER TABLE public.plans DROP CONSTRAINT IF EXISTS plans_supersedes_plan_id_fkey;
|
||||||
|
ALTER TABLE public.plan_dependencies DROP CONSTRAINT IF EXISTS plan_dependencies_plan_id_fkey;
|
||||||
|
ALTER TABLE public.plan_dependencies DROP CONSTRAINT IF EXISTS plan_dependencies_depends_on_plan_id_fkey;
|
||||||
|
ALTER TABLE public.plan_related_plans DROP CONSTRAINT IF EXISTS plan_related_plans_plan_a_id_fkey;
|
||||||
|
ALTER TABLE public.plan_related_plans DROP CONSTRAINT IF EXISTS plan_related_plans_plan_b_id_fkey;
|
||||||
|
ALTER TABLE public.plan_skills DROP CONSTRAINT IF EXISTS plan_skills_plan_id_fkey;
|
||||||
|
ALTER TABLE public.plan_skills DROP CONSTRAINT IF EXISTS plan_skills_skill_id_fkey;
|
||||||
|
ALTER TABLE public.plan_guardrails DROP CONSTRAINT IF EXISTS plan_guardrails_plan_id_fkey;
|
||||||
|
ALTER TABLE public.plan_guardrails DROP CONSTRAINT IF EXISTS plan_guardrails_guardrail_id_fkey;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- STEP 2: Drop PK constraints on uuid-pk tables
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
ALTER TABLE public.agent_skills DROP CONSTRAINT IF EXISTS agent_skills_pkey;
|
||||||
|
ALTER TABLE public.agent_guardrails DROP CONSTRAINT IF EXISTS agent_guardrails_pkey;
|
||||||
|
ALTER TABLE public.chat_histories DROP CONSTRAINT IF EXISTS chat_histories_pkey;
|
||||||
|
ALTER TABLE public.learnings DROP CONSTRAINT IF EXISTS learnings_pkey;
|
||||||
|
ALTER TABLE public.plans DROP CONSTRAINT IF EXISTS plans_pkey;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- STEP 3: Rename uuid id → guid on formerly uuid-pk tables
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
ALTER TABLE public.agent_skills RENAME COLUMN id TO guid;
|
||||||
|
ALTER TABLE public.agent_guardrails RENAME COLUMN id TO guid;
|
||||||
|
ALTER TABLE public.chat_histories RENAME COLUMN id TO guid;
|
||||||
|
ALTER TABLE public.learnings RENAME COLUMN id TO guid;
|
||||||
|
ALTER TABLE public.plans RENAME COLUMN id TO guid;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- STEP 4: Add bigserial id columns to formerly uuid-pk tables
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
ALTER TABLE public.agent_skills ADD COLUMN id bigserial;
|
||||||
|
ALTER TABLE public.agent_guardrails ADD COLUMN id bigserial;
|
||||||
|
ALTER TABLE public.chat_histories ADD COLUMN id bigserial;
|
||||||
|
ALTER TABLE public.learnings ADD COLUMN id bigserial;
|
||||||
|
ALTER TABLE public.plans ADD COLUMN id bigserial;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- STEP 5: Add new bigint FK columns (prefixed _new) where uuid FKs exist
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- thoughts.project_id (uuid → bigint via projects.guid)
|
||||||
|
ALTER TABLE public.thoughts ADD COLUMN project_id_new bigint;
|
||||||
|
UPDATE public.thoughts t SET project_id_new = p.id FROM public.projects p WHERE p.guid = t.project_id;
|
||||||
|
|
||||||
|
-- embeddings.thought_id (uuid → bigint via thoughts.guid)
|
||||||
|
ALTER TABLE public.embeddings ADD COLUMN thought_id_new bigint;
|
||||||
|
UPDATE public.embeddings e SET thought_id_new = t.id FROM public.thoughts t WHERE t.guid = e.thought_id;
|
||||||
|
|
||||||
|
-- stored_files.thought_id (uuid → bigint via thoughts.guid)
|
||||||
|
ALTER TABLE public.stored_files ADD COLUMN thought_id_new bigint;
|
||||||
|
UPDATE public.stored_files f SET thought_id_new = t.id FROM public.thoughts t WHERE t.guid = f.thought_id;
|
||||||
|
|
||||||
|
-- stored_files.project_id (uuid → bigint via projects.guid)
|
||||||
|
ALTER TABLE public.stored_files ADD COLUMN project_id_new bigint;
|
||||||
|
UPDATE public.stored_files f SET project_id_new = p.id FROM public.projects p WHERE p.guid = f.project_id;
|
||||||
|
|
||||||
|
-- project_skills.project_id (uuid → bigint via projects.guid)
|
||||||
|
ALTER TABLE public.project_skills ADD COLUMN project_id_new bigint;
|
||||||
|
UPDATE public.project_skills ps SET project_id_new = p.id FROM public.projects p WHERE p.guid = ps.project_id;
|
||||||
|
|
||||||
|
-- project_skills.skill_id (uuid → bigint via agent_skills.guid)
|
||||||
|
ALTER TABLE public.project_skills ADD COLUMN skill_id_new bigint;
|
||||||
|
UPDATE public.project_skills ps SET skill_id_new = s.id FROM public.agent_skills s WHERE s.guid = ps.skill_id;
|
||||||
|
|
||||||
|
-- project_guardrails.project_id (uuid → bigint via projects.guid)
|
||||||
|
ALTER TABLE public.project_guardrails ADD COLUMN project_id_new bigint;
|
||||||
|
UPDATE public.project_guardrails pg SET project_id_new = p.id FROM public.projects p WHERE p.guid = pg.project_id;
|
||||||
|
|
||||||
|
-- project_guardrails.guardrail_id (uuid → bigint via agent_guardrails.guid)
|
||||||
|
ALTER TABLE public.project_guardrails ADD COLUMN guardrail_id_new bigint;
|
||||||
|
UPDATE public.project_guardrails pg SET guardrail_id_new = g.id FROM public.agent_guardrails g WHERE g.guid = pg.guardrail_id;
|
||||||
|
|
||||||
|
-- chat_histories.project_id (uuid → bigint via projects.guid)
|
||||||
|
ALTER TABLE public.chat_histories ADD COLUMN project_id_new bigint;
|
||||||
|
UPDATE public.chat_histories ch SET project_id_new = p.id FROM public.projects p WHERE p.guid = ch.project_id;
|
||||||
|
|
||||||
|
-- learnings.project_id (uuid → bigint via projects.guid)
|
||||||
|
ALTER TABLE public.learnings ADD COLUMN project_id_new bigint;
|
||||||
|
UPDATE public.learnings l SET project_id_new = p.id FROM public.projects p WHERE p.guid = l.project_id;
|
||||||
|
|
||||||
|
-- learnings.related_thought_id (uuid → bigint via thoughts.guid)
|
||||||
|
ALTER TABLE public.learnings ADD COLUMN related_thought_id_new bigint;
|
||||||
|
UPDATE public.learnings l SET related_thought_id_new = t.id FROM public.thoughts t WHERE t.guid = l.related_thought_id;
|
||||||
|
|
||||||
|
-- learnings.related_skill_id (uuid → bigint via agent_skills.guid)
|
||||||
|
ALTER TABLE public.learnings ADD COLUMN related_skill_id_new bigint;
|
||||||
|
UPDATE public.learnings l SET related_skill_id_new = s.id FROM public.agent_skills s WHERE s.guid = l.related_skill_id;
|
||||||
|
|
||||||
|
-- learnings.duplicate_of_learning_id (uuid → bigint via learnings.guid)
|
||||||
|
ALTER TABLE public.learnings ADD COLUMN duplicate_of_learning_id_new bigint;
|
||||||
|
UPDATE public.learnings l SET duplicate_of_learning_id_new = l2.id FROM public.learnings l2 WHERE l2.guid = l.duplicate_of_learning_id;
|
||||||
|
|
||||||
|
-- learnings.supersedes_learning_id (uuid → bigint via learnings.guid)
|
||||||
|
ALTER TABLE public.learnings ADD COLUMN supersedes_learning_id_new bigint;
|
||||||
|
UPDATE public.learnings l SET supersedes_learning_id_new = l2.id FROM public.learnings l2 WHERE l2.guid = l.supersedes_learning_id;
|
||||||
|
|
||||||
|
-- plans.project_id (uuid → bigint via projects.guid)
|
||||||
|
ALTER TABLE public.plans ADD COLUMN project_id_new bigint;
|
||||||
|
UPDATE public.plans pl SET project_id_new = p.id FROM public.projects p WHERE p.guid = pl.project_id;
|
||||||
|
|
||||||
|
-- plans.supersedes_plan_id (uuid → bigint via plans.guid)
|
||||||
|
ALTER TABLE public.plans ADD COLUMN supersedes_plan_id_new bigint;
|
||||||
|
UPDATE public.plans pl SET supersedes_plan_id_new = pl2.id FROM public.plans pl2 WHERE pl2.guid = pl.supersedes_plan_id;
|
||||||
|
|
||||||
|
-- plan_dependencies.plan_id (uuid → bigint via plans.guid)
|
||||||
|
ALTER TABLE public.plan_dependencies ADD COLUMN plan_id_new bigint;
|
||||||
|
UPDATE public.plan_dependencies pd SET plan_id_new = pl.id FROM public.plans pl WHERE pl.guid = pd.plan_id;
|
||||||
|
|
||||||
|
-- plan_dependencies.depends_on_plan_id (uuid → bigint via plans.guid)
|
||||||
|
ALTER TABLE public.plan_dependencies ADD COLUMN depends_on_plan_id_new bigint;
|
||||||
|
UPDATE public.plan_dependencies pd SET depends_on_plan_id_new = pl.id FROM public.plans pl WHERE pl.guid = pd.depends_on_plan_id;
|
||||||
|
|
||||||
|
-- plan_related_plans.plan_a_id (uuid → bigint via plans.guid)
|
||||||
|
ALTER TABLE public.plan_related_plans ADD COLUMN plan_a_id_new bigint;
|
||||||
|
UPDATE public.plan_related_plans pr SET plan_a_id_new = pl.id FROM public.plans pl WHERE pl.guid = pr.plan_a_id;
|
||||||
|
|
||||||
|
-- plan_related_plans.plan_b_id (uuid → bigint via plans.guid)
|
||||||
|
ALTER TABLE public.plan_related_plans ADD COLUMN plan_b_id_new bigint;
|
||||||
|
UPDATE public.plan_related_plans pr SET plan_b_id_new = pl.id FROM public.plans pl WHERE pl.guid = pr.plan_b_id;
|
||||||
|
|
||||||
|
-- plan_skills.plan_id (uuid → bigint via plans.guid)
|
||||||
|
ALTER TABLE public.plan_skills ADD COLUMN plan_id_new bigint;
|
||||||
|
UPDATE public.plan_skills ps SET plan_id_new = pl.id FROM public.plans pl WHERE pl.guid = ps.plan_id;
|
||||||
|
|
||||||
|
-- plan_skills.skill_id (uuid → bigint via agent_skills.guid)
|
||||||
|
ALTER TABLE public.plan_skills ADD COLUMN skill_id_new bigint;
|
||||||
|
UPDATE public.plan_skills ps SET skill_id_new = s.id FROM public.agent_skills s WHERE s.guid = ps.skill_id;
|
||||||
|
|
||||||
|
-- plan_guardrails.plan_id (uuid → bigint via plans.guid)
|
||||||
|
ALTER TABLE public.plan_guardrails ADD COLUMN plan_id_new bigint;
|
||||||
|
UPDATE public.plan_guardrails pg SET plan_id_new = pl.id FROM public.plans pl WHERE pl.guid = pg.plan_id;
|
||||||
|
|
||||||
|
-- plan_guardrails.guardrail_id (uuid → bigint via agent_guardrails.guid)
|
||||||
|
ALTER TABLE public.plan_guardrails ADD COLUMN guardrail_id_new bigint;
|
||||||
|
UPDATE public.plan_guardrails pg SET guardrail_id_new = g.id FROM public.agent_guardrails g WHERE g.guid = pg.guardrail_id;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- STEP 6: Drop old uuid FK columns
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
ALTER TABLE public.thoughts DROP COLUMN project_id;
|
||||||
|
ALTER TABLE public.embeddings DROP COLUMN thought_id;
|
||||||
|
ALTER TABLE public.stored_files DROP COLUMN thought_id;
|
||||||
|
ALTER TABLE public.stored_files DROP COLUMN project_id;
|
||||||
|
ALTER TABLE public.project_skills DROP COLUMN project_id;
|
||||||
|
ALTER TABLE public.project_skills DROP COLUMN skill_id;
|
||||||
|
ALTER TABLE public.project_guardrails DROP COLUMN project_id;
|
||||||
|
ALTER TABLE public.project_guardrails DROP COLUMN guardrail_id;
|
||||||
|
ALTER TABLE public.chat_histories DROP COLUMN project_id;
|
||||||
|
ALTER TABLE public.learnings DROP COLUMN project_id;
|
||||||
|
ALTER TABLE public.learnings DROP COLUMN related_thought_id;
|
||||||
|
ALTER TABLE public.learnings DROP COLUMN related_skill_id;
|
||||||
|
ALTER TABLE public.learnings DROP COLUMN duplicate_of_learning_id;
|
||||||
|
ALTER TABLE public.learnings DROP COLUMN supersedes_learning_id;
|
||||||
|
ALTER TABLE public.plans DROP COLUMN project_id;
|
||||||
|
ALTER TABLE public.plans DROP COLUMN supersedes_plan_id;
|
||||||
|
ALTER TABLE public.plan_dependencies DROP COLUMN plan_id;
|
||||||
|
ALTER TABLE public.plan_dependencies DROP COLUMN depends_on_plan_id;
|
||||||
|
ALTER TABLE public.plan_related_plans DROP COLUMN plan_a_id;
|
||||||
|
ALTER TABLE public.plan_related_plans DROP COLUMN plan_b_id;
|
||||||
|
ALTER TABLE public.plan_skills DROP COLUMN plan_id;
|
||||||
|
ALTER TABLE public.plan_skills DROP COLUMN skill_id;
|
||||||
|
ALTER TABLE public.plan_guardrails DROP COLUMN plan_id;
|
||||||
|
ALTER TABLE public.plan_guardrails DROP COLUMN guardrail_id;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- STEP 7: Rename _new columns to final names
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
ALTER TABLE public.thoughts RENAME COLUMN project_id_new TO project_id;
|
||||||
|
ALTER TABLE public.embeddings RENAME COLUMN thought_id_new TO thought_id;
|
||||||
|
ALTER TABLE public.stored_files RENAME COLUMN thought_id_new TO thought_id;
|
||||||
|
ALTER TABLE public.stored_files RENAME COLUMN project_id_new TO project_id;
|
||||||
|
ALTER TABLE public.project_skills RENAME COLUMN project_id_new TO project_id;
|
||||||
|
ALTER TABLE public.project_skills RENAME COLUMN skill_id_new TO skill_id;
|
||||||
|
ALTER TABLE public.project_guardrails RENAME COLUMN project_id_new TO project_id;
|
||||||
|
ALTER TABLE public.project_guardrails RENAME COLUMN guardrail_id_new TO guardrail_id;
|
||||||
|
ALTER TABLE public.chat_histories RENAME COLUMN project_id_new TO project_id;
|
||||||
|
ALTER TABLE public.learnings RENAME COLUMN project_id_new TO project_id;
|
||||||
|
ALTER TABLE public.learnings RENAME COLUMN related_thought_id_new TO related_thought_id;
|
||||||
|
ALTER TABLE public.learnings RENAME COLUMN related_skill_id_new TO related_skill_id;
|
||||||
|
ALTER TABLE public.learnings RENAME COLUMN duplicate_of_learning_id_new TO duplicate_of_learning_id;
|
||||||
|
ALTER TABLE public.learnings RENAME COLUMN supersedes_learning_id_new TO supersedes_learning_id;
|
||||||
|
ALTER TABLE public.plans RENAME COLUMN project_id_new TO project_id;
|
||||||
|
ALTER TABLE public.plans RENAME COLUMN supersedes_plan_id_new TO supersedes_plan_id;
|
||||||
|
ALTER TABLE public.plan_dependencies RENAME COLUMN plan_id_new TO plan_id;
|
||||||
|
ALTER TABLE public.plan_dependencies RENAME COLUMN depends_on_plan_id_new TO depends_on_plan_id;
|
||||||
|
ALTER TABLE public.plan_related_plans RENAME COLUMN plan_a_id_new TO plan_a_id;
|
||||||
|
ALTER TABLE public.plan_related_plans RENAME COLUMN plan_b_id_new TO plan_b_id;
|
||||||
|
ALTER TABLE public.plan_skills RENAME COLUMN plan_id_new TO plan_id;
|
||||||
|
ALTER TABLE public.plan_skills RENAME COLUMN skill_id_new TO skill_id;
|
||||||
|
ALTER TABLE public.plan_guardrails RENAME COLUMN plan_id_new TO plan_id;
|
||||||
|
ALTER TABLE public.plan_guardrails RENAME COLUMN guardrail_id_new TO guardrail_id;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- STEP 8: Upgrade serial → bigserial (alter sequence type)
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- thought_links
|
||||||
|
ALTER SEQUENCE IF EXISTS thought_links_id_seq AS bigint;
|
||||||
|
ALTER TABLE public.thought_links ALTER COLUMN id TYPE bigint;
|
||||||
|
|
||||||
|
-- plan_dependencies
|
||||||
|
ALTER SEQUENCE IF EXISTS plan_dependencies_id_seq AS bigint;
|
||||||
|
ALTER TABLE public.plan_dependencies ALTER COLUMN id TYPE bigint;
|
||||||
|
|
||||||
|
-- plan_related_plans
|
||||||
|
ALTER SEQUENCE IF EXISTS plan_related_plans_id_seq AS bigint;
|
||||||
|
ALTER TABLE public.plan_related_plans ALTER COLUMN id TYPE bigint;
|
||||||
|
|
||||||
|
-- plan_skills
|
||||||
|
ALTER SEQUENCE IF EXISTS plan_skills_id_seq AS bigint;
|
||||||
|
ALTER TABLE public.plan_skills ALTER COLUMN id TYPE bigint;
|
||||||
|
|
||||||
|
-- plan_guardrails
|
||||||
|
ALTER SEQUENCE IF EXISTS plan_guardrails_id_seq AS bigint;
|
||||||
|
ALTER TABLE public.plan_guardrails ALTER COLUMN id TYPE bigint;
|
||||||
|
|
||||||
|
-- project_skills
|
||||||
|
ALTER SEQUENCE IF EXISTS project_skills_id_seq AS bigint;
|
||||||
|
ALTER TABLE public.project_skills ALTER COLUMN id TYPE bigint;
|
||||||
|
|
||||||
|
-- project_guardrails
|
||||||
|
ALTER SEQUENCE IF EXISTS project_guardrails_id_seq AS bigint;
|
||||||
|
ALTER TABLE public.project_guardrails ALTER COLUMN id TYPE bigint;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- STEP 9: Add PK constraints to formerly uuid-pk tables
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
ALTER TABLE public.agent_skills ADD CONSTRAINT agent_skills_pkey PRIMARY KEY (id);
|
||||||
|
ALTER TABLE public.agent_guardrails ADD CONSTRAINT agent_guardrails_pkey PRIMARY KEY (id);
|
||||||
|
ALTER TABLE public.chat_histories ADD CONSTRAINT chat_histories_pkey PRIMARY KEY (id);
|
||||||
|
ALTER TABLE public.learnings ADD CONSTRAINT learnings_pkey PRIMARY KEY (id);
|
||||||
|
ALTER TABLE public.plans ADD CONSTRAINT plans_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
-- Add unique constraint on guid columns
|
||||||
|
ALTER TABLE public.agent_skills ADD CONSTRAINT agent_skills_guid_key UNIQUE (guid);
|
||||||
|
ALTER TABLE public.agent_guardrails ADD CONSTRAINT agent_guardrails_guid_key UNIQUE (guid);
|
||||||
|
ALTER TABLE public.chat_histories ADD CONSTRAINT chat_histories_guid_key UNIQUE (guid);
|
||||||
|
ALTER TABLE public.learnings ADD CONSTRAINT learnings_guid_key UNIQUE (guid);
|
||||||
|
ALTER TABLE public.plans ADD CONSTRAINT plans_guid_key UNIQUE (guid);
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- STEP 10: Re-add FK constraints
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
ALTER TABLE public.thoughts
|
||||||
|
ADD CONSTRAINT thoughts_project_id_fkey FOREIGN KEY (project_id) REFERENCES public.projects(id);
|
||||||
|
|
||||||
|
ALTER TABLE public.embeddings
|
||||||
|
ADD CONSTRAINT embeddings_thought_id_fkey FOREIGN KEY (thought_id) REFERENCES public.thoughts(id);
|
||||||
|
|
||||||
|
ALTER TABLE public.stored_files
|
||||||
|
ADD CONSTRAINT stored_files_thought_id_fkey FOREIGN KEY (thought_id) REFERENCES public.thoughts(id);
|
||||||
|
ALTER TABLE public.stored_files
|
||||||
|
ADD CONSTRAINT stored_files_project_id_fkey FOREIGN KEY (project_id) REFERENCES public.projects(id);
|
||||||
|
|
||||||
|
ALTER TABLE public.project_skills
|
||||||
|
ADD CONSTRAINT project_skills_project_id_fkey FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
|
||||||
|
ALTER TABLE public.project_skills
|
||||||
|
ADD CONSTRAINT project_skills_skill_id_fkey FOREIGN KEY (skill_id) REFERENCES public.agent_skills(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE public.project_guardrails
|
||||||
|
ADD CONSTRAINT project_guardrails_project_id_fkey FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
|
||||||
|
ALTER TABLE public.project_guardrails
|
||||||
|
ADD CONSTRAINT project_guardrails_guardrail_id_fkey FOREIGN KEY (guardrail_id) REFERENCES public.agent_guardrails(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE public.chat_histories
|
||||||
|
ADD CONSTRAINT chat_histories_project_id_fkey FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE SET NULL;
|
||||||
|
|
||||||
|
ALTER TABLE public.learnings
|
||||||
|
ADD CONSTRAINT learnings_project_id_fkey FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE SET NULL;
|
||||||
|
ALTER TABLE public.learnings
|
||||||
|
ADD CONSTRAINT learnings_related_thought_id_fkey FOREIGN KEY (related_thought_id) REFERENCES public.thoughts(id) ON DELETE SET NULL;
|
||||||
|
ALTER TABLE public.learnings
|
||||||
|
ADD CONSTRAINT learnings_related_skill_id_fkey FOREIGN KEY (related_skill_id) REFERENCES public.agent_skills(id) ON DELETE SET NULL;
|
||||||
|
ALTER TABLE public.learnings
|
||||||
|
ADD CONSTRAINT learnings_duplicate_of_learning_id_fkey FOREIGN KEY (duplicate_of_learning_id) REFERENCES public.learnings(id) ON DELETE SET NULL;
|
||||||
|
ALTER TABLE public.learnings
|
||||||
|
ADD CONSTRAINT learnings_supersedes_learning_id_fkey FOREIGN KEY (supersedes_learning_id) REFERENCES public.learnings(id) ON DELETE SET NULL;
|
||||||
|
|
||||||
|
ALTER TABLE public.plans
|
||||||
|
ADD CONSTRAINT plans_project_id_fkey FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE SET NULL;
|
||||||
|
ALTER TABLE public.plans
|
||||||
|
ADD CONSTRAINT plans_supersedes_plan_id_fkey FOREIGN KEY (supersedes_plan_id) REFERENCES public.plans(id) ON DELETE SET NULL;
|
||||||
|
|
||||||
|
ALTER TABLE public.plan_dependencies
|
||||||
|
ADD CONSTRAINT plan_dependencies_plan_id_fkey FOREIGN KEY (plan_id) REFERENCES public.plans(id) ON DELETE CASCADE;
|
||||||
|
ALTER TABLE public.plan_dependencies
|
||||||
|
ADD CONSTRAINT plan_dependencies_depends_on_plan_id_fkey FOREIGN KEY (depends_on_plan_id) REFERENCES public.plans(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE public.plan_related_plans
|
||||||
|
ADD CONSTRAINT plan_related_plans_plan_a_id_fkey FOREIGN KEY (plan_a_id) REFERENCES public.plans(id) ON DELETE CASCADE;
|
||||||
|
ALTER TABLE public.plan_related_plans
|
||||||
|
ADD CONSTRAINT plan_related_plans_plan_b_id_fkey FOREIGN KEY (plan_b_id) REFERENCES public.plans(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE public.plan_skills
|
||||||
|
ADD CONSTRAINT plan_skills_plan_id_fkey FOREIGN KEY (plan_id) REFERENCES public.plans(id) ON DELETE CASCADE;
|
||||||
|
ALTER TABLE public.plan_skills
|
||||||
|
ADD CONSTRAINT plan_skills_skill_id_fkey FOREIGN KEY (skill_id) REFERENCES public.agent_skills(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE public.plan_guardrails
|
||||||
|
ADD CONSTRAINT plan_guardrails_plan_id_fkey FOREIGN KEY (plan_id) REFERENCES public.plans(id) ON DELETE CASCADE;
|
||||||
|
ALTER TABLE public.plan_guardrails
|
||||||
|
ADD CONSTRAINT plan_guardrails_guardrail_id_fkey FOREIGN KEY (guardrail_id) REFERENCES public.agent_guardrails(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@ Table thoughts {
|
|||||||
metadata jsonb [default: `'{}'::jsonb`]
|
metadata jsonb [default: `'{}'::jsonb`]
|
||||||
created_at timestamptz [default: `now()`]
|
created_at timestamptz [default: `now()`]
|
||||||
updated_at timestamptz [default: `now()`]
|
updated_at timestamptz [default: `now()`]
|
||||||
project_id uuid [ref: > projects.guid]
|
project_id bigint [ref: > projects.id]
|
||||||
archived_at timestamptz
|
archived_at timestamptz
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ Table projects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Table thought_links {
|
Table thought_links {
|
||||||
id serial [pk]
|
id bigserial [pk]
|
||||||
from_id bigint [not null, ref: > thoughts.id]
|
from_id bigint [not null, ref: > thoughts.id]
|
||||||
to_id bigint [not null, ref: > thoughts.id]
|
to_id bigint [not null, ref: > thoughts.id]
|
||||||
relation text [not null]
|
relation text [not null]
|
||||||
@@ -35,7 +35,7 @@ Table thought_links {
|
|||||||
Table embeddings {
|
Table embeddings {
|
||||||
id bigserial [pk]
|
id bigserial [pk]
|
||||||
guid uuid [unique, not null, default: `gen_random_uuid()`]
|
guid uuid [unique, not null, default: `gen_random_uuid()`]
|
||||||
thought_id uuid [not null, ref: > thoughts.guid]
|
thought_id bigint [not null, ref: > thoughts.id]
|
||||||
model text [not null]
|
model text [not null]
|
||||||
dim int [not null]
|
dim int [not null]
|
||||||
embedding vector [not null]
|
embedding vector [not null]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
Table stored_files {
|
Table stored_files {
|
||||||
id bigserial [pk]
|
id bigserial [pk]
|
||||||
guid uuid [unique, not null, default: `gen_random_uuid()`]
|
guid uuid [unique, not null, default: `gen_random_uuid()`]
|
||||||
thought_id uuid [ref: > thoughts.guid]
|
thought_id bigint [ref: > thoughts.id]
|
||||||
project_id uuid [ref: > projects.guid]
|
project_id bigint [ref: > projects.id]
|
||||||
name text [not null]
|
name text [not null]
|
||||||
media_type text [not null]
|
media_type text [not null]
|
||||||
kind text [not null, default: 'file']
|
kind text [not null, default: 'file']
|
||||||
@@ -21,5 +21,5 @@ Table stored_files {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cross-file refs (for relspecgo merge)
|
// Cross-file refs (for relspecgo merge)
|
||||||
Ref: stored_files.thought_id > thoughts.guid [delete: set null]
|
Ref: stored_files.thought_id > thoughts.id [delete: set null]
|
||||||
Ref: stored_files.project_id > projects.guid [delete: set null]
|
Ref: stored_files.project_id > projects.id [delete: set null]
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
Table chat_histories {
|
Table chat_histories {
|
||||||
id uuid [pk, default: `gen_random_uuid()`]
|
id bigserial [pk]
|
||||||
|
guid uuid [unique, not null, default: `gen_random_uuid()`]
|
||||||
session_id text [not null]
|
session_id text [not null]
|
||||||
title text
|
title text
|
||||||
channel text
|
channel text
|
||||||
agent_id text
|
agent_id text
|
||||||
project_id uuid [ref: > projects.guid]
|
project_id bigint [ref: > projects.id]
|
||||||
messages jsonb [not null, default: `'[]'`]
|
messages jsonb [not null, default: `'[]'`]
|
||||||
summary text
|
summary text
|
||||||
metadata jsonb [not null, default: `'{}'`]
|
metadata jsonb [not null, default: `'{}'`]
|
||||||
@@ -29,10 +30,11 @@ Table tool_annotations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cross-file refs (for relspecgo merge)
|
// Cross-file refs (for relspecgo merge)
|
||||||
Ref: chat_histories.project_id > projects.guid [delete: set null]
|
Ref: chat_histories.project_id > projects.id [delete: set null]
|
||||||
|
|
||||||
Table learnings {
|
Table learnings {
|
||||||
id uuid [pk, default: `gen_random_uuid()`]
|
id bigserial [pk]
|
||||||
|
guid uuid [unique, not null, default: `gen_random_uuid()`]
|
||||||
summary text [not null]
|
summary text [not null]
|
||||||
details text [not null, default: '']
|
details text [not null, default: '']
|
||||||
category text [not null, default: 'insight']
|
category text [not null, default: 'insight']
|
||||||
@@ -43,13 +45,13 @@ Table learnings {
|
|||||||
action_required boolean [not null, default: false]
|
action_required boolean [not null, default: false]
|
||||||
source_type text
|
source_type text
|
||||||
source_ref text
|
source_ref text
|
||||||
project_id uuid [ref: > projects.guid]
|
project_id bigint [ref: > projects.id]
|
||||||
related_thought_id uuid [ref: > thoughts.guid]
|
related_thought_id bigint [ref: > thoughts.id]
|
||||||
related_skill_id uuid [ref: > agent_skills.id]
|
related_skill_id bigint [ref: > agent_skills.id]
|
||||||
reviewed_by text
|
reviewed_by text
|
||||||
reviewed_at timestamptz
|
reviewed_at timestamptz
|
||||||
duplicate_of_learning_id uuid [ref: > learnings.id]
|
duplicate_of_learning_id bigint [ref: > learnings.id]
|
||||||
supersedes_learning_id uuid [ref: > learnings.id]
|
supersedes_learning_id bigint [ref: > learnings.id]
|
||||||
tags "text[]" [not null, default: `'{}'`]
|
tags "text[]" [not null, default: `'{}'`]
|
||||||
created_at timestamptz [not null, default: `now()`]
|
created_at timestamptz [not null, default: `now()`]
|
||||||
updated_at timestamptz [not null, default: `now()`]
|
updated_at timestamptz [not null, default: `now()`]
|
||||||
@@ -68,8 +70,8 @@ Table learnings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cross-file refs (for relspecgo merge)
|
// Cross-file refs (for relspecgo merge)
|
||||||
Ref: learnings.project_id > projects.guid [delete: set null]
|
Ref: learnings.project_id > projects.id [delete: set null]
|
||||||
Ref: learnings.related_thought_id > thoughts.guid [delete: set null]
|
Ref: learnings.related_thought_id > thoughts.id [delete: set null]
|
||||||
Ref: learnings.related_skill_id > agent_skills.id [delete: set null]
|
Ref: learnings.related_skill_id > agent_skills.id [delete: set null]
|
||||||
Ref: learnings.duplicate_of_learning_id > learnings.id [delete: set null]
|
Ref: learnings.duplicate_of_learning_id > learnings.id [delete: set null]
|
||||||
Ref: learnings.supersedes_learning_id > learnings.id [delete: set null]
|
Ref: learnings.supersedes_learning_id > learnings.id [delete: set null]
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
Table plans {
|
Table plans {
|
||||||
id uuid [pk, default: `gen_random_uuid()`]
|
id bigserial [pk]
|
||||||
|
guid uuid [unique, not null, default: `gen_random_uuid()`]
|
||||||
title text [not null]
|
title text [not null]
|
||||||
description text [not null, default: '']
|
description text [not null, default: '']
|
||||||
status text [not null, default: 'draft'] // draft, active, blocked, completed, cancelled, superseded
|
status text [not null, default: 'draft'] // draft, active, blocked, completed, cancelled, superseded
|
||||||
priority text [not null, default: 'medium'] // low, medium, high, critical
|
priority text [not null, default: 'medium'] // low, medium, high, critical
|
||||||
project_id uuid [ref: > projects.guid]
|
project_id bigint [ref: > projects.id]
|
||||||
owner text
|
owner text
|
||||||
due_date timestamptz
|
due_date timestamptz
|
||||||
completed_at timestamptz
|
completed_at timestamptz
|
||||||
reviewed_by text
|
reviewed_by text
|
||||||
last_reviewed_at timestamptz
|
last_reviewed_at timestamptz
|
||||||
supersedes_plan_id uuid [ref: > plans.id]
|
supersedes_plan_id bigint [ref: > plans.id]
|
||||||
tags "text[]" [not null, default: `'{}'`]
|
tags "text[]" [not null, default: `'{}'`]
|
||||||
created_at timestamptz [not null, default: `now()`]
|
created_at timestamptz [not null, default: `now()`]
|
||||||
updated_at timestamptz [not null, default: `now()`]
|
updated_at timestamptz [not null, default: `now()`]
|
||||||
@@ -29,9 +30,9 @@ Table plans {
|
|||||||
|
|
||||||
// Directional: plan_id cannot proceed until depends_on_plan_id is complete
|
// Directional: plan_id cannot proceed until depends_on_plan_id is complete
|
||||||
Table plan_dependencies {
|
Table plan_dependencies {
|
||||||
id serial [pk]
|
id bigserial [pk]
|
||||||
plan_id uuid [not null, ref: > plans.id]
|
plan_id bigint [not null, ref: > plans.id]
|
||||||
depends_on_plan_id uuid [not null, ref: > plans.id]
|
depends_on_plan_id bigint [not null, ref: > plans.id]
|
||||||
created_at timestamptz [not null, default: `now()`]
|
created_at timestamptz [not null, default: `now()`]
|
||||||
|
|
||||||
indexes {
|
indexes {
|
||||||
@@ -43,9 +44,9 @@ Table plan_dependencies {
|
|||||||
|
|
||||||
// Bidirectional: store with plan_a_id < plan_b_id to avoid duplicates
|
// Bidirectional: store with plan_a_id < plan_b_id to avoid duplicates
|
||||||
Table plan_related_plans {
|
Table plan_related_plans {
|
||||||
id serial [pk]
|
id bigserial [pk]
|
||||||
plan_a_id uuid [not null, ref: > plans.id]
|
plan_a_id bigint [not null, ref: > plans.id]
|
||||||
plan_b_id uuid [not null, ref: > plans.id]
|
plan_b_id bigint [not null, ref: > plans.id]
|
||||||
created_at timestamptz [not null, default: `now()`]
|
created_at timestamptz [not null, default: `now()`]
|
||||||
|
|
||||||
indexes {
|
indexes {
|
||||||
@@ -56,9 +57,9 @@ Table plan_related_plans {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Table plan_skills {
|
Table plan_skills {
|
||||||
id serial [pk]
|
id bigserial [pk]
|
||||||
plan_id uuid [not null, ref: > plans.id]
|
plan_id bigint [not null, ref: > plans.id]
|
||||||
skill_id uuid [not null, ref: > agent_skills.id]
|
skill_id bigint [not null, ref: > agent_skills.id]
|
||||||
created_at timestamptz [not null, default: `now()`]
|
created_at timestamptz [not null, default: `now()`]
|
||||||
|
|
||||||
indexes {
|
indexes {
|
||||||
@@ -68,9 +69,9 @@ Table plan_skills {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Table plan_guardrails {
|
Table plan_guardrails {
|
||||||
id serial [pk]
|
id bigserial [pk]
|
||||||
plan_id uuid [not null, ref: > plans.id]
|
plan_id bigint [not null, ref: > plans.id]
|
||||||
guardrail_id uuid [not null, ref: > agent_guardrails.id]
|
guardrail_id bigint [not null, ref: > agent_guardrails.id]
|
||||||
created_at timestamptz [not null, default: `now()`]
|
created_at timestamptz [not null, default: `now()`]
|
||||||
|
|
||||||
indexes {
|
indexes {
|
||||||
@@ -80,7 +81,7 @@ Table plan_guardrails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cross-file refs (for relspecgo merge)
|
// Cross-file refs (for relspecgo merge)
|
||||||
Ref: plans.project_id > projects.guid [delete: set null]
|
Ref: plans.project_id > projects.id [delete: set null]
|
||||||
Ref: plans.supersedes_plan_id > plans.id [delete: set null]
|
Ref: plans.supersedes_plan_id > plans.id [delete: set null]
|
||||||
Ref: plan_dependencies.plan_id > plans.id [delete: cascade]
|
Ref: plan_dependencies.plan_id > plans.id [delete: cascade]
|
||||||
Ref: plan_dependencies.depends_on_plan_id > plans.id [delete: cascade]
|
Ref: plan_dependencies.depends_on_plan_id > plans.id [delete: cascade]
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
Table agent_skills {
|
Table agent_skills {
|
||||||
id uuid [pk, default: `gen_random_uuid()`]
|
id bigserial [pk]
|
||||||
|
guid uuid [unique, not null, default: `gen_random_uuid()`]
|
||||||
name text [unique, not null]
|
name text [unique, not null]
|
||||||
description text [not null, default: '']
|
description text [not null, default: '']
|
||||||
content text [not null]
|
content text [not null]
|
||||||
@@ -9,7 +10,8 @@ Table agent_skills {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Table agent_guardrails {
|
Table agent_guardrails {
|
||||||
id uuid [pk, default: `gen_random_uuid()`]
|
id bigserial [pk]
|
||||||
|
guid uuid [unique, not null, default: `gen_random_uuid()`]
|
||||||
name text [unique, not null]
|
name text [unique, not null]
|
||||||
description text [not null, default: '']
|
description text [not null, default: '']
|
||||||
content text [not null]
|
content text [not null]
|
||||||
@@ -20,9 +22,9 @@ Table agent_guardrails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Table project_skills {
|
Table project_skills {
|
||||||
id serial [pk]
|
id bigserial [pk]
|
||||||
project_id uuid [not null, ref: > projects.guid]
|
project_id bigint [not null, ref: > projects.id]
|
||||||
skill_id uuid [not null, ref: > agent_skills.id]
|
skill_id bigint [not null, ref: > agent_skills.id]
|
||||||
created_at timestamptz [not null, default: `now()`]
|
created_at timestamptz [not null, default: `now()`]
|
||||||
|
|
||||||
indexes {
|
indexes {
|
||||||
@@ -32,9 +34,9 @@ Table project_skills {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Table project_guardrails {
|
Table project_guardrails {
|
||||||
id serial [pk]
|
id bigserial [pk]
|
||||||
project_id uuid [not null, ref: > projects.guid]
|
project_id bigint [not null, ref: > projects.id]
|
||||||
guardrail_id uuid [not null, ref: > agent_guardrails.id]
|
guardrail_id bigint [not null, ref: > agent_guardrails.id]
|
||||||
created_at timestamptz [not null, default: `now()`]
|
created_at timestamptz [not null, default: `now()`]
|
||||||
|
|
||||||
indexes {
|
indexes {
|
||||||
@@ -44,5 +46,7 @@ Table project_guardrails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cross-file refs (for relspecgo merge)
|
// Cross-file refs (for relspecgo merge)
|
||||||
Ref: project_skills.project_id > projects.guid [delete: cascade]
|
Ref: project_skills.project_id > projects.id [delete: cascade]
|
||||||
Ref: project_guardrails.project_id > projects.guid [delete: cascade]
|
Ref: project_skills.skill_id > agent_skills.id [delete: cascade]
|
||||||
|
Ref: project_guardrails.project_id > projects.id [delete: cascade]
|
||||||
|
Ref: project_guardrails.guardrail_id > agent_guardrails.id [delete: cascade]
|
||||||
|
|||||||
Reference in New Issue
Block a user