@kweaver-ai/kweaver-sdk 0.8.1 → 0.8.3
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/README.md +40 -52
- package/README.zh.md +41 -46
- package/dist/agent-providers/index.d.ts +7 -0
- package/dist/agent-providers/index.js +5 -0
- package/dist/agent-providers/prompt-template.d.ts +62 -0
- package/dist/agent-providers/prompt-template.js +105 -0
- package/dist/agent-providers/prompts/rubric-judge-v1.prompt.md +51 -0
- package/dist/agent-providers/prompts/within-trace-synthesizer-v1.prompt.md +60 -0
- package/dist/agent-providers/providers/claude-code-subprocess.d.ts +74 -0
- package/dist/agent-providers/providers/claude-code-subprocess.js +259 -0
- package/dist/agent-providers/providers/stub.d.ts +47 -0
- package/dist/agent-providers/providers/stub.js +77 -0
- package/dist/agent-providers/registry.d.ts +45 -0
- package/dist/agent-providers/registry.js +77 -0
- package/dist/agent-providers/types.d.ts +91 -0
- package/dist/agent-providers/types.js +25 -0
- package/dist/api/agent-chat.js +8 -6
- package/dist/api/context-loader.d.ts +1 -0
- package/dist/api/resources.d.ts +94 -0
- package/dist/api/resources.js +166 -0
- package/dist/api/semantic-search.d.ts +5 -0
- package/dist/api/semantic-search.js +5 -0
- package/dist/api/skills.d.ts +75 -2
- package/dist/api/skills.js +108 -12
- package/dist/api/trace.d.ts +5 -0
- package/dist/api/trace.js +4 -0
- package/dist/cli.js +109 -15
- package/dist/client.d.ts +3 -3
- package/dist/client.js +5 -5
- package/dist/commands/agent/mode.d.ts +6 -0
- package/dist/commands/agent/mode.js +75 -0
- package/dist/commands/agent-members.js +27 -11
- package/dist/commands/agent.js +469 -286
- package/dist/commands/auth.js +184 -71
- package/dist/commands/bkn-metric.js +37 -16
- package/dist/commands/bkn-ops.js +164 -86
- package/dist/commands/bkn-query.js +99 -31
- package/dist/commands/bkn-schema.d.ts +3 -3
- package/dist/commands/bkn-schema.js +127 -86
- package/dist/commands/bkn.js +153 -114
- package/dist/commands/call.js +23 -13
- package/dist/commands/config.js +22 -12
- package/dist/commands/context-loader.js +625 -49
- package/dist/commands/dataflow.js +14 -6
- package/dist/commands/ds.js +52 -30
- package/dist/commands/explore.js +18 -15
- package/dist/commands/model.js +53 -42
- package/dist/commands/resource.d.ts +1 -0
- package/dist/commands/{dataview.js → resource.js} +62 -84
- package/dist/commands/skill.d.ts +21 -1
- package/dist/commands/skill.js +567 -43
- package/dist/commands/token.js +11 -0
- package/dist/commands/tool.js +46 -29
- package/dist/commands/toolbox.js +31 -15
- package/dist/commands/trace.d.ts +26 -1
- package/dist/commands/trace.js +515 -15
- package/dist/commands/vega.js +466 -250
- package/dist/help/format.d.ts +65 -0
- package/dist/help/format.js +141 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +3 -3
- package/dist/resources/bkn.d.ts +5 -0
- package/dist/resources/bkn.js +5 -0
- package/dist/resources/{dataviews.d.ts → resources.d.ts} +10 -11
- package/dist/resources/{dataviews.js → resources.js} +12 -13
- package/dist/resources/skills.d.ts +17 -1
- package/dist/resources/skills.js +32 -1
- package/dist/trace-ai/diagnose/agent-binding.d.ts +67 -0
- package/dist/trace-ai/diagnose/agent-binding.js +257 -0
- package/dist/trace-ai/diagnose/builtin-rules/tool-retry-intent-mismatch.yaml +68 -0
- package/dist/trace-ai/diagnose/index.d.ts +32 -0
- package/dist/trace-ai/diagnose/index.js +246 -0
- package/dist/trace-ai/diagnose/output-schema-converter.d.ts +24 -0
- package/dist/trace-ai/diagnose/output-schema-converter.js +81 -0
- package/dist/trace-ai/diagnose/query-extractor.d.ts +14 -0
- package/dist/trace-ai/diagnose/query-extractor.js +45 -0
- package/dist/trace-ai/diagnose/report-assembler.d.ts +31 -0
- package/dist/{trace-core → trace-ai}/diagnose/report-assembler.js +19 -9
- package/dist/trace-ai/diagnose/report-markdown.d.ts +18 -0
- package/dist/trace-ai/diagnose/report-markdown.js +192 -0
- package/dist/{trace-core → trace-ai}/diagnose/rule-loader.js +42 -8
- package/dist/{trace-core → trace-ai}/diagnose/schemas.d.ts +77 -2
- package/dist/trace-ai/diagnose/schemas.js +154 -0
- package/dist/trace-ai/diagnose/signal-probe.d.ts +17 -0
- package/dist/trace-ai/diagnose/signal-probe.js +39 -0
- package/dist/trace-ai/diagnose/synthesizer-agent.d.ts +40 -0
- package/dist/trace-ai/diagnose/synthesizer-agent.js +158 -0
- package/dist/{trace-core → trace-ai}/diagnose/trace-shaper.js +1 -0
- package/dist/{trace-core → trace-ai}/diagnose/types.d.ts +55 -6
- package/dist/trace-ai/eval-set/assertion-evaluator.d.ts +29 -0
- package/dist/trace-ai/eval-set/assertion-evaluator.js +100 -0
- package/dist/trace-ai/eval-set/builder.d.ts +36 -0
- package/dist/trace-ai/eval-set/builder.js +126 -0
- package/dist/trace-ai/eval-set/index.d.ts +15 -0
- package/dist/trace-ai/eval-set/index.js +10 -0
- package/dist/trace-ai/eval-set/output-writer.d.ts +27 -0
- package/dist/trace-ai/eval-set/output-writer.js +126 -0
- package/dist/trace-ai/eval-set/query-picker.d.ts +37 -0
- package/dist/trace-ai/eval-set/query-picker.js +147 -0
- package/dist/trace-ai/eval-set/redactor.d.ts +42 -0
- package/dist/trace-ai/eval-set/redactor.js +133 -0
- package/dist/trace-ai/eval-set/rubric-templates/answer-match-reference.prompt.md +19 -0
- package/dist/trace-ai/eval-set/schemas.d.ts +136 -0
- package/dist/trace-ai/eval-set/schemas.js +130 -0
- package/dist/trace-ai/eval-set/semantic-match-provider.d.ts +33 -0
- package/dist/trace-ai/eval-set/semantic-match-provider.js +51 -0
- package/dist/trace-ai/eval-set/test-runner.d.ts +34 -0
- package/dist/trace-ai/eval-set/test-runner.js +153 -0
- package/dist/trace-ai/eval-set/types.d.ts +46 -0
- package/dist/trace-ai/eval-set/types.js +8 -0
- package/dist/trace-ai/exp/bundle-writer.d.ts +10 -0
- package/dist/trace-ai/exp/bundle-writer.js +54 -0
- package/dist/trace-ai/exp/claude-binary.d.ts +5 -0
- package/dist/trace-ai/exp/claude-binary.js +30 -0
- package/dist/trace-ai/exp/coordinator.d.ts +45 -0
- package/dist/trace-ai/exp/coordinator.js +203 -0
- package/dist/trace-ai/exp/eval-runner.d.ts +14 -0
- package/dist/trace-ai/exp/eval-runner.js +47 -0
- package/dist/trace-ai/exp/exp-store/abort-signal.d.ts +3 -0
- package/dist/trace-ai/exp/exp-store/abort-signal.js +27 -0
- package/dist/trace-ai/exp/exp-store/candidate-lineage-yaml.d.ts +4 -0
- package/dist/trace-ai/exp/exp-store/candidate-lineage-yaml.js +37 -0
- package/dist/trace-ai/exp/exp-store/events-jsonl.d.ts +17 -0
- package/dist/trace-ai/exp/exp-store/events-jsonl.js +60 -0
- package/dist/trace-ai/exp/exp-store/exp-registry.d.ts +6 -0
- package/dist/trace-ai/exp/exp-store/exp-registry.js +41 -0
- package/dist/trace-ai/exp/exp-store/index.d.ts +46 -0
- package/dist/trace-ai/exp/exp-store/index.js +59 -0
- package/dist/trace-ai/exp/exp-store/lock.d.ts +3 -0
- package/dist/trace-ai/exp/exp-store/lock.js +73 -0
- package/dist/trace-ai/exp/exp-store/mission-md.d.ts +3 -0
- package/dist/trace-ai/exp/exp-store/mission-md.js +37 -0
- package/dist/trace-ai/exp/exp-store/readme-template.d.ts +5 -0
- package/dist/trace-ai/exp/exp-store/readme-template.js +25 -0
- package/dist/trace-ai/exp/exp-store/round-yaml.d.ts +3 -0
- package/dist/trace-ai/exp/exp-store/round-yaml.js +33 -0
- package/dist/trace-ai/exp/index.d.ts +8 -0
- package/dist/trace-ai/exp/index.js +238 -0
- package/dist/trace-ai/exp/info.d.ts +35 -0
- package/dist/trace-ai/exp/info.js +120 -0
- package/dist/trace-ai/exp/patch/agent-config.d.ts +1 -0
- package/dist/trace-ai/exp/patch/agent-config.js +26 -0
- package/dist/trace-ai/exp/patch/index.d.ts +2 -0
- package/dist/trace-ai/exp/patch/index.js +13 -0
- package/dist/trace-ai/exp/patch/skill.d.ts +1 -0
- package/dist/trace-ai/exp/patch/skill.js +24 -0
- package/dist/trace-ai/exp/providers/synthesizer-client.d.ts +14 -0
- package/dist/trace-ai/exp/providers/synthesizer-client.js +39 -0
- package/dist/trace-ai/exp/providers/triage-client.d.ts +19 -0
- package/dist/trace-ai/exp/providers/triage-client.js +51 -0
- package/dist/trace-ai/exp/schemas.d.ts +147 -0
- package/dist/trace-ai/exp/schemas.js +50 -0
- package/dist/trace-ai/exp/scoring.d.ts +2 -0
- package/dist/trace-ai/exp/scoring.js +46 -0
- package/dist/trace-ai/scan/aggregator.d.ts +20 -0
- package/dist/trace-ai/scan/aggregator.js +26 -0
- package/dist/trace-ai/scan/artifacts/paths.d.ts +12 -0
- package/dist/trace-ai/scan/artifacts/paths.js +18 -0
- package/dist/trace-ai/scan/artifacts/writer.d.ts +67 -0
- package/dist/trace-ai/scan/artifacts/writer.js +96 -0
- package/dist/trace-ai/scan/batched-rubric.d.ts +55 -0
- package/dist/trace-ai/scan/batched-rubric.js +159 -0
- package/dist/trace-ai/scan/cross-trace-synthesizer.d.ts +24 -0
- package/dist/trace-ai/scan/cross-trace-synthesizer.js +93 -0
- package/dist/trace-ai/scan/index.d.ts +31 -0
- package/dist/trace-ai/scan/index.js +390 -0
- package/dist/trace-ai/scan/prompts/builtin/cross-trace-synthesizer-v1.prompt.md +44 -0
- package/dist/trace-ai/scan/prompts/builtin/rubric-judge-batch-v1.prompt.md +44 -0
- package/dist/trace-ai/scan/runner.d.ts +25 -0
- package/dist/trace-ai/scan/runner.js +42 -0
- package/dist/trace-ai/scan/sampler.d.ts +18 -0
- package/dist/trace-ai/scan/sampler.js +81 -0
- package/dist/trace-ai/scan/scan-summary-markdown.d.ts +2 -0
- package/dist/trace-ai/scan/scan-summary-markdown.js +71 -0
- package/dist/trace-ai/scan/scan-summary-schema.d.ts +73 -0
- package/dist/trace-ai/scan/scan-summary-schema.js +61 -0
- package/dist/trace-ai/scan/single-agent-validator.d.ts +23 -0
- package/dist/trace-ai/scan/single-agent-validator.js +42 -0
- package/dist/trace-ai/scan/traces-list-parser.d.ts +15 -0
- package/dist/trace-ai/scan/traces-list-parser.js +46 -0
- package/package.json +2 -2
- package/dist/api/dataviews.d.ts +0 -117
- package/dist/api/dataviews.js +0 -265
- package/dist/commands/dataview.d.ts +0 -8
- package/dist/trace-core/diagnose/index.d.ts +0 -9
- package/dist/trace-core/diagnose/index.js +0 -104
- package/dist/trace-core/diagnose/report-assembler.d.ts +0 -12
- package/dist/trace-core/diagnose/schemas.js +0 -94
- package/dist/trace-core/diagnose/signal-probe.d.ts +0 -5
- package/dist/trace-core/diagnose/signal-probe.js +0 -21
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/excessive-tool-calls-per-turn.d.ts +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/excessive-tool-calls-per-turn.js +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/excessive-tool-calls-per-turn.yaml +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/llm-response-truncated-no-continue.d.ts +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/llm-response-truncated-no-continue.js +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/llm-response-truncated-no-continue.yaml +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/register.d.ts +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/register.js +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/retrieval-empty-no-fallback.d.ts +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/retrieval-empty-no-fallback.js +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/retrieval-empty-no-fallback.yaml +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/tool-error-swallowed.d.ts +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/tool-error-swallowed.js +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/tool-error-swallowed.yaml +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/tool-loop-no-state-change.d.ts +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/tool-loop-no-state-change.js +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/tool-loop-no-state-change.yaml +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/predicate-registry.d.ts +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/predicate-registry.js +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/rule-loader.d.ts +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/synthesizer-template.d.ts +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/synthesizer-template.js +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/trace-shaper.d.ts +0 -0
- /package/dist/{trace-core → trace-ai}/diagnose/types.js +0 -0
package/dist/api/dataviews.js
DELETED
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { HttpError } from "../utils/http.js";
|
|
3
|
-
import { buildHeaders } from "./headers.js";
|
|
4
|
-
function extractViewId(data) {
|
|
5
|
-
if (Array.isArray(data) && data.length > 0) {
|
|
6
|
-
const item = data[0];
|
|
7
|
-
if (typeof item === "string")
|
|
8
|
-
return item;
|
|
9
|
-
if (item && typeof item === "object" && "id" in item) {
|
|
10
|
-
return String(item.id ?? "");
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
if (data && typeof data === "object" && "id" in data) {
|
|
14
|
-
return String(data.id ?? "");
|
|
15
|
-
}
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
export function parseDataView(raw) {
|
|
19
|
-
const fieldsRaw = raw.fields;
|
|
20
|
-
let fields;
|
|
21
|
-
if (Array.isArray(fieldsRaw) && fieldsRaw.length > 0) {
|
|
22
|
-
fields = [];
|
|
23
|
-
for (const f of fieldsRaw) {
|
|
24
|
-
if (f && typeof f === "object") {
|
|
25
|
-
const fr = f;
|
|
26
|
-
fields.push({
|
|
27
|
-
name: String(fr.name ?? ""),
|
|
28
|
-
type: String(fr.type ?? "varchar"),
|
|
29
|
-
display_name: fr.display_name != null ? String(fr.display_name) : undefined,
|
|
30
|
-
comment: fr.comment != null ? String(fr.comment) : undefined,
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
const dv = {
|
|
36
|
-
id: String(raw.id ?? ""),
|
|
37
|
-
name: String(raw.name ?? ""),
|
|
38
|
-
query_type: String(raw.query_type ?? "SQL"),
|
|
39
|
-
datasource_id: String(raw.data_source_id ?? raw.group_id ?? ""),
|
|
40
|
-
};
|
|
41
|
-
if (raw.type != null)
|
|
42
|
-
dv.type = String(raw.type);
|
|
43
|
-
if (raw.data_source_type != null)
|
|
44
|
-
dv.data_source_type = String(raw.data_source_type);
|
|
45
|
-
if (raw.data_source_name != null)
|
|
46
|
-
dv.data_source_name = String(raw.data_source_name);
|
|
47
|
-
if (raw.sql_str != null)
|
|
48
|
-
dv.sql_str = String(raw.sql_str);
|
|
49
|
-
if (raw.meta_table_name != null)
|
|
50
|
-
dv.meta_table_name = String(raw.meta_table_name);
|
|
51
|
-
if (fields)
|
|
52
|
-
dv.fields = fields;
|
|
53
|
-
return dv;
|
|
54
|
-
}
|
|
55
|
-
function extractListPayload(data) {
|
|
56
|
-
if (Array.isArray(data))
|
|
57
|
-
return data;
|
|
58
|
-
if (data && typeof data === "object") {
|
|
59
|
-
const obj = data;
|
|
60
|
-
const items = obj.entries ?? obj.data;
|
|
61
|
-
if (Array.isArray(items))
|
|
62
|
-
return items;
|
|
63
|
-
}
|
|
64
|
-
return [];
|
|
65
|
-
}
|
|
66
|
-
export async function createDataView(options) {
|
|
67
|
-
const { baseUrl, accessToken, name, datasourceId, table, fields = [], businessDomain = "bd_public", } = options;
|
|
68
|
-
const viewId = createHash("md5").update(`${datasourceId}:${table}`).digest("hex").slice(0, 35);
|
|
69
|
-
const body = JSON.stringify([
|
|
70
|
-
{
|
|
71
|
-
id: viewId,
|
|
72
|
-
name,
|
|
73
|
-
technical_name: table,
|
|
74
|
-
type: "atomic",
|
|
75
|
-
query_type: "SQL",
|
|
76
|
-
data_source_id: datasourceId,
|
|
77
|
-
group_id: datasourceId,
|
|
78
|
-
fields,
|
|
79
|
-
},
|
|
80
|
-
]);
|
|
81
|
-
const base = baseUrl.replace(/\/+$/, "");
|
|
82
|
-
const url = `${base}/api/mdl-data-model/v1/data-views`;
|
|
83
|
-
const response = await fetch(url, {
|
|
84
|
-
method: "POST",
|
|
85
|
-
headers: {
|
|
86
|
-
...buildHeaders(accessToken, businessDomain),
|
|
87
|
-
"content-type": "application/json",
|
|
88
|
-
},
|
|
89
|
-
body,
|
|
90
|
-
});
|
|
91
|
-
const responseBody = await response.text();
|
|
92
|
-
if (!response.ok) {
|
|
93
|
-
// If DataView already exists (403 with "Existed" error code), delete and recreate
|
|
94
|
-
if (response.status === 403) {
|
|
95
|
-
try {
|
|
96
|
-
const errBody = JSON.parse(responseBody);
|
|
97
|
-
if (errBody.error_code?.includes("Existed")) {
|
|
98
|
-
const actualId = await findDataViewByName({ baseUrl, accessToken, name, groupId: datasourceId, businessDomain });
|
|
99
|
-
if (actualId && fields.length > 0) {
|
|
100
|
-
// Delete the bare DataView (created by scanMetadata) and recreate with fields
|
|
101
|
-
await deleteDataView({ baseUrl, accessToken, id: actualId, businessDomain });
|
|
102
|
-
const retryResponse = await fetch(url, {
|
|
103
|
-
method: "POST",
|
|
104
|
-
headers: { ...buildHeaders(accessToken, businessDomain), "content-type": "application/json" },
|
|
105
|
-
body,
|
|
106
|
-
});
|
|
107
|
-
if (retryResponse.ok) {
|
|
108
|
-
const retryBody = await retryResponse.text();
|
|
109
|
-
const retryId = extractViewId(JSON.parse(retryBody));
|
|
110
|
-
return retryId ?? viewId;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (actualId)
|
|
114
|
-
return actualId;
|
|
115
|
-
return viewId;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
catch { /* fall through to throw */ }
|
|
119
|
-
}
|
|
120
|
-
throw new HttpError(response.status, response.statusText, responseBody);
|
|
121
|
-
}
|
|
122
|
-
const createdId = extractViewId(JSON.parse(responseBody));
|
|
123
|
-
return createdId ?? viewId;
|
|
124
|
-
}
|
|
125
|
-
async function findDataViewByName(options) {
|
|
126
|
-
const list = await listDataViews({
|
|
127
|
-
baseUrl: options.baseUrl,
|
|
128
|
-
accessToken: options.accessToken,
|
|
129
|
-
businessDomain: options.businessDomain,
|
|
130
|
-
name: options.name,
|
|
131
|
-
});
|
|
132
|
-
const match = list.find((e) => e.name === options.name && e.datasource_id === options.groupId);
|
|
133
|
-
return match?.id ?? null;
|
|
134
|
-
}
|
|
135
|
-
export async function listDataViews(options) {
|
|
136
|
-
const { baseUrl, accessToken, businessDomain = "bd_public", datasourceId, name, type, limit = 30, } = options;
|
|
137
|
-
const base = baseUrl.replace(/\/+$/, "");
|
|
138
|
-
const url = new URL(`${base}/api/mdl-data-model/v1/data-views`);
|
|
139
|
-
url.searchParams.set("limit", String(limit));
|
|
140
|
-
if (datasourceId)
|
|
141
|
-
url.searchParams.set("data_source_id", datasourceId);
|
|
142
|
-
if (name)
|
|
143
|
-
url.searchParams.set("keyword", name);
|
|
144
|
-
if (type)
|
|
145
|
-
url.searchParams.set("type", type);
|
|
146
|
-
const response = await fetch(url.toString(), {
|
|
147
|
-
method: "GET",
|
|
148
|
-
headers: buildHeaders(accessToken, businessDomain),
|
|
149
|
-
});
|
|
150
|
-
const bodyText = await response.text();
|
|
151
|
-
if (!response.ok) {
|
|
152
|
-
throw new HttpError(response.status, response.statusText, bodyText);
|
|
153
|
-
}
|
|
154
|
-
const parsed = JSON.parse(bodyText);
|
|
155
|
-
const items = extractListPayload(parsed);
|
|
156
|
-
const out = [];
|
|
157
|
-
for (const item of items) {
|
|
158
|
-
if (item && typeof item === "object") {
|
|
159
|
-
out.push(parseDataView(item));
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
return out;
|
|
163
|
-
}
|
|
164
|
-
export async function deleteDataView(options) {
|
|
165
|
-
const { baseUrl, accessToken, id, businessDomain = "bd_public" } = options;
|
|
166
|
-
const base = baseUrl.replace(/\/+$/, "");
|
|
167
|
-
const url = `${base}/api/mdl-data-model/v1/data-views/${encodeURIComponent(id)}`;
|
|
168
|
-
const response = await fetch(url, {
|
|
169
|
-
method: "DELETE",
|
|
170
|
-
headers: buildHeaders(accessToken, businessDomain),
|
|
171
|
-
});
|
|
172
|
-
const bodyText = await response.text();
|
|
173
|
-
if (!response.ok) {
|
|
174
|
-
throw new HttpError(response.status, response.statusText, bodyText);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
export async function getDataView(options) {
|
|
178
|
-
const { baseUrl, accessToken, id, businessDomain = "bd_public", } = options;
|
|
179
|
-
const base = baseUrl.replace(/\/+$/, "");
|
|
180
|
-
const url = `${base}/api/mdl-data-model/v1/data-views/${encodeURIComponent(id)}`;
|
|
181
|
-
const response = await fetch(url, {
|
|
182
|
-
method: "GET",
|
|
183
|
-
headers: buildHeaders(accessToken, businessDomain),
|
|
184
|
-
});
|
|
185
|
-
const body = await response.text();
|
|
186
|
-
if (!response.ok) {
|
|
187
|
-
throw new HttpError(response.status, response.statusText, body);
|
|
188
|
-
}
|
|
189
|
-
let parsed = JSON.parse(body);
|
|
190
|
-
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
191
|
-
parsed = parsed[0];
|
|
192
|
-
}
|
|
193
|
-
if (!parsed || typeof parsed !== "object") {
|
|
194
|
-
throw new HttpError(500, "Invalid response", body);
|
|
195
|
-
}
|
|
196
|
-
return parseDataView(parsed);
|
|
197
|
-
}
|
|
198
|
-
function sleepMs(ms) {
|
|
199
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Find data views by name. Uses server-side keyword filtering; when `exact` is true,
|
|
203
|
-
* applies client-side `name ===` filter. Optional polling with exponential backoff.
|
|
204
|
-
*/
|
|
205
|
-
export async function findDataView(options) {
|
|
206
|
-
const { baseUrl, accessToken, businessDomain = "bd_public", name, datasourceId, exact = false, wait = false, timeoutMs = 30_000, } = options;
|
|
207
|
-
const deadline = Date.now() + timeoutMs;
|
|
208
|
-
let attempt = 0;
|
|
209
|
-
while (true) {
|
|
210
|
-
const list = await listDataViews({
|
|
211
|
-
baseUrl,
|
|
212
|
-
accessToken,
|
|
213
|
-
businessDomain,
|
|
214
|
-
datasourceId,
|
|
215
|
-
name,
|
|
216
|
-
limit: -1,
|
|
217
|
-
});
|
|
218
|
-
const results = exact ? list.filter((v) => v.name === name) : list;
|
|
219
|
-
if (results.length > 0 || !wait || Date.now() >= deadline)
|
|
220
|
-
return results;
|
|
221
|
-
const delayMs = Math.min(5000, 1000 * 2 ** attempt);
|
|
222
|
-
attempt += 1;
|
|
223
|
-
await sleepMs(delayMs);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Execute a query against a data view (POST /api/mdl-uniquery/v1/data-views/:id).
|
|
228
|
-
* When `sql` is omitted, the server uses the view's stored SQL definition.
|
|
229
|
-
*/
|
|
230
|
-
export async function queryDataView(options) {
|
|
231
|
-
const { baseUrl, accessToken, id, sql, offset = 0, limit = 50, needTotal = false, outputFields, filters, sort, businessDomain = "bd_public", } = options;
|
|
232
|
-
const base = baseUrl.replace(/\/+$/, "");
|
|
233
|
-
const url = `${base}/api/mdl-uniquery/v1/data-views/${encodeURIComponent(id)}`;
|
|
234
|
-
const body = {
|
|
235
|
-
offset,
|
|
236
|
-
limit,
|
|
237
|
-
need_total: needTotal,
|
|
238
|
-
};
|
|
239
|
-
if (sql !== undefined && sql !== "")
|
|
240
|
-
body.sql = sql;
|
|
241
|
-
if (outputFields !== undefined)
|
|
242
|
-
body.output_fields = outputFields;
|
|
243
|
-
if (filters !== undefined)
|
|
244
|
-
body.filters = filters;
|
|
245
|
-
if (sort !== undefined)
|
|
246
|
-
body.sort = sort;
|
|
247
|
-
const response = await fetch(url, {
|
|
248
|
-
method: "POST",
|
|
249
|
-
headers: {
|
|
250
|
-
...buildHeaders(accessToken, businessDomain),
|
|
251
|
-
"content-type": "application/json",
|
|
252
|
-
"x-http-method-override": "GET",
|
|
253
|
-
},
|
|
254
|
-
body: JSON.stringify(body),
|
|
255
|
-
});
|
|
256
|
-
const bodyText = await response.text();
|
|
257
|
-
if (!response.ok) {
|
|
258
|
-
throw new HttpError(response.status, response.statusText, bodyText);
|
|
259
|
-
}
|
|
260
|
-
const parsed = JSON.parse(bodyText);
|
|
261
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
262
|
-
return parsed;
|
|
263
|
-
}
|
|
264
|
-
return {};
|
|
265
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Strip SQL line/block comments and leading whitespace, then return the first identifier token (lowercase).
|
|
3
|
-
* Used to reject DDL/DML passed to dataview query (server applies LIMIT semantics).
|
|
4
|
-
*/
|
|
5
|
-
export declare function getFirstSqlTokenAfterComments(sql: string): string;
|
|
6
|
-
/** True if ad-hoc SQL is safe for dataview query (SELECT / WITH only). */
|
|
7
|
-
export declare function isDataviewSelectLikeSql(sql: string): boolean;
|
|
8
|
-
export declare function runDataviewCommand(args: string[]): Promise<number>;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { RuleLoadError } from "./rule-loader.js";
|
|
2
|
-
import { RuleProbeError } from "./signal-probe.js";
|
|
3
|
-
import type { DiagnoseOpts, Report } from "./types.js";
|
|
4
|
-
import "./builtin-rules/register.js";
|
|
5
|
-
export declare class TraceNotFoundError extends Error {
|
|
6
|
-
constructor(conversationId: string);
|
|
7
|
-
}
|
|
8
|
-
export declare function diagnose(conversationId: string, opts: DiagnoseOpts): Promise<Report>;
|
|
9
|
-
export { TraceNotFoundError as DiagnoseTraceNotFound, RuleLoadError, RuleProbeError };
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import yaml from "js-yaml";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { getSpansByConversationId } from "../../api/trace.js";
|
|
6
|
-
import { assembleTraceTree } from "./trace-shaper.js";
|
|
7
|
-
import { loadRules, RuleLoadError } from "./rule-loader.js";
|
|
8
|
-
import { runRules, RuleProbeError } from "./signal-probe.js";
|
|
9
|
-
import { templateSynthesize } from "./synthesizer-template.js";
|
|
10
|
-
import { assembleReport, reportToYamlObject } from "./report-assembler.js";
|
|
11
|
-
import "./builtin-rules/register.js"; // side effect: registers all builtin predicates
|
|
12
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
const BUILTIN_DIR = path.join(__dirname, "builtin-rules");
|
|
14
|
-
export class TraceNotFoundError extends Error {
|
|
15
|
-
constructor(conversationId) {
|
|
16
|
-
super(`no spans found for conversation: ${conversationId}`);
|
|
17
|
-
this.name = "TraceNotFoundError";
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
export async function diagnose(conversationId, opts) {
|
|
21
|
-
// PR-A: opts.noLlm, opts.agentProvider, opts.timeoutMs are reserved for PR-B's
|
|
22
|
-
// agent / rubric path; they are accepted by the interface but not consumed here.
|
|
23
|
-
const cwdRulesDir = opts.rulesDir ?? path.join(process.cwd(), "diagnosis-rules");
|
|
24
|
-
const fetched = await getSpansByConversationId({
|
|
25
|
-
baseUrl: opts.baseUrl,
|
|
26
|
-
token: opts.token,
|
|
27
|
-
businessDomain: opts.businessDomain,
|
|
28
|
-
conversationId,
|
|
29
|
-
});
|
|
30
|
-
const rawSpans = fetched.spans;
|
|
31
|
-
if (rawSpans.length === 0)
|
|
32
|
-
throw new TraceNotFoundError(conversationId);
|
|
33
|
-
// A conversation may produce multiple OTel traces (one per turn). PR-A
|
|
34
|
-
// diagnose is single-trace: pick the first observed traceId; warn on extras.
|
|
35
|
-
const observedTraceIds = fetched.traceIds.length > 0
|
|
36
|
-
? fetched.traceIds
|
|
37
|
-
: [...new Set(rawSpans.map((s) => s.traceId).filter((t) => Boolean(t)))];
|
|
38
|
-
const primaryTraceId = observedTraceIds[0] ?? conversationId;
|
|
39
|
-
if (observedTraceIds.length > 1) {
|
|
40
|
-
process.stderr.write(`warning: conversation ${conversationId} has ${observedTraceIds.length} traces; diagnosing the first (${primaryTraceId})\n`);
|
|
41
|
-
}
|
|
42
|
-
const spansForPrimary = observedTraceIds.length > 0
|
|
43
|
-
? rawSpans.filter((s) => !s.traceId || s.traceId === primaryTraceId)
|
|
44
|
-
: rawSpans;
|
|
45
|
-
const tree = assembleTraceTree(primaryTraceId, spansForPrimary);
|
|
46
|
-
const rules = await loadRules({
|
|
47
|
-
builtinDir: BUILTIN_DIR,
|
|
48
|
-
cwdRulesDir,
|
|
49
|
-
extraRulesDir: null,
|
|
50
|
-
noBuiltin: opts.noBuiltin,
|
|
51
|
-
});
|
|
52
|
-
const hits = await runRules(rules, tree);
|
|
53
|
-
const version = await cliVersion();
|
|
54
|
-
// Build provisional findings list to feed the synthesizer.
|
|
55
|
-
const provisionalReport = assembleReport({
|
|
56
|
-
traceId: primaryTraceId,
|
|
57
|
-
agentId: extractAgentId(tree),
|
|
58
|
-
tenant: extractTenant(tree),
|
|
59
|
-
cliVersion: version,
|
|
60
|
-
rules,
|
|
61
|
-
hits,
|
|
62
|
-
summary: { headline: "", primaryRootCause: null, fixPriority: [], crossFindingLinks: [] },
|
|
63
|
-
});
|
|
64
|
-
const summary = templateSynthesize(provisionalReport.findings);
|
|
65
|
-
const report = { ...provisionalReport, summary };
|
|
66
|
-
if (opts.out !== null) {
|
|
67
|
-
await fs.mkdir(path.dirname(opts.out), { recursive: true });
|
|
68
|
-
await fs.writeFile(opts.out, yaml.dump(reportToYamlObject(report)), "utf8");
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
process.stdout.write(yaml.dump(reportToYamlObject(report)));
|
|
72
|
-
}
|
|
73
|
-
if (report.findings.length === 0) {
|
|
74
|
-
process.stderr.write("no findings\n");
|
|
75
|
-
}
|
|
76
|
-
return report;
|
|
77
|
-
}
|
|
78
|
-
function extractAgentId(tree) {
|
|
79
|
-
for (const s of tree.spans) {
|
|
80
|
-
const v = s.attributes["gen_ai.agent.id"];
|
|
81
|
-
if (typeof v === "string")
|
|
82
|
-
return v;
|
|
83
|
-
}
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
function extractTenant(tree) {
|
|
87
|
-
for (const s of tree.spans) {
|
|
88
|
-
const v = s.attributes["tenant"];
|
|
89
|
-
if (typeof v === "string")
|
|
90
|
-
return v;
|
|
91
|
-
}
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
async function cliVersion() {
|
|
95
|
-
try {
|
|
96
|
-
const pkgPath = path.join(__dirname, "..", "..", "..", "package.json");
|
|
97
|
-
const txt = await fs.readFile(pkgPath, "utf8");
|
|
98
|
-
return JSON.parse(txt).version ?? "0.0.0";
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
return "0.0.0";
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
export { TraceNotFoundError as DiagnoseTraceNotFound, RuleLoadError, RuleProbeError };
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Hit, Report, Rule, Summary } from "./types.js";
|
|
2
|
-
export interface AssembleReportOpts {
|
|
3
|
-
traceId: string;
|
|
4
|
-
agentId: string | null;
|
|
5
|
-
tenant: string | null;
|
|
6
|
-
cliVersion: string;
|
|
7
|
-
rules: Rule[];
|
|
8
|
-
hits: Map<string, Hit[]>;
|
|
9
|
-
summary: Summary;
|
|
10
|
-
}
|
|
11
|
-
export declare function assembleReport(opts: AssembleReportOpts): Report;
|
|
12
|
-
export declare function reportToYamlObject(r: Report): unknown;
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
const TaxonomySchema = z.object({
|
|
3
|
-
signals_axis: z.enum(["interaction", "execution", "environment"]),
|
|
4
|
-
ms_class: z.enum([
|
|
5
|
-
"retry_loop",
|
|
6
|
-
"tool_misuse",
|
|
7
|
-
"context_loss",
|
|
8
|
-
"goal_drift",
|
|
9
|
-
"cascading_error",
|
|
10
|
-
"silent_quality_degradation",
|
|
11
|
-
]),
|
|
12
|
-
});
|
|
13
|
-
const SuggestedFixSchema = z.object({
|
|
14
|
-
target: z.string().min(1),
|
|
15
|
-
change_template: z.string().min(1),
|
|
16
|
-
});
|
|
17
|
-
const VerifyWithSchema = z.object({
|
|
18
|
-
assertion_templates: z.array(z.string()).default([]),
|
|
19
|
-
});
|
|
20
|
-
// PR-A: only `predicate` branch (rubric XOR enforced in PR-B).
|
|
21
|
-
// We still encode the XOR shape so PR-B can enable rubric without breaking parsers.
|
|
22
|
-
export const RuleSchema = z
|
|
23
|
-
.object({
|
|
24
|
-
schema_version: z.literal("diagnosis-rule/v1"),
|
|
25
|
-
id: z.string().regex(/^[a-z][a-z0-9_]*$/),
|
|
26
|
-
severity: z.enum(["low", "medium", "high"]),
|
|
27
|
-
symptom: z.string().min(1),
|
|
28
|
-
taxonomy: TaxonomySchema,
|
|
29
|
-
suggested_fix: SuggestedFixSchema,
|
|
30
|
-
verify_with: VerifyWithSchema,
|
|
31
|
-
predicate: z.string().regex(/^builtin:[a-z][a-z0-9_]*$/).optional(),
|
|
32
|
-
rubric: z.unknown().optional(), // PR-B will define a real schema
|
|
33
|
-
params: z.record(z.string(), z.unknown()).default({}),
|
|
34
|
-
})
|
|
35
|
-
.refine((r) => Boolean(r.predicate) !== Boolean(r.rubric), { message: "exactly one of `predicate` or `rubric` must be present" });
|
|
36
|
-
const FindingSchema = z.object({
|
|
37
|
-
rule_id: z.string(),
|
|
38
|
-
judgment_kind: z.enum(["symbolic"]), // PR-B will add "rubric"
|
|
39
|
-
severity: z.enum(["low", "medium", "high"]),
|
|
40
|
-
symptom: z.string(),
|
|
41
|
-
likely_cause: z.string(),
|
|
42
|
-
evidence: z.object({
|
|
43
|
-
spans: z.array(z.string()),
|
|
44
|
-
excerpt: z.string(),
|
|
45
|
-
}),
|
|
46
|
-
suggested_fix: z.object({
|
|
47
|
-
target: z.string(),
|
|
48
|
-
change: z.string(),
|
|
49
|
-
}),
|
|
50
|
-
confidence: z.literal("low"),
|
|
51
|
-
verify_with: z.object({
|
|
52
|
-
suggested_eval_case: z.object({
|
|
53
|
-
query_id: z.string().nullable(),
|
|
54
|
-
query: z.string().nullable(),
|
|
55
|
-
assertions: z.array(z.string()),
|
|
56
|
-
}),
|
|
57
|
-
}),
|
|
58
|
-
});
|
|
59
|
-
const SummarySchema = z.object({
|
|
60
|
-
headline: z.string().max(160),
|
|
61
|
-
primary_root_cause: z
|
|
62
|
-
.object({
|
|
63
|
-
finding_ids: z.array(z.number().int().nonnegative()).min(1),
|
|
64
|
-
description: z.string(),
|
|
65
|
-
target_for_fix: z.string(),
|
|
66
|
-
})
|
|
67
|
-
.nullable(),
|
|
68
|
-
fix_priority: z.array(z.object({
|
|
69
|
-
finding_id: z.number().int().nonnegative(),
|
|
70
|
-
reason: z.string(),
|
|
71
|
-
})),
|
|
72
|
-
cross_finding_links: z.array(z.object({
|
|
73
|
-
finding_ids: z.array(z.number().int().nonnegative()).min(2),
|
|
74
|
-
relation: z.string(),
|
|
75
|
-
})),
|
|
76
|
-
});
|
|
77
|
-
export const ReportSchema = z.object({
|
|
78
|
-
schema_version: z.literal("trace-diagnose-report/v1"),
|
|
79
|
-
trace: z.object({
|
|
80
|
-
trace_id: z.string(),
|
|
81
|
-
agent_id: z.string().nullable(),
|
|
82
|
-
tenant: z.string().nullable(),
|
|
83
|
-
}),
|
|
84
|
-
run: z.object({
|
|
85
|
-
diagnosed_at: z.string(),
|
|
86
|
-
cli_version: z.string(),
|
|
87
|
-
mode: z.enum(["symbolic-only", "rubric-only", "hybrid"]),
|
|
88
|
-
rules_applied: z.array(z.string()),
|
|
89
|
-
rules_skipped: z.array(z.object({ rule_id: z.string(), reason: z.string() })),
|
|
90
|
-
synthesizer_mode: z.enum(["template", "agent"]),
|
|
91
|
-
}),
|
|
92
|
-
summary: SummarySchema,
|
|
93
|
-
findings: z.array(FindingSchema),
|
|
94
|
-
});
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { resolvePredicate } from "./predicate-registry.js";
|
|
2
|
-
export class RuleProbeError extends Error {
|
|
3
|
-
constructor(ruleId, cause) {
|
|
4
|
-
super(`predicate failed for rule '${ruleId}': ${cause.message}`);
|
|
5
|
-
this.name = "RuleProbeError";
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
export async function runRules(rules, tree) {
|
|
9
|
-
const out = new Map();
|
|
10
|
-
for (const rule of rules) {
|
|
11
|
-
const fn = resolvePredicate(rule.predicateRef);
|
|
12
|
-
try {
|
|
13
|
-
const hits = fn(tree, rule.params);
|
|
14
|
-
out.set(rule.id, hits);
|
|
15
|
-
}
|
|
16
|
-
catch (e) {
|
|
17
|
-
throw new RuleProbeError(rule.id, e);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return out;
|
|
21
|
-
}
|
/package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/excessive-tool-calls-per-turn.d.ts
RENAMED
|
File without changes
|
/package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/excessive-tool-calls-per-turn.js
RENAMED
|
File without changes
|
/package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/excessive-tool-calls-per-turn.yaml
RENAMED
|
File without changes
|
/package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/llm-response-truncated-no-continue.d.ts
RENAMED
|
File without changes
|
/package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/llm-response-truncated-no-continue.js
RENAMED
|
File without changes
|
/package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/llm-response-truncated-no-continue.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/retrieval-empty-no-fallback.d.ts
RENAMED
|
File without changes
|
|
File without changes
|
/package/dist/{trace-core → trace-ai}/diagnose/builtin-rules/retrieval-empty-no-fallback.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|