diff --git a/docs/api-reference/dream/dream-preview.mdx b/docs/api-reference/dream/dream-preview.mdx new file mode 100644 index 000000000..68154f08a --- /dev/null +++ b/docs/api-reference/dream/dream-preview.mdx @@ -0,0 +1,5 @@ +--- +title: "Preview Dream Scope" +description: "A no-write preview of the scope Dream synthesis would analyze for a project." +openapi: "post /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/preview/" +--- diff --git a/docs/api-reference/dream/get-dream-activity.mdx b/docs/api-reference/dream/get-dream-activity.mdx new file mode 100644 index 000000000..9d9c43a25 --- /dev/null +++ b/docs/api-reference/dream/get-dream-activity.mdx @@ -0,0 +1,5 @@ +--- +title: "Get Dream Activity" +description: "Supersede/merge activity feed for a project, newest first (keyset-paginated)." +openapi: "get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/activity/" +--- diff --git a/docs/api-reference/dream/get-dream-config.mdx b/docs/api-reference/dream/get-dream-config.mdx new file mode 100644 index 000000000..26389fc6a --- /dev/null +++ b/docs/api-reference/dream/get-dream-config.mdx @@ -0,0 +1,5 @@ +--- +title: "Get Dream Configuration" +description: "Retrieve a project's Dream (memory synthesis) configuration and plan entitlements." +openapi: "get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/config/" +--- diff --git a/docs/api-reference/dream/get-dream-memory-sources.mdx b/docs/api-reference/dream/get-dream-memory-sources.mdx new file mode 100644 index 000000000..6b7d44ae9 --- /dev/null +++ b/docs/api-reference/dream/get-dream-memory-sources.mdx @@ -0,0 +1,5 @@ +--- +title: "Get a Synthesized Memory's Sources" +description: "The source memories a synthesized (pattern) memory was distilled from." +openapi: "get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/memory/{memory_id}/sources/" +--- diff --git a/docs/api-reference/dream/get-dream-run-memories.mdx b/docs/api-reference/dream/get-dream-run-memories.mdx new file mode 100644 index 000000000..8652fe5b4 --- /dev/null +++ b/docs/api-reference/dream/get-dream-run-memories.mdx @@ -0,0 +1,5 @@ +--- +title: "Get Memories in a Dream Run" +description: "Keyset page of the synthesized memories within a single synthesis run." +openapi: "get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/runs/{run_id}/memories/" +--- diff --git a/docs/api-reference/dream/get-dream-runs.mdx b/docs/api-reference/dream/get-dream-runs.mdx new file mode 100644 index 000000000..9b41aa9a1 --- /dev/null +++ b/docs/api-reference/dream/get-dream-runs.mdx @@ -0,0 +1,5 @@ +--- +title: "Get Dream Synthesis Runs" +description: "Synthesis activity grouped per run, newest first (keyset-paginated)." +openapi: "get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/runs/" +--- diff --git a/docs/api-reference/dream/get-dream-stats.mdx b/docs/api-reference/dream/get-dream-stats.mdx new file mode 100644 index 000000000..0dccf287d --- /dev/null +++ b/docs/api-reference/dream/get-dream-stats.mdx @@ -0,0 +1,5 @@ +--- +title: "Get Dream Stats" +description: "Lifecycle and synthesis counts for a project, plus reflection freshness." +openapi: "get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/stats/" +--- diff --git a/docs/api-reference/dream/update-dream-config.mdx b/docs/api-reference/dream/update-dream-config.mdx new file mode 100644 index 000000000..4abd1c91f --- /dev/null +++ b/docs/api-reference/dream/update-dream-config.mdx @@ -0,0 +1,5 @@ +--- +title: "Update Dream Configuration" +description: "Enable or disable Synthesis (reflection) for a project, or change the reflection mode." +openapi: "patch /api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/config/" +--- diff --git a/docs/docs.json b/docs/docs.json index e4f2630a3..5be90c28c 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -539,6 +539,20 @@ "api-reference/project/delete-project" ] }, + { + "group": "Dream", + "icon": "sparkles", + "pages": [ + "api-reference/dream/get-dream-config", + "api-reference/dream/update-dream-config", + "api-reference/dream/get-dream-stats", + "api-reference/dream/get-dream-activity", + "api-reference/dream/get-dream-runs", + "api-reference/dream/get-dream-run-memories", + "api-reference/dream/get-dream-memory-sources", + "api-reference/dream/dream-preview" + ] + }, { "group": "Webhooks", "icon": "webhook", diff --git a/docs/openapi.json b/docs/openapi.json index 4b8cf0378..e760544c4 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -7207,6 +7207,855 @@ } ] } + }, + "/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/config/": { + "get": { + "tags": [ + "dream" + ], + "summary": "Get Dream configuration", + "description": "Retrieve the project's Dream (memory synthesis) configuration together with the plan entitlement snapshot. Dream automatically supersedes/merges memories on the add path; **Synthesis** (reflection) is the opt-in part controlled by `reflection_enabled`.", + "operationId": "get_dream_config", + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "description": "Unique identifier of the organization.", + "schema": { + "type": "string" + } + }, + { + "name": "project_id", + "in": "path", + "required": true, + "description": "Unique identifier of the project.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "config": { + "type": "object", + "properties": { + "reflection_enabled": { + "type": "boolean", + "description": "Whether background synthesis (reflection) is enabled for the project." + }, + "reflection_enabled_at": { + "type": "string", + "description": "When synthesis was last enabled. Synthesis only considers memories created on or after this time (forward-only).", + "format": "date-time", + "nullable": true + }, + "reflection_mode": { + "type": "string", + "description": "Synthesis execution mode.", + "enum": [ + "batch", + "direct" + ] + } + } + }, + "entitlements": { + "type": "object", + "properties": { + "plan": { + "type": "string", + "description": "Resolved billing tier for the project (e.g. `free`, `pro`, `custom`)." + }, + "reflection_interval_days": { + "type": "integer", + "description": "How often synthesis runs for this plan, in days (Pro weekly, Enterprise daily)." + }, + "features": { + "type": "object", + "properties": {}, + "description": "Per-feature entitlement snapshot, keyed by Dream feature (e.g. `dream_reflection`, `dream_tab`, `dream_preview`).", + "additionalProperties": { + "type": "object", + "properties": { + "entitled": { + "type": "boolean", + "description": "Whether the plan is entitled to the feature." + }, + "killed": { + "type": "boolean", + "description": "Whether the feature is globally disabled by a kill switch." + }, + "enabled": { + "type": "boolean", + "description": "Effective state: entitled AND not killed AND turned on." + } + } + } + } + } + } + } + } + } + } + } + } + }, + "patch": { + "tags": [ + "dream" + ], + "summary": "Update Dream configuration", + "description": "Enable or disable Synthesis (reflection) for the project, or change the reflection mode. Requires a Pro or Enterprise (CUSTOM) plan and organization-owner permission. Synthesis is forward-only: after enabling, it only synthesizes memories added from that point on.", + "operationId": "update_dream_config", + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "description": "Unique identifier of the organization.", + "schema": { + "type": "string" + } + }, + { + "name": "project_id", + "in": "path", + "required": true, + "description": "Unique identifier of the project.", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "reflection_enabled": { + "type": "boolean", + "description": "Turn background synthesis on or off." + }, + "reflection_mode": { + "type": "string", + "description": "Synthesis execution mode.", + "enum": [ + "batch", + "direct" + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Updated configuration.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "config": { + "type": "object", + "properties": { + "reflection_enabled": { + "type": "boolean", + "description": "Whether background synthesis (reflection) is enabled for the project." + }, + "reflection_enabled_at": { + "type": "string", + "description": "When synthesis was last enabled. Synthesis only considers memories created on or after this time (forward-only).", + "format": "date-time", + "nullable": true + }, + "reflection_mode": { + "type": "string", + "description": "Synthesis execution mode.", + "enum": [ + "batch", + "direct" + ] + } + } + }, + "entitlements": { + "type": "object", + "properties": { + "plan": { + "type": "string", + "description": "Resolved billing tier for the project (e.g. `free`, `pro`, `custom`)." + }, + "reflection_interval_days": { + "type": "integer", + "description": "How often synthesis runs for this plan, in days (Pro weekly, Enterprise daily)." + }, + "features": { + "type": "object", + "properties": {}, + "description": "Per-feature entitlement snapshot, keyed by Dream feature (e.g. `dream_reflection`, `dream_tab`, `dream_preview`).", + "additionalProperties": { + "type": "object", + "properties": { + "entitled": { + "type": "boolean", + "description": "Whether the plan is entitled to the feature." + }, + "killed": { + "type": "boolean", + "description": "Whether the feature is globally disabled by a kill switch." + }, + "enabled": { + "type": "boolean", + "description": "Effective state: entitled AND not killed AND turned on." + } + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Validation error (e.g. a field the plan is not entitled to change)." + }, + "403": { + "description": "Not entitled on the current plan (`upgrade_required: true`), or the caller is not an organization owner." + } + } + } + }, + "/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/stats/": { + "get": { + "tags": [ + "dream" + ], + "summary": "Get Dream stats", + "description": "Lifecycle + synthesis counts for the project's Dream dashboard, plus reflection freshness. Requires a Pro or Enterprise (CUSTOM) plan.", + "operationId": "get_dream_stats", + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "description": "Unique identifier of the organization.", + "schema": { + "type": "string" + } + }, + { + "name": "project_id", + "in": "path", + "required": true, + "description": "Unique identifier of the project.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "active": { + "type": "integer", + "description": "Active (current) memory count." + }, + "merged": { + "type": "integer", + "description": "Count of memories merged into a canonical one." + }, + "superseded": { + "type": "integer", + "description": "Count of memories superseded by a newer one." + }, + "synthesized": { + "type": "integer", + "description": "Count of higher-order pattern memories created by synthesis." + }, + "last_run_at": { + "type": "string", + "description": "When synthesis last completed.", + "format": "date-time", + "nullable": true + }, + "processed_through": { + "type": "string", + "description": "Timestamp of the newest source memory synthesis has processed.", + "format": "date-time", + "nullable": true + }, + "running": { + "type": "boolean", + "description": "Whether a synthesis run is currently in flight." + }, + "next_run_at": { + "type": "string", + "description": "Projected next synthesis run.", + "format": "date-time", + "nullable": true + } + } + } + } + } + }, + "403": { + "description": "Not entitled on the current plan (`upgrade_required: true`)." + } + } + } + }, + "/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/activity/": { + "get": { + "tags": [ + "dream" + ], + "summary": "Get Dream activity", + "description": "Supersede/merge activity feed (newest first), keyset-paginated. Synthesis output is not included here — see the runs endpoint.", + "operationId": "get_dream_activity", + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "description": "Unique identifier of the organization.", + "schema": { + "type": "string" + } + }, + { + "name": "project_id", + "in": "path", + "required": true, + "description": "Unique identifier of the project.", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Page size (default 50, max 200).", + "schema": { + "type": "integer", + "default": 50 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque keyset cursor from a previous page's `next_cursor`.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "memory_id": { + "type": "string", + "description": "The superseded/merged memory's ID." + }, + "text": { + "type": "string", + "description": "The memory's text (truncated)." + }, + "transition": { + "type": "string", + "description": "Lifecycle transition.", + "enum": [ + "merged", + "superseded" + ] + }, + "at": { + "type": "string", + "description": "When the transition happened.", + "format": "date-time" + }, + "replaced_by": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "ID of the newer memory." + }, + "text": { + "type": "string", + "description": "Text of the newer memory (truncated).", + "nullable": true + } + }, + "nullable": true, + "description": "The newer memory that replaced this one (null for a merge with no single replacement)." + }, + "sources": { + "type": "null", + "description": "Always null on this feed (present for schema parity with runs)." + } + } + } + }, + "next_cursor": { + "type": "string", + "description": "Cursor for the next page, or null when there are no more.", + "nullable": true + } + } + } + } + } + } + } + } + }, + "/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/runs/": { + "get": { + "tags": [ + "dream" + ], + "summary": "Get Dream synthesis runs", + "description": "Synthesis activity grouped per run (newest first), keyset-paginated. Each run inlines its first page of synthesized memories with their sources; larger runs page the rest via the run-memories endpoint.", + "operationId": "get_dream_runs", + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "description": "Unique identifier of the organization.", + "schema": { + "type": "string" + } + }, + { + "name": "project_id", + "in": "path", + "required": true, + "description": "Unique identifier of the project.", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Number of runs per page (default 20, max 100).", + "schema": { + "type": "integer", + "default": 20 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque keyset cursor from a previous page's `next_cursor`.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "run_id": { + "type": "string", + "description": "Identifier of the synthesis run." + }, + "at": { + "type": "string", + "description": "When the run produced memories.", + "format": "date-time" + }, + "count": { + "type": "integer", + "description": "Total synthesized memories in this run." + }, + "synthesized": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Synthesized memory ID." + }, + "text": { + "type": "string", + "description": "Synthesized (pattern) memory text." + }, + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Source memory ID." + }, + "text": { + "type": "string", + "description": "Source memory text (truncated)." + } + } + }, + "description": "Source memories this pattern was distilled from." + } + } + }, + "description": "First page of synthesized memories (each with its sources)." + }, + "has_more": { + "type": "boolean", + "description": "Whether the run has more memories than are inlined here." + }, + "mem_cursor": { + "type": "string", + "description": "Cursor to page this run's remaining memories via the run-memories endpoint.", + "nullable": true + }, + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Source memory ID." + }, + "text": { + "type": "string", + "description": "Source memory text (truncated)." + } + } + }, + "description": "De-duplicated source memories across the inlined page." + } + } + } + }, + "next_cursor": { + "type": "string", + "description": "Cursor for the next page, or null when there are no more.", + "nullable": true + } + } + } + } + } + } + } + } + }, + "/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/runs/{run_id}/memories/": { + "get": { + "tags": [ + "dream" + ], + "summary": "Get memories in a Dream run", + "description": "Keyset page of the synthesized memories within a single run (for runs whose `has_more` is true).", + "operationId": "get_dream_run_memories", + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "description": "Unique identifier of the organization.", + "schema": { + "type": "string" + } + }, + { + "name": "project_id", + "in": "path", + "required": true, + "description": "Unique identifier of the project.", + "schema": { + "type": "string" + } + }, + { + "name": "run_id", + "in": "path", + "required": true, + "description": "Identifier of the synthesis run.", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Page size (default 50, max 200).", + "schema": { + "type": "integer", + "default": 50 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque keyset cursor (use the run's `mem_cursor` or a previous `next_cursor`).", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Synthesized memory ID." + }, + "text": { + "type": "string", + "description": "Synthesized (pattern) memory text." + }, + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Source memory ID." + }, + "text": { + "type": "string", + "description": "Source memory text (truncated)." + } + } + }, + "description": "Source memories this pattern was distilled from." + } + } + } + }, + "next_cursor": { + "type": "string", + "description": "Cursor for the next page, or null when there are no more.", + "nullable": true + } + } + } + } + } + } + } + } + }, + "/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/memory/{memory_id}/sources/": { + "get": { + "tags": [ + "dream" + ], + "summary": "Get a synthesized memory's sources", + "description": "The source memories a synthesized (pattern) memory was distilled from, for the memory drawer's provenance panel.", + "operationId": "get_dream_memory_sources", + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "description": "Unique identifier of the organization.", + "schema": { + "type": "string" + } + }, + { + "name": "project_id", + "in": "path", + "required": true, + "description": "Unique identifier of the project.", + "schema": { + "type": "string" + } + }, + { + "name": "memory_id", + "in": "path", + "required": true, + "description": "ID of the (synthesized) memory.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "memory_id": { + "type": "string", + "description": "The memory's ID." + }, + "synthesized": { + "type": "boolean", + "description": "Whether this memory was produced by synthesis." + }, + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Source memory ID." + }, + "text": { + "type": "string", + "description": "Source memory text." + }, + "lifecycle_state": { + "type": "string", + "description": "Source memory lifecycle state.", + "enum": [ + "active", + "merged", + "superseded" + ] + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Memory not found in this project." + } + } + } + }, + "/api/v1/orgs/organizations/{org_id}/projects/{project_id}/dream/preview/": { + "post": { + "tags": [ + "dream" + ], + "summary": "Preview Dream scope", + "description": "A no-write preview of the scope Dream synthesis would analyze for the project (a capped sample plus the count of users with enough memories to benefit). Never runs the LLM and never mutates anything.", + "operationId": "dream_preview", + "parameters": [ + { + "name": "org_id", + "in": "path", + "required": true, + "description": "Unique identifier of the organization.", + "schema": { + "type": "string" + } + }, + { + "name": "project_id", + "in": "path", + "required": true, + "description": "Unique identifier of the project.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "active_total": { + "type": "integer", + "description": "Total active memories in the project." + }, + "scanned": { + "type": "integer", + "description": "How many recent memories the preview aggregated over (capped)." + }, + "cap": { + "type": "integer", + "description": "The scan cap applied." + }, + "eligible_users": { + "type": "integer", + "description": "Users with enough memories to benefit from synthesis." + }, + "note": { + "type": "string", + "description": "Human-readable note about the preview scope." + } + } + } + } + } + }, + "403": { + "description": "Preview not available on the current plan (`upgrade_required: true`)." + } + } + } } }, "components": {