fix(mcp-server): correct TelemetryCluster type, remove productId QS dead code from telemetryClusters, remove redundant extend() in pipeline-tool
This commit is contained in:
parent
0f044830fa
commit
6cee9c20af
@ -66,20 +66,34 @@ export async function telemetryQuery(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface TelemetryCluster {
|
export interface TelemetryCluster {
|
||||||
|
/** Cluster doc ID: ${fingerprint}:${yyyyMM} */
|
||||||
|
id: string;
|
||||||
|
/** Partition key: ${productId}:${platform}:${module} */
|
||||||
|
pk: string;
|
||||||
fingerprint: string;
|
fingerprint: string;
|
||||||
count: number;
|
severity: 'warn' | 'error' | 'fatal';
|
||||||
lastSeen: string;
|
totalCount: number;
|
||||||
sample: unknown;
|
lastSeenAt: string;
|
||||||
|
firstSeenAt: string;
|
||||||
|
platform: string;
|
||||||
|
module: string;
|
||||||
|
eventName: string;
|
||||||
|
sampleMessage?: string;
|
||||||
|
status: 'open' | 'resolved' | 'ignored';
|
||||||
|
resolvedBy?: string;
|
||||||
|
resolvedAt?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function telemetryClusters(
|
export async function telemetryClusters(
|
||||||
params: { productId: string; from?: string; to?: string },
|
params: { from?: string; to?: string; platform?: string; module?: string },
|
||||||
opts: PlatformClientOptions
|
opts: PlatformClientOptions
|
||||||
): Promise<{ clusters: TelemetryCluster[] }> {
|
): Promise<{ clusters: TelemetryCluster[]; total: number }> {
|
||||||
const qs = new URLSearchParams({ productId: params.productId });
|
const qs = new URLSearchParams();
|
||||||
if (params.from) qs.set('from', params.from);
|
if (params.from) qs.set('from', params.from);
|
||||||
if (params.to) qs.set('to', params.to);
|
if (params.to) qs.set('to', params.to);
|
||||||
return platformFetch<{ clusters: TelemetryCluster[] }>(
|
if (params.platform) qs.set('platform', params.platform);
|
||||||
|
if (params.module) qs.set('module', params.module);
|
||||||
|
return platformFetch<{ clusters: TelemetryCluster[]; total: number }>(
|
||||||
`/api/telemetry/clusters?${qs}`,
|
`/api/telemetry/clusters?${qs}`,
|
||||||
{ method: 'GET' },
|
{ method: 'GET' },
|
||||||
opts
|
opts
|
||||||
|
|||||||
@ -5,22 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { randomUUID } from 'node:crypto';
|
import { randomUUID } from 'node:crypto';
|
||||||
import { telemetryClusters } from '../../../lib/platform-client.js';
|
import { telemetryClusters, type TelemetryCluster } from '../../../lib/platform-client.js';
|
||||||
import type { DispatchDecision, TelemetryFindings, ClusterRef } from '../types.js';
|
import type { DispatchDecision, TelemetryFindings, ClusterRef } from '../types.js';
|
||||||
|
|
||||||
interface RawCluster {
|
|
||||||
id?: string;
|
|
||||||
pk?: string;
|
|
||||||
fingerprint?: string;
|
|
||||||
severity?: string;
|
|
||||||
totalCount?: number;
|
|
||||||
lastSeenAt?: string;
|
|
||||||
platform?: string;
|
|
||||||
module?: string;
|
|
||||||
sampleMessage?: string;
|
|
||||||
status?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function analyze(
|
export async function analyze(
|
||||||
decision: DispatchDecision,
|
decision: DispatchDecision,
|
||||||
opts: { token?: string }
|
opts: { token?: string }
|
||||||
@ -34,25 +21,25 @@ export async function analyze(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await telemetryClusters(
|
const result = await telemetryClusters(
|
||||||
{ productId: brief.productId, from: resolvedTimeWindow.from, to: resolvedTimeWindow.to },
|
{ from: resolvedTimeWindow.from, to: resolvedTimeWindow.to },
|
||||||
{ token: opts.token, requestId: runContext.requestId, productId: brief.productId }
|
{ token: opts.token, requestId: runContext.requestId, productId: brief.productId }
|
||||||
);
|
);
|
||||||
|
|
||||||
const raw: RawCluster[] = (result as { clusters?: RawCluster[] }).clusters ?? [];
|
clusters = result.clusters
|
||||||
|
.filter((c: TelemetryCluster) => c.status !== 'resolved' && c.status !== 'ignored')
|
||||||
clusters = raw
|
.map(
|
||||||
.filter(c => c.status !== 'resolved' && c.status !== 'ignored')
|
(c: TelemetryCluster): ClusterRef => ({
|
||||||
.map(c => ({
|
clusterId: c.id,
|
||||||
clusterId: c.id ?? '',
|
pk: c.pk,
|
||||||
pk: c.pk ?? '',
|
fingerprint: c.fingerprint,
|
||||||
fingerprint: c.fingerprint ?? '',
|
severity: c.severity,
|
||||||
severity: c.severity ?? 'error',
|
totalCount: c.totalCount,
|
||||||
totalCount: c.totalCount ?? 0,
|
lastSeenAt: c.lastSeenAt,
|
||||||
lastSeenAt: c.lastSeenAt ?? '',
|
platform: c.platform,
|
||||||
platform: c.platform ?? '',
|
module: c.module,
|
||||||
module: c.module ?? '',
|
sampleMessage: c.sampleMessage,
|
||||||
sampleMessage: c.sampleMessage,
|
})
|
||||||
}));
|
);
|
||||||
|
|
||||||
// Filter by platform if the incident report names one
|
// Filter by platform if the incident report names one
|
||||||
if (brief.userReport.platform) {
|
if (brief.userReport.platform) {
|
||||||
|
|||||||
@ -5,7 +5,6 @@
|
|||||||
* Agents run in sequence: Dispatcher → TelemetryAnalyst → DiagnosticsOrchestrator → ReportWriter.
|
* Agents run in sequence: Dispatcher → TelemetryAnalyst → DiagnosticsOrchestrator → ReportWriter.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { z } from 'zod';
|
|
||||||
import { registerTool } from '../tools/registry.js';
|
import { registerTool } from '../tools/registry.js';
|
||||||
import { SupportIncidentBriefSchema } from './types.js';
|
import { SupportIncidentBriefSchema } from './types.js';
|
||||||
import { runIncidentPipeline } from './runner.js';
|
import { runIncidentPipeline } from './runner.js';
|
||||||
@ -22,14 +21,7 @@ registerTool({
|
|||||||
'Requires admin role.',
|
'Requires admin role.',
|
||||||
].join(' '),
|
].join(' '),
|
||||||
requiredRole: 'admin',
|
requiredRole: 'admin',
|
||||||
inputSchema: SupportIncidentBriefSchema.extend({
|
inputSchema: SupportIncidentBriefSchema,
|
||||||
openDiagnosticsSession: z
|
|
||||||
.boolean()
|
|
||||||
.default(false)
|
|
||||||
.describe(
|
|
||||||
'Open a live diagnostics session for the affected user (requires userId or anonymousInstallId)'
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
async execute(args, req: McpToolRequest) {
|
async execute(args, req: McpToolRequest) {
|
||||||
const token = req.headers.authorization?.slice(7);
|
const token = req.headers.authorization?.slice(7);
|
||||||
return runIncidentPipeline(args, {
|
return runIncidentPipeline(args, {
|
||||||
|
|||||||
@ -39,11 +39,10 @@ registerTool({
|
|||||||
to: z.string().optional().describe('ISO 8601 end time'),
|
to: z.string().optional().describe('ISO 8601 end time'),
|
||||||
}),
|
}),
|
||||||
async execute(args, req) {
|
async execute(args, req) {
|
||||||
return telemetryClusters(args, {
|
return telemetryClusters(
|
||||||
token: tokenOf(req),
|
{ from: args.from, to: args.to },
|
||||||
requestId: req.id,
|
{ token: tokenOf(req), requestId: req.id, productId: args.productId }
|
||||||
productId: args.productId,
|
);
|
||||||
});
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -44,11 +44,8 @@ registerTool({
|
|||||||
let clusters: unknown[] = [];
|
let clusters: unknown[] = [];
|
||||||
let clusterError: string | undefined;
|
let clusterError: string | undefined;
|
||||||
try {
|
try {
|
||||||
const result = await telemetryClusters(
|
const result = await telemetryClusters({ from: args.from, to: args.to }, opts);
|
||||||
{ productId: args.productId, from: args.from, to: args.to },
|
clusters = result.clusters;
|
||||||
opts
|
|
||||||
);
|
|
||||||
clusters = result.clusters ?? [];
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
clusterError = err instanceof Error ? err.message : String(err);
|
clusterError = err instanceof Error ? err.message : String(err);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user