doc: add blog (#201)
* doc: introduce mental models blog post Write blog post introducing Mental Models in Hindsight 0.4.0: - Evolution from observations and opinions - How mental models work (consolidation, evidence tracking) - Breaking changes and migration path - Environment variable to enable (experimental) - Agentic reflect explanation * updates * Update 2026-01-26-learning-capabilities.md * fix: doc build issues - Add missing code snippets for versioned docs (recall-opinions-only, recall-include-entities, bank-background) - Fix broken links by using relative paths for version compatibility - Update blog post title to sentence case - Clear versions.json since v0.3 versioned docs don't exist yet - Enable INCLUDE_CURRENT_VERSION in build script * fix: update doc links after rebase - Fix blog post to link to correct pages (/developer/api/mental-models and /developer/observations) - Fix CLI docs to link to /api-reference instead of /api * feat: add directives section to blog post - Update intro to mention three layers of knowledge - Add concise Directives section for compliance/guardrails - Add directives to resources section - Keep focus on learning capabilities (observations and mental models) * fix: revert intro to focus on learning capabilities only Directives are a separate feature for compliance/guardrails, not a learning capability. The blog post is about observations and mental models.
This commit is contained in:
parent
2118d0a7cd
commit
1bf90358c3
12 changed files with 442 additions and 11 deletions
284
hindsight-docs/blog/2026-01-26-learning-capabilities.md
Normal file
284
hindsight-docs/blog/2026-01-26-learning-capabilities.md
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
---
|
||||
slug: learning-capabilities
|
||||
title: "Agent memory that learns: observations and mental models"
|
||||
authors: [hindsight]
|
||||
image: /img/reflect-operation.webp
|
||||
hide_table_of_contents: false
|
||||
---
|
||||
|
||||
Today we're releasing Hindsight 0.4.0, which introduces two powerful learning capabilities for AI agents: **Observations** for automatic knowledge consolidation, and **Mental Models** for user-curated summaries.
|
||||
|
||||
<!-- truncate -->
|
||||
|
||||
## Two Levels of Learning
|
||||
|
||||
Hindsight 0.4.0 introduces a hierarchical learning system:
|
||||
|
||||
| Level | What It Is | How It's Created |
|
||||
|-------|------------|------------------|
|
||||
| **Mental Models** | User-curated summaries for common queries | Manually created via API |
|
||||
| **Observations** | Consolidated knowledge from facts | Automatically after retain |
|
||||
|
||||
During `reflect`, the agent checks these in priority order — mental models first (your curated knowledge), then observations (automatic synthesis), then raw facts.
|
||||
|
||||
---
|
||||
|
||||
## Observations: Automatic Knowledge Consolidation
|
||||
|
||||
### Evolution from Entity Summaries and Opinions
|
||||
|
||||
In Hindsight 0.3.0, we had two separate systems for synthesized knowledge:
|
||||
|
||||
- **Entity summaries**: Per-entity summaries synthesized from related facts. Generated automatically for frequently-mentioned entities — if "Alice" appeared in many facts, you'd get a summary like "Alice is a software engineer at Google who joined in 2020 and leads the search team." Objective and entity-scoped.
|
||||
|
||||
- **Opinions**: Beliefs formed during `reflect` operations, influenced by the bank's disposition traits. These captured subjective judgments with confidence scores, like "Python is best for data science" (confidence: 0.85).
|
||||
|
||||
Both systems served their purpose well, but they operated independently. Entity summaries were entity-centric, opinions were belief-centric, and neither captured the full picture of how knowledge evolves over time.
|
||||
|
||||
**Observations** unify these concepts into a single, more expressive system that captures patterns, preferences, and learnings as they emerge from accumulated evidence.
|
||||
|
||||
### What Are Observations?
|
||||
|
||||
Observations are **consolidated knowledge** synthesized from multiple facts. Unlike raw facts which are individual pieces of information, observations represent patterns and insights that emerge from accumulated evidence.
|
||||
|
||||
| Raw Facts | Observation |
|
||||
|-----------|--------------|
|
||||
| "Alice prefers Python" | "Alice is a Python-focused developer who values readability and simplicity, recommends type hints, and prefers pytest for testing" |
|
||||
| "Alice dislikes verbose code" | |
|
||||
| "Alice recommends type hints" | |
|
||||
|
||||
### Automatic Background Consolidation
|
||||
|
||||
After every `retain()` call, Hindsight's consolidation engine runs automatically:
|
||||
|
||||
1. **Analyzes new facts** against existing knowledge
|
||||
2. **Detects patterns** across related information
|
||||
3. **Synthesizes observations** that capture higher-order insights
|
||||
4. **Tracks evidence** linking each observation to its supporting facts
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[New Facts] --> B[Consolidation Engine]
|
||||
B --> C{Existing Observation?}
|
||||
C -->|Yes| D[Refine Observation]
|
||||
C -->|No| E[Create Observation]
|
||||
D --> F[Observations]
|
||||
E --> F
|
||||
```
|
||||
|
||||
### Evidence-Based Evolution
|
||||
|
||||
Observations evolve as new evidence arrives, capturing the full journey rather than just the current state:
|
||||
|
||||
| Time | Fact | Observation |
|
||||
|------|------|--------------|
|
||||
| Week 1 | "User loves React" | "User prefers React for frontend development" |
|
||||
| Week 2 | "User praises React's component model" | "User is enthusiastic about React, particularly its component model" |
|
||||
| Week 3 | "User switched to Vue and won't use React anymore" | "User was previously a React enthusiast who appreciated its component model, but has now switched to Vue" |
|
||||
|
||||
Notice how the final observation captures the **full journey** — not just "User prefers Vue" but the complete evolution. Your agent now understands:
|
||||
|
||||
- The user deliberately moved away from React (it wasn't ignorance)
|
||||
- They previously appreciated React's component model (relevant context)
|
||||
- Recommending React tutorials would be inappropriate
|
||||
|
||||
### Mission-Oriented Consolidation
|
||||
|
||||
Observations are influenced by your bank's **mission**. When you set a mission, the consolidation engine focuses on extracting knowledge that serves that purpose:
|
||||
|
||||
```python
|
||||
client.create_bank(
|
||||
bank_id="support-agent",
|
||||
mission="You're a customer support agent - track customer preferences, "
|
||||
"past issues, and communication styles."
|
||||
)
|
||||
```
|
||||
|
||||
With this mission, the engine prioritizes customer-relevant observations while skipping ephemeral details. Without a mission, it performs general-purpose consolidation.
|
||||
|
||||
---
|
||||
|
||||
## Mental Models: User-Curated Knowledge
|
||||
|
||||
While observations are created automatically, **mental models** give you explicit control over how your agent answers common questions.
|
||||
|
||||
### What Are Mental Models?
|
||||
|
||||
Mental models are **saved reflect responses** that you curate for your memory bank. When you create a mental model, Hindsight runs a reflect operation with your source query and stores the result. During future reflect calls, these pre-computed summaries are checked first.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Create Mental Model] --> B[Run Reflect]
|
||||
B --> C[Store Result]
|
||||
C --> D[Future Queries]
|
||||
D --> E{Match Found?}
|
||||
E -->|Yes| F[Return Mental Model]
|
||||
E -->|No| G[Run Full Reflect]
|
||||
```
|
||||
|
||||
### Why Use Mental Models?
|
||||
|
||||
| Benefit | Description |
|
||||
|---------|-------------|
|
||||
| **Consistency** | Same answer every time for common questions |
|
||||
| **Speed** | Pre-computed responses are returned instantly |
|
||||
| **Quality** | Manually curated summaries you've reviewed |
|
||||
| **Control** | Define exactly how key topics should be answered |
|
||||
|
||||
### Two Ways to Use Mental Models
|
||||
|
||||
Mental models work in two ways:
|
||||
|
||||
1. **Automatic via Reflect**: During `reflect` calls, the agent automatically checks mental models first. If a relevant one exists, it's used to inform the response.
|
||||
|
||||
2. **Direct Lookup**: Mental models work like a key-value store — you can retrieve them instantly by ID, bypassing the reflect reasoning loop entirely.
|
||||
|
||||
```python
|
||||
# Direct lookup by ID — instant response, no LLM call
|
||||
mental_model = client.get_mental_model(
|
||||
bank_id="my-bank",
|
||||
mental_model_id="team-communication"
|
||||
)
|
||||
print(mental_model.content) # Pre-computed answer, ready to use
|
||||
```
|
||||
|
||||
This is useful when you know exactly what mental model you need and want the fastest possible response — no LLM reasoning required, just a simple database lookup.
|
||||
|
||||
### Creating Mental Models
|
||||
|
||||
```python
|
||||
# Create a mental model for a common question
|
||||
response = client.create_mental_model(
|
||||
bank_id="my-bank",
|
||||
name="Team Communication Preferences",
|
||||
source_query="How does the team prefer to communicate?",
|
||||
tags=["team"]
|
||||
)
|
||||
```
|
||||
|
||||
### Automatic Refresh
|
||||
|
||||
Mental models can automatically stay in sync with your observations:
|
||||
|
||||
```python
|
||||
# Mental model that refreshes when observations update
|
||||
response = client.create_mental_model(
|
||||
bank_id="my-bank",
|
||||
name="Project Status",
|
||||
source_query="What is the current project status?",
|
||||
trigger={"refresh_after_consolidation": True}
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Directives: Compliance and Guardrails
|
||||
|
||||
In addition to learning capabilities, **directives** provide hard rules that your agent must always follow during reflect operations. Unlike disposition traits which *influence* reasoning style, directives are absolute requirements that are enforced in every response.
|
||||
|
||||
Use directives for compliance, privacy, and safety constraints:
|
||||
- "Never provide medical diagnoses or treatment advice"
|
||||
- "Always respond in formal English"
|
||||
- "Never share personally identifiable information"
|
||||
- "Always cite sources when making factual claims"
|
||||
|
||||
Directives are injected into reflect prompts as hard constraints and are included in the response's `based_on` field. See the [Directives documentation](../developer/api/memory-banks#directives) for how to create and manage them.
|
||||
|
||||
---
|
||||
|
||||
## What Changes from 0.3.0
|
||||
|
||||
### Unified Memory Types
|
||||
|
||||
Opinions and entity summaries are now consolidated into observations:
|
||||
|
||||
```python
|
||||
# 0.3.0 - opinions via types, entity summaries via include_entities
|
||||
response = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="What do you think about Python?",
|
||||
types=["opinion"],
|
||||
include_entities=True # to get entity summaries
|
||||
)
|
||||
|
||||
# 0.4.0 - observations unify both
|
||||
response = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="What do you think about Python?",
|
||||
types=["observation"]
|
||||
)
|
||||
```
|
||||
|
||||
### From Confidence Scores to Evidence Tracking
|
||||
|
||||
Opinions had numeric confidence scores (0.0-1.0). Observations instead track:
|
||||
|
||||
- **Supporting facts**: The evidence behind the observation
|
||||
- **Last updated**: When the observation was last refined
|
||||
- **Freshness**: Whether the observation reflects recent information
|
||||
|
||||
This shift from a single score to evidence tracking means your agent can explain *why* it believes something, not just *how confident* it is.
|
||||
|
||||
### Automatic vs On-Demand
|
||||
|
||||
Entity summaries were created automatically for top entities, but opinions only formed during `reflect`. Observations are always consolidated automatically after `retain`, ensuring knowledge stays current without explicit queries.
|
||||
|
||||
### Background Becomes Mission
|
||||
|
||||
The bank's `background` field has been renamed to `mission`. During the migration, your existing background text is automatically copied to the mission field — no action needed.
|
||||
|
||||
### Agentic Reflect
|
||||
|
||||
The `reflect` operation is now agentic — it reasons more deeply by iteratively retrieving memories and consulting mental models and observations before formulating a response. This makes reflect significantly smarter, especially for complex questions that require synthesizing information across multiple topics.
|
||||
|
||||
The trade-off is that reflect may take longer to respond. For latency-sensitive use cases, consider using `recall` directly when you just need to retrieve facts.
|
||||
|
||||
### Data Migration
|
||||
|
||||
**Important:** When upgrading to 0.4.0, existing opinions and entity summaries will be deleted. The consolidation engine will automatically create new observations from your existing facts. This is a one-time migration — your raw facts are preserved, and observations will be synthesized from them after the upgrade.
|
||||
|
||||
### Migration Checklist
|
||||
|
||||
**If you were using `types=["opinion"]` in recall:**
|
||||
|
||||
1. Update to `types=["observation"]`
|
||||
2. Observations combine both entity-centric summaries and belief-based insights
|
||||
|
||||
**If you were using `include_entities=True` in recall:**
|
||||
|
||||
1. Entity summaries are now included in observations
|
||||
2. Use `types=["observation"]` to retrieve them
|
||||
|
||||
**If you were relying on confidence scores:**
|
||||
|
||||
1. Use the `based_on` field to access supporting evidence
|
||||
2. The number and recency of supporting facts indicates strength
|
||||
|
||||
**If you were setting `background` on banks:**
|
||||
|
||||
1. The field is now called `mission`
|
||||
2. Existing values are migrated automatically
|
||||
|
||||
**No changes needed for reflect:**
|
||||
|
||||
Observations are automatically included in reflect responses via the `based_on` field.
|
||||
|
||||
---
|
||||
|
||||
## What's Next
|
||||
|
||||
These learning capabilities are the foundation for more sophisticated agent memory capabilities we're exploring:
|
||||
|
||||
- **Temporal reasoning**: Better understanding of how knowledge evolves over time
|
||||
- **Selective consolidation**: Fine-grained control over what gets synthesized into observations
|
||||
- **Consolidation insights**: Visibility into how observations are formed and updated
|
||||
|
||||
---
|
||||
|
||||
**Resources:**
|
||||
- [Recall API](../developer/api/recall) — retrieve observations alongside facts
|
||||
- [Reflect API](../developer/api/reflect) — responses now include supporting observations
|
||||
- [Mental Models API](../developer/api/mental-models) — create and manage curated summaries
|
||||
- [Observations Guide](../developer/observations) — deep dive into knowledge consolidation
|
||||
- [Directives](../developer/api/memory-banks#directives) — hard rules for compliance and guardrails
|
||||
- [Full Changelog](../changelog)
|
||||
3
hindsight-docs/blog/authors.yml
Normal file
3
hindsight-docs/blog/authors.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
hindsight:
|
||||
name: Hindsight Team
|
||||
url: https://github.com/vectorize-io/hindsight
|
||||
|
|
@ -4,7 +4,7 @@ sidebar_position: 3
|
|||
|
||||
# CLI Reference
|
||||
|
||||
The Hindsight CLI provides command-line access to memory operations and bank management. All commands follow the [OpenAPI specification](/api), so you can use `--help` on any command to see all available options.
|
||||
The Hindsight CLI provides command-line access to memory operations and bank management. All commands follow the [OpenAPI specification](/api-reference), so you can use `--help` on any command to see all available options.
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ const config: Config = {
|
|||
{
|
||||
docs: {
|
||||
sidebarPath: './sidebars.ts',
|
||||
editUrl: 'https://github.com/vectorize-io/hindsight/tree/main/hindsight-docs/',
|
||||
routeBasePath: '/',
|
||||
// Only show "next" version in development or when INCLUDE_CURRENT_VERSION=true
|
||||
// In production, only show released versions from versions.json
|
||||
|
|
@ -97,7 +96,14 @@ const config: Config = {
|
|||
return config;
|
||||
})(),
|
||||
},
|
||||
blog: false,
|
||||
blog: {
|
||||
showReadingTime: true,
|
||||
blogTitle: 'Hindsight Blog',
|
||||
blogDescription: 'Updates, insights, and deep dives into agent memory',
|
||||
postsPerPage: 10,
|
||||
blogSidebarTitle: 'Recent posts',
|
||||
blogSidebarCount: 'ALL',
|
||||
},
|
||||
theme: {
|
||||
customCss: './src/css/custom.css',
|
||||
},
|
||||
|
|
@ -151,7 +157,8 @@ const config: Config = {
|
|||
{
|
||||
hashed: true,
|
||||
docsRouteBasePath: '/',
|
||||
indexBlog: false,
|
||||
indexBlog: true,
|
||||
blogRouteBasePath: '/blog',
|
||||
highlightSearchTermsOnTargetPage: false,
|
||||
},
|
||||
],
|
||||
|
|
@ -206,6 +213,12 @@ const config: Config = {
|
|||
label: 'Cookbook',
|
||||
className: 'navbar-item-cookbook',
|
||||
},
|
||||
{
|
||||
to: '/blog',
|
||||
position: 'left',
|
||||
label: 'Blog',
|
||||
className: 'navbar-item-blog',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
docId: 'changelog/index',
|
||||
|
|
|
|||
|
|
@ -38,6 +38,33 @@ for opinion in response.results:
|
|||
# [/docs:opinion-search]
|
||||
|
||||
|
||||
# [docs:recall-opinions-only]
|
||||
# Only retrieve opinions (beliefs and preferences)
|
||||
opinions = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="What are my preferences?",
|
||||
types=["opinion"]
|
||||
)
|
||||
# [/docs:recall-opinions-only]
|
||||
|
||||
|
||||
# [docs:recall-include-entities]
|
||||
# Include entity summaries in recall results
|
||||
response = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="What do I know about Alice?",
|
||||
include_entities=True,
|
||||
max_entity_tokens=500
|
||||
)
|
||||
|
||||
# Results include both facts and entity summaries
|
||||
for result in response.results:
|
||||
print(f"- {result.text}")
|
||||
if hasattr(result, 'entity_summary'):
|
||||
print(f" Entity: {result.entity_summary}")
|
||||
# [/docs:recall-include-entities]
|
||||
|
||||
|
||||
# [docs:opinion-disposition]
|
||||
# Bank disposition affects how opinions are formed
|
||||
# High skepticism = lower confidence, requires more evidence
|
||||
|
|
|
|||
|
|
@ -39,6 +39,16 @@ await client.createBank('financial-advisor', {
|
|||
// [/docs:bank-mission]
|
||||
|
||||
|
||||
// [docs:bank-background]
|
||||
// Legacy snippet for v0.3 docs (background renamed to mission in v0.4)
|
||||
await client.createBank('legacy-bank', {
|
||||
name: 'Legacy Example',
|
||||
mission: `I'm a personal assistant helping a software engineer. I should track their
|
||||
project preferences, coding style, and technology choices.`
|
||||
});
|
||||
// [/docs:bank-background]
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
|
|
|
|||
|
|
@ -43,6 +43,17 @@ client.create_bank(
|
|||
# [/docs:bank-mission]
|
||||
|
||||
|
||||
# [docs:bank-background]
|
||||
# Legacy snippet for v0.3 docs (background renamed to mission in v0.4)
|
||||
client.create_bank(
|
||||
bank_id="legacy-bank",
|
||||
name="Legacy Example",
|
||||
mission="""I'm a personal assistant helping a software engineer. I should track their
|
||||
project preferences, coding style, and technology choices."""
|
||||
)
|
||||
# [/docs:bank-background]
|
||||
|
||||
|
||||
# [docs:bank-with-disposition]
|
||||
client.create_bank(
|
||||
bank_id="architect-bank",
|
||||
|
|
|
|||
|
|
@ -147,6 +147,33 @@ response = client.recall(
|
|||
# [/docs:recall-tags-all]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Legacy snippets for v0.3 docs (kept for backward compatibility)
|
||||
# =============================================================================
|
||||
|
||||
# [docs:recall-opinions-only]
|
||||
# Legacy: opinions replaced by observations in v0.4+
|
||||
# Only retrieve opinions (beliefs and preferences)
|
||||
opinions = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="What are my preferences?",
|
||||
types=["opinion"]
|
||||
)
|
||||
# [/docs:recall-opinions-only]
|
||||
|
||||
|
||||
# [docs:recall-include-entities]
|
||||
# Legacy: entity summaries replaced by observations in v0.4+
|
||||
# Include entity summaries in recall results
|
||||
response = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="What do I know about Alice?",
|
||||
include_entities=True,
|
||||
max_entity_tokens=500
|
||||
)
|
||||
# [/docs:recall-include-entities]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start",
|
||||
"build": "docusaurus build",
|
||||
"build": "INCLUDE_CURRENT_VERSION=true docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
|
|
|
|||
|
|
@ -1247,3 +1247,59 @@ ul[class*="suggestion"] {
|
|||
display: none !important;
|
||||
}
|
||||
|
||||
/* ===== Blog Styling ===== */
|
||||
|
||||
/* Hide TOC sidebar on blog post pages */
|
||||
.blog-post-page .col--3,
|
||||
.blog-post-page [class*="tableOfContents"],
|
||||
.blog-post-page aside[class*="toc"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Make blog post content full width when TOC is hidden */
|
||||
.blog-post-page .col--9 {
|
||||
--ifm-col-width: 100%;
|
||||
max-width: 100%;
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
/* Hide author avatar/icon on blog posts */
|
||||
[class*="blogPostAuthor"] img,
|
||||
[class*="authorImage"],
|
||||
.avatar__photo {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Blog author text visible in dark mode */
|
||||
[data-theme='dark'] [class*="blogPostAuthor"],
|
||||
[data-theme='dark'] [class*="blogPostAuthor"] *,
|
||||
[data-theme='dark'] .avatar__name,
|
||||
[data-theme='dark'] .avatar__name a,
|
||||
[data-theme='dark'] .avatar__subtitle,
|
||||
[data-theme='dark'] [class*="authorName"],
|
||||
[data-theme='dark'] [class*="blogPostData"] a,
|
||||
[data-theme='dark'] [class*="blogPostInfo"] a {
|
||||
color: #e2e8f0 !important;
|
||||
-webkit-text-fill-color: #e2e8f0 !important;
|
||||
}
|
||||
|
||||
/* Blog navbar icon */
|
||||
@media (min-width: 997px) {
|
||||
.navbar-item-blog::before {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 6px;
|
||||
vertical-align: middle;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
content: '';
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath fill='%23666' d='M216 36H40a20 20 0 0 0-20 20v144a20 20 0 0 0 20 20h176a20 20 0 0 0 20-20V56a20 20 0 0 0-20-20Zm-4 160H44V60h168ZM68 92a12 12 0 0 1 12-12h96a12 12 0 0 1 0 24H80a12 12 0 0 1-12-12Zm0 36a12 12 0 0 1 12-12h96a12 12 0 0 1 0 24H80a12 12 0 0 1-12-12Zm0 36a12 12 0 0 1 12-12h96a12 12 0 0 1 0 24H80a12 12 0 0 1-12-12Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
[data-theme='dark'] .navbar-item-blog::before {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath fill='%23ccc' d='M216 36H40a20 20 0 0 0-20 20v144a20 20 0 0 0 20 20h176a20 20 0 0 0 20-20V56a20 20 0 0 0-20-20Zm-4 160H44V60h168ZM68 92a12 12 0 0 1 12-12h96a12 12 0 0 1 0 24H80a12 12 0 0 1-12-12Zm0 36a12 12 0 0 1 12-12h96a12 12 0 0 1 0 24H80a12 12 0 0 1-12-12Zm0 36a12 12 0 0 1 12-12h96a12 12 0 0 1 0 24H80a12 12 0 0 1-12-12Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
["0.3"]
|
||||
[]
|
||||
|
|
|
|||
10
uv.lock
10
uv.lock
|
|
@ -1295,7 +1295,7 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "hindsight-all"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = { editable = "hindsight" }
|
||||
dependencies = [
|
||||
{ name = "hindsight-api" },
|
||||
|
|
@ -1319,7 +1319,7 @@ provides-extras = ["test"]
|
|||
|
||||
[[package]]
|
||||
name = "hindsight-api"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = { editable = "hindsight-api" }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
|
|
@ -1447,7 +1447,7 @@ dev = [
|
|||
|
||||
[[package]]
|
||||
name = "hindsight-client"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = { editable = "hindsight-clients/python" }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
|
|
@ -1481,7 +1481,7 @@ provides-extras = ["test"]
|
|||
|
||||
[[package]]
|
||||
name = "hindsight-dev"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = { editable = "hindsight-dev" }
|
||||
dependencies = [
|
||||
{ name = "hindsight-api" },
|
||||
|
|
@ -1527,7 +1527,7 @@ dev = [
|
|||
|
||||
[[package]]
|
||||
name = "hindsight-embed"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = { editable = "hindsight-embed" }
|
||||
dependencies = [
|
||||
{ name = "httpx" },
|
||||
|
|
|
|||
Loading…
Reference in a new issue