Compare commits
2
Commits
trust
...
md-reflect
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f281ae022 | ||
|
|
4abdec8d6b |
+60
@@ -0,0 +1,60 @@
|
||||
"""Fix mental_models primary key to be scoped per bank
|
||||
|
||||
Revision ID: w8r9s0t1u2v3
|
||||
Revises: v7q8r9s0t1u2
|
||||
Create Date: 2026-02-05
|
||||
|
||||
This migration fixes a critical bank isolation bug where mental_models.id was
|
||||
globally unique across all banks instead of being scoped per bank. This caused
|
||||
conflicts when different banks tried to use the same custom ID.
|
||||
|
||||
CRITICAL FIX: Changes primary key from (id) to (bank_id, id) to ensure proper isolation.
|
||||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
|
||||
from alembic import context, op
|
||||
|
||||
revision: str = "w8r9s0t1u2v3"
|
||||
down_revision: str | Sequence[str] | None = "v7q8r9s0t1u2"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
def _get_schema_prefix() -> str:
|
||||
"""Get schema prefix for table names (required for multi-tenant support)."""
|
||||
schema = context.config.get_main_option("target_schema")
|
||||
return f'"{schema}".' if schema else ""
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Change mental_models primary key from (id) to (bank_id, id) for proper bank isolation."""
|
||||
schema = _get_schema_prefix()
|
||||
|
||||
# Drop the old primary key constraint (just id)
|
||||
# Note: The constraint might be named differently on different DBs
|
||||
# Try both old names (pinned_reflections_pkey from original, mental_models_pkey from rename)
|
||||
op.execute(f"ALTER TABLE {schema}mental_models DROP CONSTRAINT IF EXISTS pinned_reflections_pkey")
|
||||
op.execute(f"ALTER TABLE {schema}mental_models DROP CONSTRAINT IF EXISTS mental_models_pkey")
|
||||
|
||||
# Create the new composite primary key (bank_id, id)
|
||||
# This ensures IDs are scoped per bank, not globally
|
||||
op.execute(f"""
|
||||
ALTER TABLE {schema}mental_models
|
||||
ADD CONSTRAINT mental_models_pkey PRIMARY KEY (bank_id, id)
|
||||
""")
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Revert mental_models primary key from (bank_id, id) to (id)."""
|
||||
schema = _get_schema_prefix()
|
||||
|
||||
# Drop the composite primary key
|
||||
op.execute(f"ALTER TABLE {schema}mental_models DROP CONSTRAINT IF EXISTS mental_models_pkey")
|
||||
|
||||
# Restore the old primary key (just id)
|
||||
# WARNING: This downgrade will fail if there are duplicate IDs across banks
|
||||
op.execute(f"""
|
||||
ALTER TABLE {schema}mental_models
|
||||
ADD CONSTRAINT mental_models_pkey PRIMARY KEY (id)
|
||||
""")
|
||||
@@ -523,7 +523,9 @@ class ReflectFact(BaseModel):
|
||||
)
|
||||
|
||||
id: str | None = None
|
||||
text: str
|
||||
text: str = Field(
|
||||
description="Fact text. When type='observation', this contains markdown-formatted consolidated knowledge"
|
||||
)
|
||||
type: str | None = None # fact type: world, experience, observation
|
||||
context: str | None = None
|
||||
occurred_start: str | None = None
|
||||
@@ -588,7 +590,7 @@ class ReflectResponse(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
json_schema_extra={
|
||||
"example": {
|
||||
"text": "Based on my understanding, AI is a transformative technology...",
|
||||
"text": "## AI Overview\n\nBased on my understanding, AI is a **transformative technology**:\n\n- Used extensively in healthcare\n- Discussed in recent conversations\n- Continues to evolve rapidly",
|
||||
"based_on": {
|
||||
"memories": [
|
||||
{"id": "123", "text": "AI is used in healthcare", "type": "world"},
|
||||
@@ -616,7 +618,9 @@ class ReflectResponse(BaseModel):
|
||||
}
|
||||
)
|
||||
|
||||
text: str
|
||||
text: str = Field(
|
||||
description="The reflect response as well-formatted markdown (headers, lists, bold/italic, code blocks, etc.)"
|
||||
)
|
||||
based_on: ReflectBasedOn | None = Field(
|
||||
default=None,
|
||||
description="Evidence used to generate the response. Only present when include.facts is set.",
|
||||
@@ -1114,7 +1118,9 @@ class MentalModelResponse(BaseModel):
|
||||
bank_id: str
|
||||
name: str
|
||||
source_query: str
|
||||
content: str
|
||||
content: str = Field(
|
||||
description="The mental model content as well-formatted markdown (auto-generated from reflect endpoint)"
|
||||
)
|
||||
tags: list[str] = Field(default_factory=list)
|
||||
max_tokens: int = Field(default=2048)
|
||||
trigger: MentalModelTrigger = Field(default_factory=MentalModelTrigger)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
CONSOLIDATION_SYSTEM_PROMPT = """You are a memory consolidation system. Your job is to convert facts into durable knowledge (observations) and merge with existing knowledge when appropriate.
|
||||
|
||||
You must output ONLY valid JSON with no markdown formatting, no code blocks, and no additional text.
|
||||
You must output ONLY valid JSON with no markdown code blocks or additional text. However, the "text" field within each observation should use markdown formatting (headers, lists, bold, etc.) for clarity and readability.
|
||||
|
||||
## EXTRACT DURABLE KNOWLEDGE, NOT EPHEMERAL STATE
|
||||
Facts often describe events or actions. Extract the DURABLE KNOWLEDGE implied by the fact, not the transient state.
|
||||
@@ -71,10 +71,15 @@ Instructions:
|
||||
- New topic → CREATE new observation
|
||||
- Purely ephemeral → return []
|
||||
|
||||
Output JSON array of actions:
|
||||
Output JSON array of actions (the "text" field should use markdown formatting for structure):
|
||||
[
|
||||
{{"action": "update", "learning_id": "uuid-from-observations", "text": "updated knowledge", "reason": "..."}},
|
||||
{{"action": "create", "text": "new durable knowledge", "reason": "..."}}
|
||||
{{"action": "update", "learning_id": "uuid-from-observations", "text": "## Updated Knowledge\n\n**Key point**: details here\n\n- Supporting detail 1\n- Supporting detail 2", "reason": "..."}},
|
||||
{{"action": "create", "text": "## New Durable Knowledge\n\nDescription with **emphasis** and proper structure", "reason": "..."}}
|
||||
]
|
||||
|
||||
Return [] if fact contains no durable knowledge."""
|
||||
Return [] if fact contains no durable knowledge.
|
||||
|
||||
IMPORTANT: Format the "text" field with markdown for better readability:
|
||||
- Use headers, lists, bold/italic, tables where appropriate
|
||||
- CRITICAL: Add blank lines before and after block elements (tables, code blocks, lists)
|
||||
- Ensure proper spacing for markdown to render correctly"""
|
||||
|
||||
@@ -31,7 +31,7 @@ class ReflectAction(BaseModel):
|
||||
default=None, description="Observation sections for done action (when output_mode=observations)"
|
||||
)
|
||||
# Plain text answer fields (for output_mode=answer)
|
||||
answer: str | None = Field(default=None, description="Plain text answer for done action (no markdown)")
|
||||
answer: str | None = Field(default=None, description="Well-formatted markdown answer for done action")
|
||||
answer_memory_ids: list[str] | None = Field(
|
||||
default=None, description="Memory IDs supporting the answer", alias="memory_ids"
|
||||
)
|
||||
|
||||
@@ -300,9 +300,11 @@ def build_system_prompt_for_tools(
|
||||
parts.extend(
|
||||
[
|
||||
"",
|
||||
"## Output Format: Plain Text Answer",
|
||||
"Call done() with a plain text 'answer' field.",
|
||||
"- Do NOT use markdown formatting",
|
||||
"## Output Format: Well-Formatted Markdown Answer",
|
||||
"Call done() with a well-formatted markdown 'answer' field.",
|
||||
"- USE markdown formatting for structure (headers, lists, bold, italic, code blocks, tables, etc.)",
|
||||
"- CRITICAL: Add blank lines before and after block elements (tables, code blocks, lists)",
|
||||
"- Format for clarity and readability with proper spacing and hierarchy",
|
||||
"- NEVER include memory IDs, UUIDs, or 'Memory references' in the answer text",
|
||||
"- Put IDs ONLY in the memory_ids/mental_model_ids/observation_ids arrays, not in the answer",
|
||||
]
|
||||
@@ -485,8 +487,17 @@ Your approach:
|
||||
Only say "I don't have information" if the retrieved data is truly unrelated to the question.
|
||||
Do NOT fabricate information that has no basis in the retrieved data.
|
||||
|
||||
FORMATTING: Use proper markdown formatting in your answer:
|
||||
- Headers (##, ###) for sections
|
||||
- Lists (bullet or numbered) for enumerations
|
||||
- Bold/italic for emphasis
|
||||
- Tables with proper syntax (ensure blank line before and after)
|
||||
- Code blocks where appropriate
|
||||
- CRITICAL: Always add blank lines before and after block elements (tables, code blocks, lists)
|
||||
- Proper spacing between sections
|
||||
|
||||
CRITICAL: Output ONLY the final synthesized answer. Do NOT include:
|
||||
- Meta-commentary about what you're doing ("I'll search...", "Let me analyze...")
|
||||
- Explanations of your reasoning process
|
||||
- Descriptions of your approach
|
||||
Just provide the direct answer."""
|
||||
Just provide the direct answer with proper markdown formatting."""
|
||||
|
||||
@@ -139,7 +139,7 @@ TOOL_DONE_ANSWER = {
|
||||
"properties": {
|
||||
"answer": {
|
||||
"type": "string",
|
||||
"description": "Your response as plain text. Do NOT use markdown formatting. NEVER include memory IDs, UUIDs, or 'Memory references' in this text - put IDs only in memory_ids array.",
|
||||
"description": "Your response as well-formatted markdown. Use headers, lists, bold/italic, and code blocks for clarity. NEVER include memory IDs, UUIDs, or 'Memory references' in this text - put IDs only in memory_ids array.",
|
||||
},
|
||||
"memory_ids": {
|
||||
"type": "array",
|
||||
@@ -190,7 +190,7 @@ def _build_done_tool_with_directives(directive_rules: list[str]) -> dict:
|
||||
"properties": {
|
||||
"answer": {
|
||||
"type": "string",
|
||||
"description": "Your response as plain text. Do NOT use markdown formatting. NEVER include memory IDs, UUIDs, or 'Memory references' in this text - put IDs only in memory_ids array.",
|
||||
"description": "Your response as well-formatted markdown. Use headers, lists, bold/italic, and code blocks for clarity. NEVER include memory IDs, UUIDs, or 'Memory references' in this text - put IDs only in memory_ids array.",
|
||||
},
|
||||
"memory_ids": {
|
||||
"type": "array",
|
||||
|
||||
@@ -17,7 +17,7 @@ import pprint
|
||||
import re # noqa: F401
|
||||
import json
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr
|
||||
from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
|
||||
from typing import Any, ClassVar, Dict, List, Optional
|
||||
from hindsight_client_api.models.mental_model_trigger import MentalModelTrigger
|
||||
from typing import Optional, Set
|
||||
@@ -31,7 +31,7 @@ class MentalModelResponse(BaseModel):
|
||||
bank_id: StrictStr
|
||||
name: StrictStr
|
||||
source_query: StrictStr
|
||||
content: StrictStr
|
||||
content: StrictStr = Field(description="The mental model content as well-formatted markdown (auto-generated from reflect endpoint)")
|
||||
tags: Optional[List[StrictStr]] = None
|
||||
max_tokens: Optional[StrictInt] = 2048
|
||||
trigger: Optional[MentalModelTrigger] = None
|
||||
|
||||
@@ -17,7 +17,7 @@ import pprint
|
||||
import re # noqa: F401
|
||||
import json
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, StrictStr
|
||||
from pydantic import BaseModel, ConfigDict, Field, StrictStr
|
||||
from typing import Any, ClassVar, Dict, List, Optional
|
||||
from typing import Optional, Set
|
||||
from typing_extensions import Self
|
||||
@@ -27,7 +27,7 @@ class ReflectFact(BaseModel):
|
||||
A fact used in think response.
|
||||
""" # noqa: E501
|
||||
id: Optional[StrictStr] = None
|
||||
text: StrictStr
|
||||
text: StrictStr = Field(description="Fact text. When type='observation', this contains markdown-formatted consolidated knowledge")
|
||||
type: Optional[StrictStr] = None
|
||||
context: Optional[StrictStr] = None
|
||||
occurred_start: Optional[StrictStr] = None
|
||||
|
||||
@@ -17,7 +17,7 @@ import pprint
|
||||
import re # noqa: F401
|
||||
import json
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, StrictStr
|
||||
from pydantic import BaseModel, ConfigDict, Field, StrictStr
|
||||
from typing import Any, ClassVar, Dict, List, Optional
|
||||
from hindsight_client_api.models.reflect_based_on import ReflectBasedOn
|
||||
from hindsight_client_api.models.reflect_trace import ReflectTrace
|
||||
@@ -29,7 +29,7 @@ class ReflectResponse(BaseModel):
|
||||
"""
|
||||
Response model for think endpoint.
|
||||
""" # noqa: E501
|
||||
text: StrictStr
|
||||
text: StrictStr = Field(description="The reflect response as well-formatted markdown (headers, lists, bold/italic, code blocks, etc.)")
|
||||
based_on: Optional[ReflectBasedOn] = None
|
||||
structured_output: Optional[Dict[str, Any]] = None
|
||||
usage: Optional[TokenUsage] = None
|
||||
|
||||
@@ -1034,6 +1034,8 @@ export type MentalModelResponse = {
|
||||
source_query: string;
|
||||
/**
|
||||
* Content
|
||||
*
|
||||
* The mental model content as well-formatted markdown (auto-generated from reflect endpoint)
|
||||
*/
|
||||
content: string;
|
||||
/**
|
||||
@@ -1382,6 +1384,8 @@ export type ReflectFact = {
|
||||
id?: string | null;
|
||||
/**
|
||||
* Text
|
||||
*
|
||||
* Fact text. When type='observation', this contains markdown-formatted consolidated knowledge
|
||||
*/
|
||||
text: string;
|
||||
/**
|
||||
@@ -1523,6 +1527,8 @@ export type ReflectRequest = {
|
||||
export type ReflectResponse = {
|
||||
/**
|
||||
* Text
|
||||
*
|
||||
* The reflect response as well-formatted markdown (headers, lists, bold/italic, code blocks, etc.)
|
||||
*/
|
||||
text: string;
|
||||
/**
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
"react-markdown": "^10.1.0",
|
||||
"react18-json-view": "^0.2.9",
|
||||
"recharts": "^3.5.1",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"tailwind-merge": "^3.4.0",
|
||||
"tailwindcss": "^4.1.17",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
|
||||
@@ -189,4 +189,75 @@ input[type="datetime-local"]::-webkit-calendar-picker-indicator {
|
||||
|
||||
.dark input[type="datetime-local"]::-webkit-calendar-picker-indicator {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
/* Markdown table styles - explicitly override Tailwind reset */
|
||||
.prose table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.5;
|
||||
border: 2px solid rgba(0, 0, 0, 0.2) !important;
|
||||
}
|
||||
|
||||
.prose thead {
|
||||
border-bottom: 3px solid rgba(0, 0, 0, 0.3) !important;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.prose thead th {
|
||||
padding: 0.5rem 0.75rem;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
vertical-align: bottom;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2) !important;
|
||||
border-bottom-width: 3px !important;
|
||||
}
|
||||
|
||||
.prose tbody tr {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.15) !important;
|
||||
}
|
||||
|
||||
.prose tbody tr:last-child {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.15) !important;
|
||||
}
|
||||
|
||||
.prose tbody td {
|
||||
padding: 0.5rem 0.75rem;
|
||||
vertical-align: top;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15) !important;
|
||||
}
|
||||
|
||||
.prose tbody tr:hover {
|
||||
background-color: rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
/* Dark mode table styles - use white borders with transparency */
|
||||
.dark .prose table {
|
||||
color: hsl(var(--foreground));
|
||||
border: 2px solid rgba(255, 255, 255, 0.2) !important;
|
||||
}
|
||||
|
||||
.dark .prose thead {
|
||||
border-bottom: 3px solid rgba(255, 255, 255, 0.3) !important;
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.dark .prose thead th {
|
||||
border: 1px solid rgba(255, 255, 255, 0.2) !important;
|
||||
border-bottom-width: 3px !important;
|
||||
}
|
||||
|
||||
.dark .prose tbody tr {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.15) !important;
|
||||
}
|
||||
|
||||
.dark .prose tbody td {
|
||||
border: 1px solid rgba(255, 255, 255, 0.15) !important;
|
||||
}
|
||||
|
||||
.dark .prose tbody tr:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { client } from "@/lib/api";
|
||||
import { useBank } from "@/lib/bank-context";
|
||||
@@ -1343,7 +1344,7 @@ function DirectiveDetailPanel({
|
||||
Rule
|
||||
</div>
|
||||
<div className="prose prose-base dark:prose-invert max-w-none">
|
||||
<ReactMarkdown>{directive.content}</ReactMarkdown>
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>{directive.content}</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||||
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
|
||||
import { Loader2, Zap } from "lucide-react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
|
||||
interface MentalModelDetailContentProps {
|
||||
mentalModel: MentalModel;
|
||||
@@ -73,7 +74,7 @@ export function MentalModelDetailContent({ mentalModel }: MentalModelDetailConte
|
||||
Content
|
||||
</div>
|
||||
<div className="prose prose-base dark:prose-invert max-w-none">
|
||||
<ReactMarkdown>{mentalModel.content}</ReactMarkdown>
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>{mentalModel.content}</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import { client } from "@/lib/api";
|
||||
import { useBank } from "@/lib/bank-context";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -302,8 +303,24 @@ export function MentalModelsView() {
|
||||
<p className="text-sm text-muted-foreground line-clamp-2 mb-3">
|
||||
{m.source_query}
|
||||
</p>
|
||||
<div className="text-sm text-foreground line-clamp-6 mb-3 border-t border-border pt-3">
|
||||
{m.content}
|
||||
<div className="text-sm text-foreground mb-3 border-t border-border pt-3">
|
||||
{/* Check if content has tables or complex markdown */}
|
||||
{m.content.includes("|") ||
|
||||
m.content.includes("```") ||
|
||||
m.content.includes("\n\n") ? (
|
||||
// Show plain text preview for complex content
|
||||
<div className="line-clamp-3 text-muted-foreground italic">
|
||||
{m.content.substring(0, 150)}...{" "}
|
||||
<span className="text-primary">Click to view full content</span>
|
||||
</div>
|
||||
) : (
|
||||
// Render simple markdown with line clamp
|
||||
<div className="line-clamp-6 prose prose-sm dark:prose-invert max-w-none">
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>
|
||||
{m.content}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-xs border-t border-border pt-3">
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -1115,7 +1132,7 @@ function MentalModelDetailPanel({
|
||||
Content
|
||||
</div>
|
||||
<div className="prose prose-base dark:prose-invert max-w-none">
|
||||
<ReactMarkdown>{mentalModel.content}</ReactMarkdown>
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>{mentalModel.content}</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ import JsonView from "react18-json-view";
|
||||
import "react18-json-view/src/style.css";
|
||||
import { MemoryDetailModal } from "./memory-detail-modal";
|
||||
import { MentalModelDetailModal } from "./mental-model-detail-modal";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
|
||||
type TagsMatch = "any" | "all" | "any_strict" | "all_strict";
|
||||
type ViewMode = "answer" | "trace" | "json";
|
||||
@@ -364,7 +366,9 @@ export function ThinkView() {
|
||||
<CardTitle>Answer</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-base leading-relaxed whitespace-pre-wrap">{result.text}</div>
|
||||
<div className="prose prose-sm max-w-none dark:prose-invert">
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>{result.text}</ReactMarkdown>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -967,9 +971,11 @@ export function ThinkView() {
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<h3 className="text-sm font-medium text-muted-foreground">Text</h3>
|
||||
<p className="mt-1 font-medium">
|
||||
{fullObservation?.text || selectedObservation.text}
|
||||
</p>
|
||||
<div className="mt-1 prose prose-sm max-w-none dark:prose-invert">
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>
|
||||
{fullObservation?.text || selectedObservation.text}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
{fullObservation?.tags && fullObservation.tags.length > 0 && (
|
||||
<div>
|
||||
|
||||
@@ -4672,7 +4672,8 @@
|
||||
},
|
||||
"content": {
|
||||
"type": "string",
|
||||
"title": "Content"
|
||||
"title": "Content",
|
||||
"description": "The mental model content as well-formatted markdown (auto-generated from reflect endpoint)"
|
||||
},
|
||||
"tags": {
|
||||
"items": {
|
||||
@@ -5391,7 +5392,8 @@
|
||||
},
|
||||
"text": {
|
||||
"type": "string",
|
||||
"title": "Text"
|
||||
"title": "Text",
|
||||
"description": "Fact text. When type='observation', this contains markdown-formatted consolidated knowledge"
|
||||
},
|
||||
"type": {
|
||||
"anyOf": [
|
||||
@@ -5651,7 +5653,8 @@
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string",
|
||||
"title": "Text"
|
||||
"title": "Text",
|
||||
"description": "The reflect response as well-formatted markdown (headers, lists, bold/italic, code blocks, etc.)"
|
||||
},
|
||||
"based_on": {
|
||||
"anyOf": [
|
||||
@@ -5728,7 +5731,7 @@
|
||||
],
|
||||
"summary": "AI is transformative"
|
||||
},
|
||||
"text": "Based on my understanding, AI is a transformative technology...",
|
||||
"text": "## AI Overview\n\nBased on my understanding, AI is a **transformative technology**:\n\n- Used extensively in healthcare\n- Discussed in recent conversations\n- Continues to evolve rapidly",
|
||||
"trace": {
|
||||
"llm_calls": [
|
||||
{
|
||||
|
||||
Generated
+3
-2
@@ -13,7 +13,7 @@
|
||||
},
|
||||
"hindsight-clients/typescript": {
|
||||
"name": "@vectorize-io/hindsight-client",
|
||||
"version": "0.4.4",
|
||||
"version": "0.4.9",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@hey-api/openapi-ts": "0.88.0",
|
||||
@@ -131,7 +131,7 @@
|
||||
},
|
||||
"hindsight-control-plane": {
|
||||
"name": "@vectorize-io/hindsight-control-plane",
|
||||
"version": "0.4.4",
|
||||
"version": "0.4.9",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-alert-dialog": "^1.1.15",
|
||||
@@ -170,6 +170,7 @@
|
||||
"react-markdown": "^10.1.0",
|
||||
"react18-json-view": "^0.2.9",
|
||||
"recharts": "^3.5.1",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"tailwind-merge": "^3.4.0",
|
||||
"tailwindcss": "^4.1.17",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
|
||||
Reference in New Issue
Block a user