Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,35 @@ const tf = new ThinkFleetMemory({
| `runMonitorTick()` | `POST /projects/:id/lattice/monitor/tick` |
| `getMonitorStatus()` | `GET /projects/:id/lattice/monitor/status` |

### `tf.brains` — marketplace registry

Register, version, and manage the brains a project publishes (a brain = a Brain
Card manifest + a stable `externalId` slug). Once a brain is `PUBLISHED` +
`PUBLIC`, any caller consumes it over the hosted MCP endpoint
(`/brains/:brainId/mcp-server/http`) — an MCP connection, not a REST call, so it
lives outside this resource.

| Method | Endpoint |
| -------------------------- | ----------------------------------------- |
| `create(body)` | `POST /projects/:id/brains` |
| `list(params?)` | `GET /projects/:id/brains` |
| `get(brainId)` | `GET /projects/:id/brains/:brainId` |
| `update(brainId, body)` | `PATCH /projects/:id/brains/:brainId` |
| `delete(brainId)` | `DELETE /projects/:id/brains/:brainId` |

```ts
const brain = await tf.brains.create({
externalId: 'sec-edgar-financials',
name: 'SEC EDGAR Financials',
domain: 'finance',
card: { provenance: [{ source: 'SEC EDGAR', license: 'public-domain' }] },
})
await tf.brains.update(brain.id, { visibility: 'PUBLIC', status: 'PUBLISHED' })

const page = await tf.brains.list({ limit: 20 })
for (const b of page.data) console.log(b.externalId, b.status)
```

---

## Predict anything (v2)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@thinkfleet/memory-sdk",
"version": "0.5.0",
"version": "0.6.0",
"description": "TypeScript SDK for app.memmesh.ai — admin + project memory CRUD, semantic search, feedback, and Lattice behavioral patterns",
"type": "module",
"main": "./dist/index.cjs",
Expand Down
3 changes: 3 additions & 0 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { HttpClient } from './core/http-client.js'
import type { RequestInterceptor, ResponseInterceptor } from './core/types.js'
import { AlertsResource } from './resources/alerts.js'
import { BehaviorsResource } from './resources/behaviors.js'
import { BrainsResource } from './resources/brains.js'
import { ComplianceResource } from './resources/compliance.js'
import { ContextResource } from './resources/context.js'
import { EventsResource } from './resources/events.js'
Expand Down Expand Up @@ -64,6 +65,7 @@ export class ThinkFleetMemory {
readonly health: HealthResource
readonly financial: FinancialResource
readonly typed: TypedAttributesResource
readonly brains: BrainsResource

constructor(options: ThinkFleetMemoryOptions) {
if (!options.apiKey) {
Expand Down Expand Up @@ -95,5 +97,6 @@ export class ThinkFleetMemory {
this.health = new HealthResource(http)
this.financial = new FinancialResource(http)
this.typed = new TypedAttributesResource(http)
this.brains = new BrainsResource(http)
}
}
13 changes: 13 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,19 @@ export type {
} from './resources/learning.js'
export { HealthResource } from './resources/health.js'
export { FinancialResource } from './resources/financial.js'
export { BrainsResource } from './resources/brains.js'

// Types — brain marketplace
export type {
Brain,
BrainCard,
BrainProvenance,
BrainVisibility,
BrainStatus,
CreateBrainRequest,
UpdateBrainRequest,
ListBrainsParams,
} from './types/brain.js'

// Types — financial
export type {
Expand Down
66 changes: 66 additions & 0 deletions src/resources/brains.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import type { HttpClient } from '../core/http-client.js'
import type { RequestOptions, SeekPage } from '../core/types.js'
import type {
Brain,
CreateBrainRequest,
ListBrainsParams,
UpdateBrainRequest,
} from '../types/brain.js'

/**
* Brains — the marketplace registry.
*
* Register, version, and manage the brains a project publishes. A brain carries
* a Brain Card manifest (ontology, provenance, coverage, eval, pricing) and a
* stable `externalId` slug. Once a brain is `PUBLISHED` + `PUBLIC`, any caller
* can consume it over the hosted MCP endpoint
* (`/brains/{brainId}/mcp-server/http`); consumption is an MCP connection, not a
* REST call, so it lives outside this resource.
*
* @example
* ```ts
* const brain = await tf.brains.create({
* externalId: 'sec-edgar-financials',
* name: 'SEC EDGAR Financials',
* domain: 'finance',
* version: '2026.07.0',
* card: { provenance: [{ source: 'SEC EDGAR', license: 'public-domain' }] },
* })
* await tf.brains.update(brain.id, { visibility: 'PUBLIC', status: 'PUBLISHED' })
*
* const page = await tf.brains.list({ limit: 20 })
* for (const b of page.data) console.log(b.externalId, b.status)
* ```
*/
export class BrainsResource {
constructor(private readonly http: HttpClient) {}

/** Register a new brain in the project's catalog. */
async create(body: CreateBrainRequest, options?: RequestOptions): Promise<Brain> {
return this.http.post<Brain>('/brains', body, options)
}

/** List the project's brains (cursor-paginated). */
async list(params?: ListBrainsParams, options?: RequestOptions): Promise<SeekPage<Brain>> {
return this.http.get<SeekPage<Brain>>(
'/brains',
params as Record<string, string | number | boolean | undefined> | undefined,
options,
)
}

/** Fetch one brain by id. */
async get(brainId: string, options?: RequestOptions): Promise<Brain> {
return this.http.get<Brain>(`/brains/${brainId}`, undefined, options)
}

/** Update / version a brain (name, version, visibility, status, card, …). */
async update(brainId: string, body: UpdateBrainRequest, options?: RequestOptions): Promise<Brain> {
return this.http.patch<Brain>(`/brains/${brainId}`, body, options)
}

/** Delete a brain from the catalog. */
async delete(brainId: string, options?: RequestOptions): Promise<void> {
await this.http.delete<{ success: boolean }>(`/brains/${brainId}`, options)
}
}
73 changes: 73 additions & 0 deletions src/types/brain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import type { BaseModel } from './common.js'

/**
* Brain marketplace types.
*
* A Brain is a publishable/consumable unit of memory: a Brain Card manifest
* plus a stable `externalId` slug the Mesh Router addresses it by. This SDK
* covers the registry (create / list / get / update / delete). Consumption of a
* published brain happens over the hosted MCP endpoint
* (`/api/v1/projects/{projectId}/brains/{brainId}/mcp-server/http`), which an
* MCP client connects to directly — it is not a REST call.
*/

export type BrainVisibility = 'PUBLIC' | 'UNLISTED' | 'PRIVATE'
export type BrainStatus = 'DRAFT' | 'PUBLISHED' | 'ARCHIVED'

/** Provenance of the facts in a brain — where they came from and under what license. */
export interface BrainProvenance {
source: string
license: string
url?: string
}

/** The Brain Card manifest (stored on the brain, surfaced in the catalog). */
export interface BrainCard {
ontologyRef?: string
provenance?: BrainProvenance[]
changelogRef?: string
coverage?: { subjects?: number; facts?: number; freshness?: string }
evaluation?: { benchmark?: string; score?: number }
predictEnabled?: boolean
pricing?: { model?: string; unit?: string }
}

export interface Brain extends BaseModel {
projectId: string
/** Stable slug the Router addresses the brain by (unique per project). */
externalId: string
name: string
domain: string | null
/** Brain Interface contract version the brain conforms to (e.g. "v1"). */
brainInterface: string
version: string
visibility: BrainVisibility
status: BrainStatus
rightsAttested: boolean
card: BrainCard | null
}

export interface CreateBrainRequest {
externalId: string
name: string
domain?: string
version?: string
visibility?: BrainVisibility
rightsAttested?: boolean
card?: BrainCard
}

export interface UpdateBrainRequest {
name?: string
domain?: string
version?: string
visibility?: BrainVisibility
status?: BrainStatus
rightsAttested?: boolean
card?: BrainCard
}

export interface ListBrainsParams {
limit?: number
cursor?: string
}
Loading