fix agnts
This commit is contained in:
parent
3f22dfcad4
commit
f521b36f9f
8 changed files with 109 additions and 201 deletions
|
|
@ -31,3 +31,38 @@ export async function GET(request: NextRequest) {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(request: NextRequest) {
|
||||
try {
|
||||
const searchParams = request.nextUrl.searchParams;
|
||||
const agentId = searchParams.get('agent_id');
|
||||
const unitId = searchParams.get('unit_id');
|
||||
|
||||
if (!agentId) {
|
||||
return NextResponse.json(
|
||||
{ error: 'agent_id is required' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
if (!unitId) {
|
||||
return NextResponse.json(
|
||||
{ error: 'unit_id is required' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
`${DATAPLANE_URL}/api/v1/agents/${agentId}/memories/${unitId}`,
|
||||
{ method: 'DELETE' }
|
||||
);
|
||||
const data = await response.json();
|
||||
return NextResponse.json(data, { status: response.status });
|
||||
} catch (error) {
|
||||
console.error('Error deleting memory unit:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to delete memory unit' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,3 +19,34 @@ export async function GET(
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ agentId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { agentId } = await params;
|
||||
const searchParams = request.nextUrl.searchParams;
|
||||
const operationId = searchParams.get('operation_id');
|
||||
|
||||
if (!operationId) {
|
||||
return NextResponse.json(
|
||||
{ error: 'operation_id is required' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
`${DATAPLANE_URL}/api/v1/agents/${agentId}/operations/${operationId}`,
|
||||
{ method: 'DELETE' }
|
||||
);
|
||||
const data = await response.json();
|
||||
return NextResponse.json(data, { status: response.status });
|
||||
} catch (error) {
|
||||
console.error('Error canceling operation:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to cancel operation' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ export function AgentProvider({ children }: { children: React.ReactNode }) {
|
|||
const loadAgents = async () => {
|
||||
try {
|
||||
const data = await dataplaneClient.listAgents();
|
||||
setAgents(data.agents);
|
||||
// Extract agent_id from each agent object
|
||||
const agentIds = data.agents.map((agent: any) => agent.agent_id);
|
||||
setAgents(agentIds);
|
||||
} catch (error) {
|
||||
console.error('Error loading agents:', error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,10 +36,9 @@ export class DataplaneClient {
|
|||
reranker?: string;
|
||||
trace?: boolean;
|
||||
}) {
|
||||
const { agent_id, ...body } = params;
|
||||
return this.fetchApi(`/api/v1/agents/${agent_id}/memories/search`, {
|
||||
return this.fetchApi(`/api/search`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -51,10 +50,9 @@ export class DataplaneClient {
|
|||
agent_id: string;
|
||||
thinking_budget?: number;
|
||||
}) {
|
||||
const { agent_id, ...body } = params;
|
||||
return this.fetchApi(`/api/v1/agents/${agent_id}/think`, {
|
||||
return this.fetchApi(`/api/think`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -70,10 +68,9 @@ export class DataplaneClient {
|
|||
}>;
|
||||
document_id?: string;
|
||||
}) {
|
||||
const { agent_id, ...body } = params;
|
||||
return this.fetchApi(`/api/v1/agents/${agent_id}/memories`, {
|
||||
return this.fetchApi(`/api/memories/batch`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -90,10 +87,9 @@ export class DataplaneClient {
|
|||
}>;
|
||||
document_id?: string;
|
||||
}) {
|
||||
const { agent_id, ...body } = params;
|
||||
return this.fetchApi(`/api/v1/agents/${agent_id}/memories/async`, {
|
||||
return this.fetchApi(`/api/memories/batch_async`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -101,14 +97,14 @@ export class DataplaneClient {
|
|||
* List all agents
|
||||
*/
|
||||
async listAgents() {
|
||||
return this.fetchApi<{ agents: any[] }>('/api/v1/agents', { cache: 'no-store' });
|
||||
return this.fetchApi<{ agents: any[] }>('/api/agents', { cache: 'no-store' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Get agent statistics
|
||||
*/
|
||||
async getAgentStats(agentId: string) {
|
||||
return this.fetchApi(`/api/v1/agents/${agentId}/stats`);
|
||||
return this.fetchApi(`/api/stats/${agentId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -119,10 +115,10 @@ export class DataplaneClient {
|
|||
fact_type?: string;
|
||||
}) {
|
||||
const queryParams = new URLSearchParams();
|
||||
queryParams.append('agent_id', params.agent_id);
|
||||
if (params.fact_type) queryParams.append('fact_type', params.fact_type);
|
||||
|
||||
const path = `/api/v1/agents/${params.agent_id}/graph${queryParams.toString() ? `?${queryParams}` : ''}`;
|
||||
return this.fetchApi(path);
|
||||
return this.fetchApi(`/api/graph?${queryParams}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -136,13 +132,13 @@ export class DataplaneClient {
|
|||
offset?: number;
|
||||
}) {
|
||||
const queryParams = new URLSearchParams();
|
||||
queryParams.append('agent_id', params.agent_id);
|
||||
if (params.fact_type) queryParams.append('fact_type', params.fact_type);
|
||||
if (params.q) queryParams.append('q', params.q);
|
||||
if (params.limit) queryParams.append('limit', params.limit.toString());
|
||||
if (params.offset) queryParams.append('offset', params.offset.toString());
|
||||
|
||||
const path = `/api/v1/agents/${params.agent_id}/memories/list${queryParams.toString() ? `?${queryParams}` : ''}`;
|
||||
return this.fetchApi(path);
|
||||
return this.fetchApi(`/api/list?${queryParams}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -155,33 +151,33 @@ export class DataplaneClient {
|
|||
offset?: number;
|
||||
}) {
|
||||
const queryParams = new URLSearchParams();
|
||||
queryParams.append('agent_id', params.agent_id);
|
||||
if (params.q) queryParams.append('q', params.q);
|
||||
if (params.limit) queryParams.append('limit', params.limit.toString());
|
||||
if (params.offset) queryParams.append('offset', params.offset.toString());
|
||||
|
||||
const path = `/api/v1/agents/${params.agent_id}/documents${queryParams.toString() ? `?${queryParams}` : ''}`;
|
||||
return this.fetchApi(path);
|
||||
return this.fetchApi(`/api/documents?${queryParams}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get document by ID
|
||||
*/
|
||||
async getDocument(documentId: string, agentId: string) {
|
||||
return this.fetchApi(`/api/v1/agents/${agentId}/documents/${documentId}`);
|
||||
return this.fetchApi(`/api/documents/${documentId}?agent_id=${agentId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* List async operations for an agent
|
||||
*/
|
||||
async listOperations(agentId: string) {
|
||||
return this.fetchApi(`/api/v1/agents/${agentId}/operations`);
|
||||
return this.fetchApi(`/api/operations/${agentId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel a pending async operation
|
||||
*/
|
||||
async cancelOperation(agentId: string, operationId: string) {
|
||||
return this.fetchApi(`/api/v1/agents/${agentId}/operations/${operationId}`, {
|
||||
return this.fetchApi(`/api/operations/${agentId}?operation_id=${operationId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
|
@ -190,7 +186,7 @@ export class DataplaneClient {
|
|||
* Delete a memory unit
|
||||
*/
|
||||
async deleteMemoryUnit(agentId: string, unitId: string) {
|
||||
return this.fetchApi(`/api/v1/agents/${agentId}/memories/${unitId}`, {
|
||||
return this.fetchApi(`/api/list?agent_id=${agentId}&unit_id=${unitId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,147 +0,0 @@
|
|||
# A generic, single database configuration.
|
||||
|
||||
[alembic]
|
||||
# path to migration scripts.
|
||||
# this is typically a path given in POSIX (e.g. forward slashes)
|
||||
# format, relative to the token %(here)s which refers to the location of this
|
||||
# ini file
|
||||
script_location = %(here)s/alembic
|
||||
|
||||
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
|
||||
# Uncomment the line below if you want the files to be prepended with date and time
|
||||
# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file
|
||||
# for all available tokens
|
||||
# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
|
||||
|
||||
# sys.path path, will be prepended to sys.path if present.
|
||||
# defaults to the current working directory. for multiple paths, the path separator
|
||||
# is defined by "path_separator" below.
|
||||
prepend_sys_path = .
|
||||
|
||||
|
||||
# timezone to use when rendering the date within the migration file
|
||||
# as well as the filename.
|
||||
# If specified, requires the tzdata library which can be installed by adding
|
||||
# `alembic[tz]` to the pip requirements.
|
||||
# string value is passed to ZoneInfo()
|
||||
# leave blank for localtime
|
||||
# timezone =
|
||||
|
||||
# max length of characters to apply to the "slug" field
|
||||
# truncate_slug_length = 40
|
||||
|
||||
# set to 'true' to run the environment during
|
||||
# the 'revision' command, regardless of autogenerate
|
||||
# revision_environment = false
|
||||
|
||||
# set to 'true' to allow .pyc and .pyo files without
|
||||
# a source .py file to be detected as revisions in the
|
||||
# versions/ directory
|
||||
# sourceless = false
|
||||
|
||||
# version location specification; This defaults
|
||||
# to <script_location>/versions. When using multiple version
|
||||
# directories, initial revisions must be specified with --version-path.
|
||||
# The path separator used here should be the separator specified by "path_separator"
|
||||
# below.
|
||||
# version_locations = %(here)s/bar:%(here)s/bat:%(here)s/alembic/versions
|
||||
|
||||
# path_separator; This indicates what character is used to split lists of file
|
||||
# paths, including version_locations and prepend_sys_path within configparser
|
||||
# files such as alembic.ini.
|
||||
# The default rendered in new alembic.ini files is "os", which uses os.pathsep
|
||||
# to provide os-dependent path splitting.
|
||||
#
|
||||
# Note that in order to support legacy alembic.ini files, this default does NOT
|
||||
# take place if path_separator is not present in alembic.ini. If this
|
||||
# option is omitted entirely, fallback logic is as follows:
|
||||
#
|
||||
# 1. Parsing of the version_locations option falls back to using the legacy
|
||||
# "version_path_separator" key, which if absent then falls back to the legacy
|
||||
# behavior of splitting on spaces and/or commas.
|
||||
# 2. Parsing of the prepend_sys_path option falls back to the legacy
|
||||
# behavior of splitting on spaces, commas, or colons.
|
||||
#
|
||||
# Valid values for path_separator are:
|
||||
#
|
||||
# path_separator = :
|
||||
# path_separator = ;
|
||||
# path_separator = space
|
||||
# path_separator = newline
|
||||
#
|
||||
# Use os.pathsep. Default configuration used for new projects.
|
||||
path_separator = os
|
||||
|
||||
# set to 'true' to search source files recursively
|
||||
# in each "version_locations" directory
|
||||
# new in Alembic version 1.10
|
||||
# recursive_version_locations = false
|
||||
|
||||
# the output encoding used when revision files
|
||||
# are written from script.py.mako
|
||||
# output_encoding = utf-8
|
||||
|
||||
# database URL. This is consumed by the user-maintained env.py script only.
|
||||
# other means of configuring database URLs may be customized within the env.py
|
||||
# file.
|
||||
# sqlalchemy.url = driver://user:pass@localhost/dbname # Disabled, using DATABASE_URL from .env
|
||||
|
||||
|
||||
[post_write_hooks]
|
||||
# post_write_hooks defines scripts or Python functions that are run
|
||||
# on newly generated revision scripts. See the documentation for further
|
||||
# detail and examples
|
||||
|
||||
# format using "black" - use the console_scripts runner, against the "black" entrypoint
|
||||
# hooks = black
|
||||
# black.type = console_scripts
|
||||
# black.entrypoint = black
|
||||
# black.options = -l 79 REVISION_SCRIPT_FILENAME
|
||||
|
||||
# lint with attempts to fix using "ruff" - use the module runner, against the "ruff" module
|
||||
# hooks = ruff
|
||||
# ruff.type = module
|
||||
# ruff.module = ruff
|
||||
# ruff.options = check --fix REVISION_SCRIPT_FILENAME
|
||||
|
||||
# Alternatively, use the exec runner to execute a binary found on your PATH
|
||||
# hooks = ruff
|
||||
# ruff.type = exec
|
||||
# ruff.executable = ruff
|
||||
# ruff.options = check --fix REVISION_SCRIPT_FILENAME
|
||||
|
||||
# Logging configuration. This is also consumed by the user-maintained
|
||||
# env.py script only.
|
||||
[loggers]
|
||||
keys = root,sqlalchemy,alembic
|
||||
|
||||
[handlers]
|
||||
keys = console
|
||||
|
||||
[formatters]
|
||||
keys = generic
|
||||
|
||||
[logger_root]
|
||||
level = WARNING
|
||||
handlers = console
|
||||
qualname =
|
||||
|
||||
[logger_sqlalchemy]
|
||||
level = WARNING
|
||||
handlers =
|
||||
qualname = sqlalchemy.engine
|
||||
|
||||
[logger_alembic]
|
||||
level = INFO
|
||||
handlers =
|
||||
qualname = alembic
|
||||
|
||||
[handler_console]
|
||||
class = StreamHandler
|
||||
args = (sys.stderr,)
|
||||
level = NOTSET
|
||||
formatter = generic
|
||||
|
||||
[formatter_generic]
|
||||
format = %(levelname)-5.5s [%(name)s] %(message)s
|
||||
datefmt = %H:%M:%S
|
||||
|
|
@ -61,7 +61,6 @@ class SearchResult(BaseModel):
|
|||
id: str
|
||||
text: str
|
||||
type: Optional[str] = None # fact type: world, agent, opinion
|
||||
activation: Optional[float] = None
|
||||
context: Optional[str] = None
|
||||
event_date: Optional[str] = None # ISO format date string
|
||||
|
||||
|
|
@ -79,7 +78,6 @@ class SearchResponse(BaseModel):
|
|||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"text": "Alice works at Google on the AI team",
|
||||
"type": "world",
|
||||
"activation": 0.95,
|
||||
"context": "work info",
|
||||
"event_date": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
|
|
@ -201,7 +199,6 @@ class ThinkFact(BaseModel):
|
|||
id: Optional[str] = None
|
||||
text: str
|
||||
type: Optional[str] = None # fact type: world, agent, opinion
|
||||
activation: Optional[float] = None
|
||||
context: Optional[str] = None
|
||||
event_date: Optional[str] = None
|
||||
|
||||
|
|
@ -231,14 +228,12 @@ class ThinkResponse(BaseModel):
|
|||
{
|
||||
"id": "123",
|
||||
"text": "AI is used in healthcare",
|
||||
"type": "world",
|
||||
"activation": 0.9
|
||||
"type": "world"
|
||||
},
|
||||
{
|
||||
"id": "456",
|
||||
"text": "I discussed AI applications last week",
|
||||
"type": "agent",
|
||||
"activation": 0.85
|
||||
"type": "agent"
|
||||
}
|
||||
],
|
||||
"new_opinions": [
|
||||
|
|
|
|||
|
|
@ -799,6 +799,21 @@ class TemporalSemanticMemory(
|
|||
async with conn.transaction():
|
||||
logger.debug("Inside transaction")
|
||||
try:
|
||||
# Ensure agent exists in agents table (create with defaults if not exists)
|
||||
# Update updated_at to reflect recent activity
|
||||
logger.debug(f"Ensuring agent '{agent_id}' exists in agents table")
|
||||
await conn.execute(
|
||||
"""
|
||||
INSERT INTO agents (agent_id, personality, background)
|
||||
VALUES ($1, $2::jsonb, $3)
|
||||
ON CONFLICT (agent_id) DO UPDATE
|
||||
SET updated_at = NOW()
|
||||
""",
|
||||
agent_id,
|
||||
'{"openness": 0.5, "conscientiousness": 0.5, "extraversion": 0.5, "agreeableness": 0.5, "neuroticism": 0.5, "bias_strength": 0.5}',
|
||||
""
|
||||
)
|
||||
|
||||
# Handle document tracking with automatic upsert
|
||||
if document_id:
|
||||
logger.debug(f"Handling document tracking for {document_id}")
|
||||
|
|
@ -1593,25 +1608,6 @@ class TemporalSemanticMemory(
|
|||
except Exception as e:
|
||||
raise Exception(f"Failed to delete agent data: {str(e)}")
|
||||
|
||||
async def list_agents(self) -> List[str]:
|
||||
"""
|
||||
Get list of all agent IDs in the database.
|
||||
|
||||
Returns:
|
||||
List of agent IDs
|
||||
"""
|
||||
pool = await self._get_pool()
|
||||
async with pool.acquire() as conn:
|
||||
# Get distinct agent IDs from memory_units
|
||||
agents = await conn.fetch("""
|
||||
SELECT DISTINCT agent_id
|
||||
FROM memory_units
|
||||
WHERE agent_id IS NOT NULL
|
||||
ORDER BY agent_id
|
||||
""")
|
||||
|
||||
return [row['agent_id'] for row in agents]
|
||||
|
||||
async def get_graph_data(self, agent_id: Optional[str] = None, fact_type: Optional[str] = None):
|
||||
"""
|
||||
Get graph data for visualization.
|
||||
|
|
|
|||
6
uv.lock
6
uv.lock
|
|
@ -248,7 +248,7 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "benchmarks"
|
||||
version = "0.0.5"
|
||||
version = "0.0.7"
|
||||
source = { editable = "memora-dev/benchmarks" }
|
||||
dependencies = [
|
||||
{ name = "memora" },
|
||||
|
|
@ -1408,7 +1408,7 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "memora"
|
||||
version = "0.0.5"
|
||||
version = "0.0.7"
|
||||
source = { editable = "memora" }
|
||||
dependencies = [
|
||||
{ name = "alembic" },
|
||||
|
|
@ -1464,7 +1464,7 @@ provides-extras = ["test"]
|
|||
|
||||
[[package]]
|
||||
name = "memora-dev"
|
||||
version = "0.0.5"
|
||||
version = "0.0.7"
|
||||
source = { editable = "memora-dev" }
|
||||
dependencies = [
|
||||
{ name = "memora" },
|
||||
|
|
|
|||
Loading…
Reference in a new issue