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
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"latest_correlation_id": "corr-a1b2c3d4e5f6",
"latest_model_name": "qwen3-coder-30b",
"latest_task_type": "code-review",
"latest_generated_text": "The delegation routing logic in node_router_delegation correctly selects the cheapest local model first. The quality-gate threshold of 0.87 is within acceptable bounds. No critical issues found. The per-task routing weights are deterministic and match the contract spec. Recommendation: promote this routing config to the next production cycle.",
"latest_prompt_tokens": 144,
"latest_completion_tokens": 62,
"latest_latency_ms": 1840,
"source_topic": "onex.evt.omnibase-infra.inference-response.v1",
"recent_responses": [
{
"correlation_id": "corr-a1b2c3d4e5f6",
"model_name": "qwen3-coder-30b",
"task_type": "code-review",
"generated_text": "The delegation routing logic in node_router_delegation correctly selects the cheapest local model first. The quality-gate threshold of 0.87 is within acceptable bounds. No critical issues found. The per-task routing weights are deterministic and match the contract spec. Recommendation: promote this routing config to the next production cycle.",
"prompt_tokens": 144,
"completion_tokens": 62,
"latency_ms": 1840,
"captured_at": "2026-05-05T11:59:30Z"
},
{
"correlation_id": "corr-b2c3d4e5f6a1",
"model_name": "deepseek-r1-14b",
"task_type": "summarization",
"generated_text": "Summary: The SEA demo pipeline executed 312 delegations across 4 models with an 87% quality gate pass rate. Local inference handled 75% of requests, saving an estimated $0.43 vs cloud-only routing.",
"prompt_tokens": 210,
"completion_tokens": 54,
"latency_ms": 2310,
"captured_at": "2026-05-05T11:58:10Z"
},
{
"correlation_id": "corr-c3d4e5f6a1b2",
"model_name": "openrouter-glm-flash",
"task_type": "classification",
"generated_text": "Classification result: task_type=code-review, confidence=0.94, routing_rule=exploit:best-latency. Delegated to qwen3-coder-30b.",
"prompt_tokens": 88,
"completion_tokens": 28,
"latency_ms": 920,
"captured_at": "2026-05-05T11:57:00Z"
}
],
"captured_at": "2026-05-05T12:00:00Z",
"provisioned": false
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
},
"scripts": {
"dev": "vite",
"dev:server": "tsx --env-file-if-exists .env watch server/index.ts",
"dev:server": "tsx watch --env-file-if-exists .env server/index.ts",
"build": "tsc --noEmit && vite build",
"build:server": "tsc --noEmit --project tsconfig.node.json",
"preview": "vite preview",
Expand Down
58 changes: 58 additions & 0 deletions scripts/generate-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,64 @@ const MVP_COMPONENTS: Record<string, ComponentManifest> = {
emptyState: { message: 'No token usage data', hint: 'Token usage data appears once LLM call metrics are recorded (OMN-10623).' },
capabilities: { supports_compare: false, supports_export: true, supports_fullscreen: true, supports_time_range: false },
},
'delegation-model-output': {
name: 'delegation-model-output',
displayName: 'Model Output',
description: 'Renders ModelLlmInferenceResponse.generated_text sourced from bus topic onex.evt.omnibase-infra.inference-response.v1. Fixture mode is the demo-blocking deliverable (OMN-12745). Live surfacing requires the demo redeploy OMN-12746.',
category: 'quality',
version: '1.0.0',
implementationKey: 'delegation/DelegationModelOutputWidget',
configSchema: {
type: 'object',
properties: {
maxHistory: { type: 'integer', minimum: 0, default: 3, title: 'Max history rows', description: 'Number of recent responses to show below the latest output.' },
showFullOutput: { type: 'boolean', default: true, title: 'Show full output', description: 'Show the full generated_text for the latest response (vs truncated preview).' },
},
additionalProperties: false,
},
projectionSchema: {
type: 'object',
description: 'Row shape from onex.snapshot.projection.delegation.inference-response-text.v1 (OMN-12745). Sources from bus topic onex.evt.omnibase-infra.inference-response.v1.',
required: ['latest_correlation_id', 'latest_model_name', 'latest_task_type', 'latest_generated_text', 'latest_prompt_tokens', 'latest_completion_tokens', 'latest_latency_ms', 'source_topic', 'recent_responses', 'captured_at', 'provisioned'],
properties: {
latest_correlation_id: { type: 'string', description: 'Correlation ID of the most recent inference response.' },
latest_model_name: { type: 'string', description: 'Model that produced the most recent generated_text.' },
latest_task_type: { type: 'string', description: 'Task type of the most recent inference request.' },
latest_generated_text: { type: 'string', description: 'generated_text from ModelLlmInferenceResponse for the most recent response.' },
latest_prompt_tokens: { type: 'number', description: 'Prompt token count for the most recent response.' },
latest_completion_tokens: { type: 'number', description: 'Completion token count for the most recent response.' },
latest_latency_ms: { type: 'number', description: 'Inference latency in ms for the most recent response.' },
source_topic: { type: 'string', description: 'Bus topic that feeds this projection.' },
recent_responses: {
type: 'array',
items: {
type: 'object',
required: ['correlation_id', 'model_name', 'task_type', 'generated_text', 'prompt_tokens', 'completion_tokens', 'latency_ms', 'captured_at'],
properties: {
correlation_id: { type: 'string' },
model_name: { type: 'string' },
task_type: { type: 'string' },
generated_text: { type: 'string' },
prompt_tokens: { type: 'number' },
completion_tokens: { type: 'number' },
latency_ms: { type: 'number' },
captured_at: { type: 'string', format: 'date-time' },
},
additionalProperties: false,
},
},
captured_at: { type: 'string', format: 'date-time' },
provisioned: { type: 'boolean', description: 'True once the live projection emitter is deployed (OMN-12746).' },
},
},
dataSources: [projectionSource(TOPICS.inferenceResponseText, false), liveSource(TOPICS.inferenceResponseText)],
events: { emits: [], consumes: [] },
defaultSize: { w: 6, h: 7 },
minSize: { w: 4, h: 5 },
maxSize: { w: 12, h: 16 },
emptyState: { message: 'No inference output', hint: 'Inference output appears once the projection emitter is deployed (OMN-12746). In file mode, add fixture files under fixtures/onex.snapshot.projection.delegation.inference-response-text.v1/' },
capabilities: { supports_compare: false, supports_export: false, supports_fullscreen: true, supports_time_range: false },
},
'delegation-control-plane': {
name: 'delegation-control-plane',
displayName: 'Delegation Control Plane',
Expand Down
84 changes: 84 additions & 0 deletions server/__tests__/dispatch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,94 @@ describe('POST /api/dispatch', () => {
});
});

describe('POST /api/delegation/trigger', () => {
beforeEach(() => {
process.env.OMNIDASH_DATA_SOURCE = 'postgres';
vi.mocked(kafkaProducer.isProducerConnected).mockReturnValue(true);
vi.mocked(kafkaProducer.publishMessage).mockResolvedValue(undefined);
});

afterEach(() => {
delete process.env.OMNIDASH_DATA_SOURCE;
vi.clearAllMocks();
});

it('returns 400 when prompt is missing', async () => {
const routes = await loadRoutes();
const res = await request(buildApp(routes))
.post('/api/delegation/trigger')
.send({ task_type: 'reasoning' });

expect(res.status).toBe(400);
expect(res.body).toEqual({ error: 'prompt is required' });
});

it('returns 400 when task_type is outside the delegate-skill contract taxonomy', async () => {
const routes = await loadRoutes();
const res = await request(buildApp(routes))
.post('/api/delegation/trigger')
.send({ prompt: 'do work', task_type: 'general' });

expect(res.status).toBe(400);
expect(res.body.error).toBe('invalid task_type');
expect(res.body.allowed_task_types).toContain('reasoning');
expect(res.body.allowed_task_types).not.toContain('general');
});

it('returns 503 when Kafka producer is not connected in live data-source mode', async () => {
vi.mocked(kafkaProducer.isProducerConnected).mockReturnValue(false);

const routes = await loadRoutes();
const res = await request(buildApp(routes))
.post('/api/delegation/trigger')
.send({ prompt: 'do work', task_type: 'reasoning' });

expect(res.status).toBe(503);
expect(res.body).toEqual({ error: 'kafka_unavailable' });
});

it('publishes the delegate-skill event envelope to Kafka', async () => {
const routes = await loadRoutes();
const res = await request(buildApp(routes))
.post('/api/delegation/trigger')
.send({ prompt: 'Review this PR for correctness', task_type: 'code_review' });

expect(res.status).toBe(200);
expect(res.body.accepted).toBe(true);
expect(res.body.topic).toBe('onex.cmd.omnimarket.delegate-skill.v1');
expect(typeof res.body.correlation_id).toBe('string');
expect(kafkaProducer.publishMessage).toHaveBeenCalledOnce();

const [topic, envelope] = vi.mocked(kafkaProducer.publishMessage).mock.calls[0] as [string, Record<string, unknown>];
expect(topic).toBe('onex.cmd.omnimarket.delegate-skill.v1');
expect(envelope.event_type).toBe('omnimarket.delegate-skill');
expect(envelope.source_tool).toBe('omnidash-ui');
expect(envelope.correlation_id).toBe(res.body.correlation_id);
expect(typeof envelope.envelope_id).toBe('string');
expect(typeof envelope.envelope_timestamp).toBe('string');

const payload = envelope.payload as Record<string, unknown>;
expect(payload.prompt).toBe('Review this PR for correctness');
expect(payload.task_type).toBe('code_review');
expect(payload.source).toBe('codex');
expect(payload.wait).toBe(true);
expect(payload.correlation_id).toBe(res.body.correlation_id);
expect(payload.metadata).toEqual({
requested_by: 'omnidash-ui',
source_surface: 'delegation-control-plane',
});
});
});

// OMN-12149: topic registration test
describe('COMMAND_TOPICS registry', () => {
it('dispatchRequest key maps to the correct topic string', async () => {
const { COMMAND_TOPICS } = await import('../../shared/types/command-topics.js');
expect(COMMAND_TOPICS.dispatchRequest).toBe('onex.cmd.omnimarket.dispatch-request.v1');
});

it('delegateSkill key maps to the contract-declared delegate-skill command topic', async () => {
const { COMMAND_TOPICS } = await import('../../shared/types/command-topics.js');
expect(COMMAND_TOPICS.delegateSkill).toBe('onex.cmd.omnimarket.delegate-skill.v1');
});
});
86 changes: 58 additions & 28 deletions server/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,26 @@ import { PostgresProjectionReader } from './postgres-projection-reader.js';
import { loadDataSourceConfig } from './data-source-contract.js';
import { isProducerConnected, publishMessage } from './kafka-producer.js';
import { COMMAND_TOPICS } from '../shared/types/command-topics.js';
// OMNIDASH_RUNTIME_EFFECTS_URL points to the stability-test runtime (:18085/v1/effects)
// when running against live infra. Absent in file/dev mode — returns a simulated accepted response.

const router = Router();

const DELEGATE_SKILL_EVENT_TYPE = 'omnimarket.delegate-skill';
const DELEGATE_SKILL_TASK_TYPES = new Set([
'test',
'document',
'research',
'code_generation',
'code_review',
'refactor',
'reasoning',
'complex_reasoning',
'planning',
'review',
'summarization',
'agent_delegation',
'escalation',
]);

const FIXTURES_DIR = resolve(process.env.VITE_FIXTURES_DIR ?? process.env.FIXTURES_DIR ?? './fixtures');

// OMN-10756: data source mode and SQLite DB path now come from contract.yaml
Expand Down Expand Up @@ -103,48 +118,63 @@ router.get('/api/delegation/correlation-trace/:correlationId', async (req, res)
}
});

// Delegation trigger: publish a delegation command to the ONEX runtime.
// Forwards to OMNIDASH_RUNTIME_EFFECTS_URL when set; otherwise returns
// a simulated accepted response so the UI can be tested without infra.
// Delegation trigger: publish the contract-declared delegate-skill command
// envelope consumed by the ONEX runtime.
router.post('/api/delegation/trigger', async (req, res) => {
const body = req.body as { prompt?: unknown; task_type?: unknown };
const prompt = typeof body.prompt === 'string' ? body.prompt.slice(0, 4096) : '';
const taskType = typeof body.task_type === 'string' ? body.task_type.slice(0, 128) : 'general';
const taskType = typeof body.task_type === 'string' ? body.task_type.slice(0, 128) : 'reasoning';
if (!prompt) {
res.status(400).json({ error: 'prompt is required' });
return;
}
if (!DELEGATE_SKILL_TASK_TYPES.has(taskType)) {
res.status(400).json({
error: 'invalid task_type',
allowed_task_types: [...DELEGATE_SKILL_TASK_TYPES],
});
return;
}

const correlationId = randomUUID();
const runtimeUrl = process.env.OMNIDASH_RUNTIME_EFFECTS_URL;

if (!runtimeUrl) {
// No runtime configured — return an accepted response so the UI works
// in dev/file mode. The correlation_id can be searched in the trace view
// once real events are materialized.
res.json({ correlation_id: correlationId, accepted: true, message: 'simulated (no OMNIDASH_RUNTIME_EFFECTS_URL set)' });
if (!isProducerConnected()) {
if (dsConfig.mode === 'file') {
res.json({ correlation_id: correlationId, accepted: true, message: 'simulated (file data source)' });
return;
}
res.status(503).json({ error: 'kafka_unavailable' });
return;
}

const requestedAt = new Date().toISOString();
const envelope = {
payload: {
prompt,
task_type: taskType,
source: 'codex',
wait: true,
correlation_id: correlationId,
metadata: {
requested_by: 'omnidash-ui',
source_surface: 'delegation-control-plane',
},
},
envelope_id: randomUUID(),
envelope_timestamp: requestedAt,
correlation_id: correlationId,
source_tool: 'omnidash-ui',
event_type: DELEGATE_SKILL_EVENT_TYPE,
priority: 5,
retry_count: 0,
};

try {
const upstream = await fetch(`${runtimeUrl}/v1/effects`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
topic: COMMAND_TOPICS.delegateSkill,
correlation_id: correlationId,
payload: { prompt, task_type: taskType, source: 'delegation-dashboard' },
}),
});
if (!upstream.ok) {
const text = await upstream.text().catch(() => '');
res.status(502).json({ error: `runtime returned ${upstream.status}`, detail: text });
return;
}
res.json({ correlation_id: correlationId, accepted: true });
await publishMessage(COMMAND_TOPICS.delegateSkill, envelope);
res.json({ correlation_id: correlationId, accepted: true, topic: COMMAND_TOPICS.delegateSkill });
} catch (err) {
console.error('[routes] /api/delegation/trigger error:', err);
res.status(503).json({ error: 'runtime unreachable', detail: String(err) });
res.status(503).json({ error: 'kafka_unavailable', detail: String(err) });
}
});

Expand Down
14 changes: 11 additions & 3 deletions shared/types/topics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ export const TOPICS = {
delegationDecisions: 'onex.snapshot.projection.delegation.decisions.v1',
/**
* Correlation trace — full event chain for a single correlation_id, ordered
* by created_at ascending. In live (postgres/http/sqlite) mode this is served
* by the typed REST endpoint /api/delegation/correlation-trace/:id; in file
* mode the trace is read from a per-correlation fixture under
* by created_at ascending, including the delegated prompt_text/response_text.
* In live mode this is the contract-declared projection served by the
* projection API at /projection/<topic>?correlation_id=<id> (OMN-12748); in
* file mode the trace is read from a per-correlation fixture under
* fixtures/onex.snapshot.projection.delegation.correlation-trace.v1/ so the
* surface renders without postgres availability (OMN-12367).
*/
Expand Down Expand Up @@ -147,6 +148,13 @@ export const TOPICS = {
voiceSessions: 'onex.snapshot.projection.voice.sessions.v1',
/** Session replay snapshots — state reconstruction checkpoints (OMN-6877). */
sessionReplay: 'onex.snapshot.projection.session.replay.v1',
/**
* Inference response text projection — latest ModelLlmInferenceResponse rows
* sourced from the bus topic onex.evt.omnibase-infra.inference-response.v1.
* Rendered by DelegationModelOutputWidget (OMN-12745). Fixture mode is the
* demo-blocking deliverable; live surfacing requires the demo redeploy OMN-12746.
*/
inferenceResponseText: 'onex.snapshot.projection.delegation.inference-response-text.v1',
} as const;

export type TopicSymbol = (typeof TOPICS)[keyof typeof TOPICS];
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('DelegationTriggerPanel', () => {

expect(mockTrigger).toHaveBeenCalledWith({
prompt: 'Review this PR for correctness',
task_type: 'general',
task_type: 'reasoning',
});
expect(screen.getByText('test-corr-id')).toBeTruthy();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { Text } from '@/components/ui/typography';
import { triggerDelegation } from '@/services/delegation-api';

const TASK_TYPES = [
'general',
'reasoning',
'code_review',
'code_generation',
'summarization',
'analysis',
'refactor',
'test_generation',
'documentation',
'test',
'document',
'research',
'planning',
'complex_reasoning',
] as const;

type TriggerState =
Expand All @@ -26,7 +28,7 @@ export function DelegationTriggerPanel({
}) {
const [open, setOpen] = useState(false);
const [prompt, setPrompt] = useState('');
const [taskType, setTaskType] = useState<string>('general');
const [taskType, setTaskType] = useState<string>('reasoning');
const [state, setState] = useState<TriggerState>({ phase: 'idle' });

async function handleSubmit() {
Expand Down
Loading
Loading