feat(server): integrate MCP queries and investigation messaging
Add project-bound OAuth MCP queries and controlled analysis with scoped evidence, limits, timeouts and a nearby-model spatial query using EPSG:4326 inputs. Default nearby searches to 200 meters and five results. Integrate investigation messaging/presentation, health/readiness and typed history; remove duplicate web search and fix online simulation and compressed baseline writes. Include project migrations 023-025; keep local credentials and demo seeding excluded. Validation: 319 focused pytest checks; real PostGIS temporary-table regression; read-only Jinqian bridge radius comparison; cross-language MCP discovery/calls.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
-- Latest investigation reading snapshots and controlled browser presentation events.
|
||||
BEGIN;
|
||||
SET LOCAL lock_timeout = '5s';
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF current_database() <> 'tjwater_v2' THEN
|
||||
RAISE EXCEPTION 'Investigation progress migration is restricted to tjwater_v2';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS workbench.operational_task_progress (
|
||||
project_id uuid NOT NULL,
|
||||
task_id uuid NOT NULL,
|
||||
run_id uuid NOT NULL,
|
||||
revision bigint NOT NULL CHECK (revision >= 1),
|
||||
document jsonb NOT NULL,
|
||||
published_at timestamptz NOT NULL,
|
||||
PRIMARY KEY (project_id,task_id,run_id),
|
||||
FOREIGN KEY (project_id,task_id)
|
||||
REFERENCES workbench.operational_tasks(project_id,task_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (project_id,run_id)
|
||||
REFERENCES workbench.operational_task_runs(project_id,run_id) ON DELETE CASCADE,
|
||||
CHECK ((jsonb_typeof(document)='object'
|
||||
AND document->>'run_id'=run_id::text
|
||||
AND (document->>'revision')::bigint=revision) IS TRUE)
|
||||
);
|
||||
|
||||
ALTER TABLE workbench.domain_event_log
|
||||
DROP CONSTRAINT IF EXISTS domain_event_log_topic_check;
|
||||
ALTER TABLE workbench.domain_event_log ADD CONSTRAINT domain_event_log_topic_check
|
||||
CHECK (topic IN (
|
||||
'operational.task.changed','operational.run.queued','operational.run.changed',
|
||||
'operational.report.published','operational.progress.changed',
|
||||
'operational.presentation.requested','operational.action.changed',
|
||||
'operational.notification.changed','workbench.alert.changed',
|
||||
'workbench.work_order.changed','analysis.run.changed'
|
||||
));
|
||||
|
||||
COMMENT ON TABLE workbench.operational_task_progress IS
|
||||
'One latest complete reading snapshot per investigation run; never an execution scheduler.';
|
||||
COMMIT;
|
||||
@@ -0,0 +1,42 @@
|
||||
-- Private messages are deliberately excluded from the project event log.
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS workbench.agent_messages (
|
||||
project_id uuid NOT NULL,
|
||||
message_id uuid NOT NULL,
|
||||
request_id uuid NOT NULL,
|
||||
task_id uuid NOT NULL,
|
||||
run_id uuid NOT NULL,
|
||||
source_session_id text NOT NULL CHECK (length(source_session_id)>0),
|
||||
source_owner_id uuid NOT NULL,
|
||||
conversation_owner_id uuid NOT NULL,
|
||||
target_session_id text,
|
||||
direction text NOT NULL CHECK (direction IN ('to_task','to_chat')),
|
||||
in_reply_to uuid,
|
||||
text text NOT NULL CHECK (length(text) BETWEEN 1 AND 12000 AND text ~ '\S'),
|
||||
status text NOT NULL CHECK (status IN ('pending','enqueued','delivered','failed')),
|
||||
native_message_id text NOT NULL,
|
||||
failure_detail text,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
delivered_at timestamptz,
|
||||
PRIMARY KEY (project_id,message_id),
|
||||
UNIQUE (project_id,source_owner_id,source_session_id,request_id),
|
||||
FOREIGN KEY (project_id,task_id)
|
||||
REFERENCES workbench.operational_tasks(project_id,task_id),
|
||||
FOREIGN KEY (project_id,run_id)
|
||||
REFERENCES workbench.operational_task_runs(project_id,run_id),
|
||||
FOREIGN KEY (project_id,in_reply_to)
|
||||
REFERENCES workbench.agent_messages(project_id,message_id),
|
||||
CHECK ((direction='to_task')
|
||||
OR (direction='to_chat' AND in_reply_to IS NOT NULL AND target_session_id IS NOT NULL))
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS agent_messages_pending_idx
|
||||
ON workbench.agent_messages(project_id,created_at,message_id)
|
||||
WHERE status IN ('pending','enqueued');
|
||||
CREATE INDEX IF NOT EXISTS agent_messages_owner_session_idx
|
||||
ON workbench.agent_messages(project_id,conversation_owner_id,created_at);
|
||||
CREATE INDEX IF NOT EXISTS agent_messages_run_idx
|
||||
ON workbench.agent_messages(project_id,run_id,status);
|
||||
|
||||
COMMIT;
|
||||
@@ -0,0 +1,27 @@
|
||||
-- Additive MCP storage. Apply through the existing project database workflow.
|
||||
-- No access token, refresh token or OAuth client secret is stored here.
|
||||
BEGIN;
|
||||
CREATE TABLE IF NOT EXISTS workbench.mcp_query_contexts (
|
||||
context_handle text PRIMARY KEY,
|
||||
project_id uuid NOT NULL,
|
||||
subject text NOT NULL,
|
||||
client_id text NOT NULL,
|
||||
document jsonb NOT NULL,
|
||||
expires_at timestamptz NOT NULL,
|
||||
revoked_at timestamptz,
|
||||
created_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS mcp_query_context_owner
|
||||
ON workbench.mcp_query_contexts (project_id,subject,client_id);
|
||||
CREATE INDEX IF NOT EXISTS mcp_query_context_expiry
|
||||
ON workbench.mcp_query_contexts (project_id,expires_at);
|
||||
CREATE TABLE IF NOT EXISTS workbench.mcp_query_receipts (
|
||||
project_id uuid NOT NULL,
|
||||
scope_key text NOT NULL,
|
||||
call_id text NOT NULL,
|
||||
parameters jsonb NOT NULL,
|
||||
result jsonb NOT NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (project_id,scope_key,call_id)
|
||||
);
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user