@oqtopus-team/pi-qdash 0.1.10-beta.15 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/extensions/qdash.ts +12 -47
- package/package.json +1 -1
- package/skills/qdash/SKILL.md +2 -2
package/extensions/qdash.ts
CHANGED
|
@@ -75,9 +75,6 @@ type QDashQueryParams = {
|
|
|
75
75
|
| "flow_helper_file"
|
|
76
76
|
| "executions"
|
|
77
77
|
| "execution"
|
|
78
|
-
| "ai_reviews"
|
|
79
|
-
| "ai_review_runs"
|
|
80
|
-
| "ai_review_run"
|
|
81
78
|
| "forum_posts"
|
|
82
79
|
| "provenance_stats"
|
|
83
80
|
| "provenance_history"
|
|
@@ -98,7 +95,6 @@ type QDashQueryParams = {
|
|
|
98
95
|
templateId?: string;
|
|
99
96
|
filename?: string;
|
|
100
97
|
executionId?: string;
|
|
101
|
-
reviewRunId?: string;
|
|
102
98
|
entityId?: string;
|
|
103
99
|
parameter?: string;
|
|
104
100
|
parameterName?: string;
|
|
@@ -106,7 +102,6 @@ type QDashQueryParams = {
|
|
|
106
102
|
date?: string;
|
|
107
103
|
backend?: string;
|
|
108
104
|
status?: string;
|
|
109
|
-
decision?: string;
|
|
110
105
|
username?: string;
|
|
111
106
|
messageContains?: string;
|
|
112
107
|
startAt?: string;
|
|
@@ -114,7 +109,6 @@ type QDashQueryParams = {
|
|
|
114
109
|
startFrom?: string;
|
|
115
110
|
startTo?: string;
|
|
116
111
|
isClosed?: boolean;
|
|
117
|
-
latestOnly?: boolean;
|
|
118
112
|
withinHours?: number;
|
|
119
113
|
limit?: number;
|
|
120
114
|
skip?: number;
|
|
@@ -323,9 +317,6 @@ const QueryAction = Type.Union([
|
|
|
323
317
|
Type.Literal("flow_helper_file"),
|
|
324
318
|
Type.Literal("executions"),
|
|
325
319
|
Type.Literal("execution"),
|
|
326
|
-
Type.Literal("ai_reviews"),
|
|
327
|
-
Type.Literal("ai_review_runs"),
|
|
328
|
-
Type.Literal("ai_review_run"),
|
|
329
320
|
Type.Literal("forum_posts"),
|
|
330
321
|
Type.Literal("provenance_stats"),
|
|
331
322
|
Type.Literal("provenance_history"),
|
|
@@ -367,7 +358,6 @@ const querySchema = Type.Object({
|
|
|
367
358
|
templateId: Type.Optional(Type.String()),
|
|
368
359
|
filename: Type.Optional(Type.String()),
|
|
369
360
|
executionId: Type.Optional(Type.String()),
|
|
370
|
-
reviewRunId: Type.Optional(Type.String()),
|
|
371
361
|
entityId: Type.Optional(Type.String()),
|
|
372
362
|
parameter: Type.Optional(Type.String({ description: "Metric/parameter name for timeseries." })),
|
|
373
363
|
parameterName: Type.Optional(Type.String()),
|
|
@@ -375,7 +365,6 @@ const querySchema = Type.Object({
|
|
|
375
365
|
date: Type.Optional(Type.String({ description: "History date, usually YYYYMMDD." })),
|
|
376
366
|
backend: Type.Optional(Type.String()),
|
|
377
367
|
status: Type.Optional(Type.String()),
|
|
378
|
-
decision: Type.Optional(Type.String()),
|
|
379
368
|
username: Type.Optional(Type.String()),
|
|
380
369
|
messageContains: Type.Optional(Type.String()),
|
|
381
370
|
startAt: Type.Optional(Type.String()),
|
|
@@ -383,7 +372,6 @@ const querySchema = Type.Object({
|
|
|
383
372
|
startFrom: Type.Optional(Type.String()),
|
|
384
373
|
startTo: Type.Optional(Type.String()),
|
|
385
374
|
isClosed: Type.Optional(Type.Boolean()),
|
|
386
|
-
latestOnly: Type.Optional(Type.Boolean()),
|
|
387
375
|
withinHours: Type.Optional(Type.Number()),
|
|
388
376
|
limit: Type.Optional(Type.Number()),
|
|
389
377
|
skip: Type.Optional(Type.Number()),
|
|
@@ -466,7 +454,7 @@ function qcalEvidenceText(evidence: CalibrationEvidence): string {
|
|
|
466
454
|
`Figures ${figures.length}`,
|
|
467
455
|
...figures.map((figure, index) => ` - #${index + 1} ${String(figure.role ?? "plot")} ${String(figure.path ?? figure.url ?? "")}`),
|
|
468
456
|
"",
|
|
469
|
-
"
|
|
457
|
+
"Pass this summary as the context of qcal_evaluate; the embedded figure is the measured result to judge.",
|
|
470
458
|
]).join("\n");
|
|
471
459
|
}
|
|
472
460
|
|
|
@@ -1252,12 +1240,11 @@ async function buildDashboardInsights(params: { profile?: string; configPath?: s
|
|
|
1252
1240
|
const limit = params.limit ?? 30;
|
|
1253
1241
|
const end = new Date();
|
|
1254
1242
|
const start = new Date(end.getTime() - (params.withinHours ?? 168) * 3600_000);
|
|
1255
|
-
const [forums, issues, failed, metrics
|
|
1243
|
+
const [forums, issues, failed, metrics] = await Promise.allSettled([
|
|
1256
1244
|
client.listForumPosts({ chipId, status: "open", limit }),
|
|
1257
1245
|
client.api.listIssues({ is_closed: false, limit }),
|
|
1258
1246
|
client.api.listTaskResults({ chip_id: chipId, status: "failed", start_from: start.toISOString(), start_to: end.toISOString(), limit }),
|
|
1259
1247
|
client.getChipMetrics(chipId),
|
|
1260
|
-
client.api.getDashboardAiInsights(chipId, { latest_only: true, start_at: start.toISOString(), end_at: end.toISOString() }),
|
|
1261
1248
|
]);
|
|
1262
1249
|
const value = <T>(result: PromiseSettledResult<T>): T | undefined => result.status === "fulfilled" ? result.value : undefined;
|
|
1263
1250
|
const insightMap = new Map<string, DashboardInsight>();
|
|
@@ -1289,20 +1276,6 @@ async function buildDashboardInsights(params: { profile?: string; configPath?: s
|
|
|
1289
1276
|
|
|
1290
1277
|
addMetricInsights(insightMap, value(metrics), client);
|
|
1291
1278
|
|
|
1292
|
-
const aiPayload = value(aiInsights);
|
|
1293
|
-
for (const item of arrayFromPayload(aiPayload).filter((entry): entry is Record<string, unknown> => Boolean(entry) && typeof entry === "object")) {
|
|
1294
|
-
const title = firstString(item, ["title", "summary"]) ?? "QDash AI insight";
|
|
1295
|
-
const severityValue = firstString(item, ["severity"])?.toLowerCase();
|
|
1296
|
-
const severity: DashboardInsight["severity"] = severityValue === "critical" ? "critical" : severityValue === "warning" ? "warning" : "info";
|
|
1297
|
-
const targets = Array.isArray(item.affected_targets) ? item.affected_targets.filter((target): target is string => typeof target === "string") : [];
|
|
1298
|
-
for (const rawTarget of targets) {
|
|
1299
|
-
const target = rawTarget.match(/^Q/i) ? `q${rawTarget.replace(/^Q0*/i, "")}` : rawTarget.match(/^C/i) ? `c${rawTarget.slice(1)}` : targetFromText(rawTarget);
|
|
1300
|
-
if (!target) continue;
|
|
1301
|
-
const evidence = firstString(item, ["recommended_action", "primary_reason"]) ?? `QDash AI insight: ${title}`;
|
|
1302
|
-
addEvidence(insightMap, target, severity, title, evidence, firstString(item, ["recommended_action"]) ?? "Review the QDash AI insight and supporting task evidence.");
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
1279
|
const insights = [...insightMap.values()].sort((a, b) => {
|
|
1307
1280
|
const rank = { critical: 2, warning: 1, info: 0 } as const;
|
|
1308
1281
|
return rank[b.severity] - rank[a.severity] || b.evidence.length - a.evidence.length;
|
|
@@ -1515,9 +1488,6 @@ async function executeQuery(params: QDashQueryParams) {
|
|
|
1515
1488
|
case "flow_helper_file": return client.api.getFlowHelperFile(requireValue(params.filename, "filename"));
|
|
1516
1489
|
case "executions": return rawGet(client, "/executions", { chip_id: params.chipId, flow_name: params.flowName, status: params.status, skip: params.skip, limit: params.limit });
|
|
1517
1490
|
case "execution": return client.getExecution(requireValue(params.executionId, "executionId"));
|
|
1518
|
-
case "ai_reviews": return client.api.listTaskResultAiReviews({ chip_id: params.chipId, task_name: params.taskName, status: params.status, decision: params.decision, latest_only: params.latestOnly, skip: params.skip, limit: params.limit });
|
|
1519
|
-
case "ai_review_runs": return client.api.listTaskResultAiReviewRuns({ chip_id: params.chipId, task_name: params.taskName, skip: params.skip, limit: params.limit });
|
|
1520
|
-
case "ai_review_run": return client.api.getTaskResultAiReviewRun(requireValue(params.reviewRunId, "reviewRunId"));
|
|
1521
1491
|
case "forum_posts": return client.listForumPosts({ status: params.status, chipId: params.chipId, limit: params.limit, skip: params.skip });
|
|
1522
1492
|
case "provenance_stats": return client.getProvenanceStats();
|
|
1523
1493
|
case "provenance_history": return client.api.getParameterHistory({ parameter_name: requireValue(params.parameterName ?? params.parameter, "parameterName"), qid: requireValue(params.qid, "qid"), limit: params.limit });
|
|
@@ -1940,15 +1910,6 @@ export default function qdashExtension(pi: ExtensionAPI) {
|
|
|
1940
1910
|
parameters: Type.Object({ ...connectionParams, executionId: Type.String() }),
|
|
1941
1911
|
});
|
|
1942
1912
|
|
|
1943
|
-
registerQueryTool({
|
|
1944
|
-
name: "qdash_list_ai_reviews",
|
|
1945
|
-
label: "QDash List AI Reviews",
|
|
1946
|
-
description: "List task-result AI reviews with optional filters.",
|
|
1947
|
-
promptSnippet: "List QDash task-result AI reviews",
|
|
1948
|
-
action: "ai_reviews",
|
|
1949
|
-
parameters: Type.Object({ ...connectionParams, chipId: Type.Optional(Type.String()), taskName: Type.Optional(Type.String()), status: Type.Optional(Type.String()), decision: Type.Optional(Type.String()), latestOnly: Type.Optional(Type.Boolean()), limit: Type.Optional(Type.Number()), skip: Type.Optional(Type.Number()) }),
|
|
1950
|
-
});
|
|
1951
|
-
|
|
1952
1913
|
pi.registerTool({
|
|
1953
1914
|
name: "qdash_create_agent_session",
|
|
1954
1915
|
label: "QDash Create Agent Session",
|
|
@@ -2652,12 +2613,12 @@ export default function qdashExtension(pi: ExtensionAPI) {
|
|
|
2652
2613
|
pi.registerTool({
|
|
2653
2614
|
name: "qdash_build_qcal_evidence",
|
|
2654
2615
|
label: "QDash Build QCal Evidence",
|
|
2655
|
-
description: "
|
|
2656
|
-
promptSnippet: "
|
|
2616
|
+
description: "Summarize a QDash task result (target, parameters, metrics, figure analysis) as evidence for pi-qcaleval's qcal_evaluate, returning the task figure as image content.",
|
|
2617
|
+
promptSnippet: "Summarize a QDash calibration task result as evidence for qcal_evaluate",
|
|
2657
2618
|
promptGuidelines: [
|
|
2658
|
-
"Use qdash_build_qcal_evidence before
|
|
2619
|
+
"Use qdash_build_qcal_evidence before qcal_evaluate when the user asks to evaluate a QDash calibration task with pi-qcaleval; pass the returned summary as the context of qcal_evaluate.",
|
|
2659
2620
|
"qdash_build_qcal_evidence is read-only and only converts QDash data into a generic evidence bundle; it does not evaluate, execute, commit, or apply calibration parameters.",
|
|
2660
|
-
"
|
|
2621
|
+
"The task figure comes back as image content, so qcal_evaluate can follow directly without fetching the figure again; treat the evaluation as advisory evidence.",
|
|
2661
2622
|
],
|
|
2662
2623
|
parameters: Type.Object({
|
|
2663
2624
|
...connectionParams,
|
|
@@ -2671,6 +2632,7 @@ export default function qdashExtension(pi: ExtensionAPI) {
|
|
|
2671
2632
|
const client = await makeClient(params);
|
|
2672
2633
|
const task = await client.getTaskResult(params.taskId) as unknown as Record<string, unknown>;
|
|
2673
2634
|
const figures: Array<Record<string, unknown>> = [];
|
|
2635
|
+
const images: Array<{ type: "image"; data: string; mimeType: string }> = [];
|
|
2674
2636
|
const notes: string[] = [];
|
|
2675
2637
|
const figurePaths = Array.isArray(task.figure_path) ? task.figure_path.filter((item): item is string => typeof item === "string") : [];
|
|
2676
2638
|
const jsonFigurePaths = Array.isArray(task.json_figure_path) ? task.json_figure_path.filter((item): item is string => typeof item === "string") : [];
|
|
@@ -2699,7 +2661,9 @@ export default function qdashExtension(pi: ExtensionAPI) {
|
|
|
2699
2661
|
const bytes = Buffer.from(file.data);
|
|
2700
2662
|
const mediaType = file.mediaType || mediaTypeForPath(file.path ?? figurePaths[index] ?? "");
|
|
2701
2663
|
if (mediaType.startsWith("image/")) {
|
|
2702
|
-
|
|
2664
|
+
const base64 = bytes.toString("base64");
|
|
2665
|
+
figures.push({ path: file.path ?? figurePaths[index], url: `data:${mediaType};base64,${base64}`, mimeType: mediaType, role: "plot" });
|
|
2666
|
+
images.push({ type: "image", data: base64, mimeType: mediaType });
|
|
2703
2667
|
}
|
|
2704
2668
|
} catch (error) {
|
|
2705
2669
|
notes.push(`Figure image #${index + 1} embedding failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -2744,7 +2708,8 @@ export default function qdashExtension(pi: ExtensionAPI) {
|
|
|
2744
2708
|
},
|
|
2745
2709
|
};
|
|
2746
2710
|
|
|
2747
|
-
|
|
2711
|
+
const result = toTextToolResult(qcalEvidenceText(evidence), { evidence }, { tool: "qdash_build_qcal_evidence", taskId: params.taskId, evidence });
|
|
2712
|
+
return { ...result, content: [...result.content, ...images] };
|
|
2748
2713
|
},
|
|
2749
2714
|
});
|
|
2750
2715
|
|
package/package.json
CHANGED
package/skills/qdash/SKILL.md
CHANGED
|
@@ -26,7 +26,7 @@ Prefer the dedicated tool that matches the question. Use `qdash_query` only as a
|
|
|
26
26
|
- `qdash_list_flows`, `qdash_get_flow` — list or inspect calibration flows
|
|
27
27
|
- `qdash_get_pipeline_catalog`, `qdash_plan_pipeline` — compose and check a calibration pipeline spec before running it
|
|
28
28
|
- `qdash_list_executions`, `qdash_get_execution`, `qdash_wait_execution`, `qdash_compare_executions` — inspect, await, or compare executions
|
|
29
|
-
- `
|
|
29
|
+
- `qdash_get_provenance_stats` — inspect provenance status
|
|
30
30
|
- `qdash_list_forum_posts`, `qdash_get_forum_post`, `qdash_list_forum_replies` — inspect Forum context
|
|
31
31
|
- `qdash_preview_forum_evidence_reply`, `qdash_preview_forum_image_reply` — preview evidence or image replies without writing
|
|
32
32
|
- `qdash_get_figure`, `qdash_get_task_figures`, `qdash_recent_calibration_figure`, `qdash_analyze_figure_json`, `qdash_build_qcal_evidence` — inspect or package figure evidence
|
|
@@ -164,5 +164,5 @@ When the user wants to preserve an investigated observation in QDash forum/notes
|
|
|
164
164
|
- Use `qdash_compare_calibration` when the user asks what changed between recent calibration experiments; treat differences as evidence, not automatic approval to commit/apply parameters.
|
|
165
165
|
- Use `qdash_recent_calibration_figure` when the user asks to see recent experiment images without a task ID.
|
|
166
166
|
- Use `qdash_analyze_figure_json` for read-only numeric summaries of Plotly JSON calibration figures; keep domain-specific interpretation in the matching skill.
|
|
167
|
-
- Use `qdash_build_qcal_evidence` when the user wants to evaluate a QDash calibration task with pi-
|
|
167
|
+
- Use `qdash_build_qcal_evidence` when the user wants to evaluate a QDash calibration task with pi-qcaleval. It only summarizes QDash data and returns the task figure; pass the summary as `context` to `qcal_evaluate` for the actual evaluation.
|
|
168
168
|
- Prefer summarizing large responses with counts, IDs, time ranges, and notable values.
|