@kweaver-ai/kweaver-sdk 0.7.4 → 0.8.2
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 +39 -5
- package/README.zh.md +37 -5
- 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/agent-observability.d.ts +51 -0
- package/dist/api/agent-observability.js +108 -0
- package/dist/api/context-loader.d.ts +1 -0
- package/dist/api/conversations.d.ts +4 -8
- package/dist/api/conversations.js +16 -58
- package/dist/api/datasources.d.ts +2 -20
- package/dist/api/datasources.js +7 -123
- 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 +49 -0
- package/dist/api/trace.js +85 -0
- package/dist/api/vega.d.ts +53 -0
- package/dist/api/vega.js +144 -0
- package/dist/cli.js +12 -5
- package/dist/commands/agent/mode.d.ts +6 -0
- package/dist/commands/agent/mode.js +75 -0
- package/dist/commands/agent.js +101 -29
- package/dist/commands/bkn-ops.js +12 -6
- package/dist/commands/bkn-utils.d.ts +9 -0
- package/dist/commands/bkn-utils.js +17 -0
- package/dist/commands/context-loader.js +608 -38
- package/dist/commands/ds.js +7 -2
- package/dist/commands/skill.d.ts +21 -1
- package/dist/commands/skill.js +389 -1
- package/dist/commands/trace.d.ts +39 -0
- package/dist/commands/trace.js +668 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/resources/bkn.d.ts +5 -0
- package/dist/resources/bkn.js +5 -0
- package/dist/resources/datasources.js +2 -1
- 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/excessive-tool-calls-per-turn.d.ts +2 -0
- package/dist/trace-ai/diagnose/builtin-rules/excessive-tool-calls-per-turn.js +15 -0
- package/dist/trace-ai/diagnose/builtin-rules/excessive-tool-calls-per-turn.yaml +16 -0
- package/dist/trace-ai/diagnose/builtin-rules/llm-response-truncated-no-continue.d.ts +2 -0
- package/dist/trace-ai/diagnose/builtin-rules/llm-response-truncated-no-continue.js +44 -0
- package/dist/trace-ai/diagnose/builtin-rules/llm-response-truncated-no-continue.yaml +15 -0
- package/dist/trace-ai/diagnose/builtin-rules/register.d.ts +1 -0
- package/dist/trace-ai/diagnose/builtin-rules/register.js +11 -0
- package/dist/trace-ai/diagnose/builtin-rules/retrieval-empty-no-fallback.d.ts +2 -0
- package/dist/trace-ai/diagnose/builtin-rules/retrieval-empty-no-fallback.js +29 -0
- package/dist/trace-ai/diagnose/builtin-rules/retrieval-empty-no-fallback.yaml +15 -0
- package/dist/trace-ai/diagnose/builtin-rules/tool-error-swallowed.d.ts +2 -0
- package/dist/trace-ai/diagnose/builtin-rules/tool-error-swallowed.js +45 -0
- package/dist/trace-ai/diagnose/builtin-rules/tool-error-swallowed.yaml +15 -0
- package/dist/trace-ai/diagnose/builtin-rules/tool-loop-no-state-change.d.ts +2 -0
- package/dist/trace-ai/diagnose/builtin-rules/tool-loop-no-state-change.js +38 -0
- package/dist/trace-ai/diagnose/builtin-rules/tool-loop-no-state-change.yaml +16 -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/predicate-registry.d.ts +7 -0
- package/dist/trace-ai/diagnose/predicate-registry.js +30 -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-ai/diagnose/report-assembler.js +100 -0
- package/dist/trace-ai/diagnose/report-markdown.d.ts +18 -0
- package/dist/trace-ai/diagnose/report-markdown.js +192 -0
- package/dist/trace-ai/diagnose/rule-loader.d.ts +11 -0
- package/dist/trace-ai/diagnose/rule-loader.js +120 -0
- package/dist/trace-ai/diagnose/schemas.d.ts +184 -0
- 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-ai/diagnose/synthesizer-template.d.ts +2 -0
- package/dist/trace-ai/diagnose/synthesizer-template.js +49 -0
- package/dist/trace-ai/diagnose/trace-shaper.d.ts +3 -0
- package/dist/trace-ai/diagnose/trace-shaper.js +73 -0
- package/dist/trace-ai/diagnose/types.d.ts +173 -0
- package/dist/trace-ai/diagnose/types.js +1 -0
- 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 +14 -4
package/dist/api/skills.js
CHANGED
|
@@ -87,6 +87,11 @@ export async function getSkill(options) {
|
|
|
87
87
|
const { body } = await fetchTextOrThrow(url, { headers: baseHeaders(options) });
|
|
88
88
|
return normalizeSkillId(unwrapEnvelope(body));
|
|
89
89
|
}
|
|
90
|
+
export async function getSkillMarketDetail(options) {
|
|
91
|
+
const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/market/${encodeURIComponent(options.skillId)}`);
|
|
92
|
+
const { body } = await fetchTextOrThrow(url, { headers: baseHeaders(options) });
|
|
93
|
+
return normalizeSkillId(unwrapEnvelope(body));
|
|
94
|
+
}
|
|
90
95
|
export async function deleteSkill(options) {
|
|
91
96
|
const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}`);
|
|
92
97
|
const { body } = await fetchTextOrThrow(url, { method: "DELETE", headers: baseHeaders(options) });
|
|
@@ -101,14 +106,49 @@ export async function updateSkillStatus(options) {
|
|
|
101
106
|
});
|
|
102
107
|
return normalizeSkillId(unwrapEnvelope(body));
|
|
103
108
|
}
|
|
109
|
+
export async function updateSkillMetadata(options) {
|
|
110
|
+
const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}/metadata`);
|
|
111
|
+
const payload = {
|
|
112
|
+
name: options.name,
|
|
113
|
+
description: options.description,
|
|
114
|
+
category: options.category,
|
|
115
|
+
};
|
|
116
|
+
if (options.source)
|
|
117
|
+
payload.source = options.source;
|
|
118
|
+
if (options.extendInfo)
|
|
119
|
+
payload.extend_info = options.extendInfo;
|
|
120
|
+
const { body } = await fetchTextOrThrow(url, {
|
|
121
|
+
method: "PUT",
|
|
122
|
+
headers: { ...baseHeaders(options), "content-type": "application/json" },
|
|
123
|
+
body: JSON.stringify(payload),
|
|
124
|
+
});
|
|
125
|
+
return normalizeSkillId(unwrapEnvelope(body));
|
|
126
|
+
}
|
|
104
127
|
export async function registerSkillContent(options) {
|
|
128
|
+
// Backend's file_type=content path is half-implemented: it stores
|
|
129
|
+
// the markdown body but skips skill_file_index, so the skill is
|
|
130
|
+
// unreadable after publish (GET /skills/:id/content -> 404).
|
|
131
|
+
// Bundle the content into a 1-file SKILL.md zip and route through
|
|
132
|
+
// the zip path, which writes skill_file_index correctly.
|
|
133
|
+
const { default: JSZip } = await import("jszip");
|
|
134
|
+
const zip = new JSZip();
|
|
135
|
+
zip.file("SKILL.md", options.content);
|
|
136
|
+
const bytes = new Uint8Array(await zip.generateAsync({ type: "uint8array", compression: "DEFLATE" }));
|
|
137
|
+
return registerSkillZip({
|
|
138
|
+
baseUrl: options.baseUrl,
|
|
139
|
+
accessToken: options.accessToken,
|
|
140
|
+
businessDomain: options.businessDomain,
|
|
141
|
+
filename: "SKILL.md.zip",
|
|
142
|
+
bytes,
|
|
143
|
+
source: options.source,
|
|
144
|
+
extendInfo: options.extendInfo,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
export async function registerSkillZip(options) {
|
|
105
148
|
const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills`);
|
|
106
149
|
const form = new FormData();
|
|
107
|
-
form.set("file_type", "
|
|
108
|
-
|
|
109
|
-
// (typed json.RawMessage); needs an actual multipart file part with
|
|
110
|
-
// filename. See utils/gin.go GetBindMultipartFormRaw.
|
|
111
|
-
form.set("file", new Blob([options.content], { type: "text/markdown" }), "SKILL.md");
|
|
150
|
+
form.set("file_type", "zip");
|
|
151
|
+
form.set("file", new Blob([Buffer.from(options.bytes)]), options.filename);
|
|
112
152
|
if (options.source)
|
|
113
153
|
form.set("source", options.source);
|
|
114
154
|
if (options.extendInfo)
|
|
@@ -120,17 +160,22 @@ export async function registerSkillContent(options) {
|
|
|
120
160
|
});
|
|
121
161
|
return normalizeSkillId(unwrapEnvelope(body));
|
|
122
162
|
}
|
|
123
|
-
export async function
|
|
124
|
-
const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills`);
|
|
163
|
+
export async function updateSkillPackageContent(options) {
|
|
164
|
+
const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}/package`);
|
|
165
|
+
const { body } = await fetchTextOrThrow(url, {
|
|
166
|
+
method: "PUT",
|
|
167
|
+
headers: { ...baseHeaders(options), "content-type": "application/json" },
|
|
168
|
+
body: JSON.stringify({ file_type: "content", file: options.content }),
|
|
169
|
+
});
|
|
170
|
+
return normalizeSkillId(unwrapEnvelope(body));
|
|
171
|
+
}
|
|
172
|
+
export async function updateSkillPackageZip(options) {
|
|
173
|
+
const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}/package`);
|
|
125
174
|
const form = new FormData();
|
|
126
175
|
form.set("file_type", "zip");
|
|
127
176
|
form.set("file", new Blob([Buffer.from(options.bytes)]), options.filename);
|
|
128
|
-
if (options.source)
|
|
129
|
-
form.set("source", options.source);
|
|
130
|
-
if (options.extendInfo)
|
|
131
|
-
form.set("extend_info", JSON.stringify(options.extendInfo));
|
|
132
177
|
const { body } = await fetchTextOrThrow(url, {
|
|
133
|
-
method: "
|
|
178
|
+
method: "PUT",
|
|
134
179
|
headers: baseHeaders(options),
|
|
135
180
|
body: form,
|
|
136
181
|
});
|
|
@@ -169,6 +214,57 @@ export async function downloadSkill(options) {
|
|
|
169
214
|
bytes: body,
|
|
170
215
|
};
|
|
171
216
|
}
|
|
217
|
+
export async function listSkillHistory(options) {
|
|
218
|
+
const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}/history`);
|
|
219
|
+
const { body } = await fetchTextOrThrow(url, { headers: baseHeaders(options) });
|
|
220
|
+
return normalizeSkillId(unwrapEnvelope(body));
|
|
221
|
+
}
|
|
222
|
+
export async function republishSkillHistory(options) {
|
|
223
|
+
const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}/history/republish`);
|
|
224
|
+
const { body } = await fetchTextOrThrow(url, {
|
|
225
|
+
method: "POST",
|
|
226
|
+
headers: { ...baseHeaders(options), "content-type": "application/json" },
|
|
227
|
+
body: JSON.stringify({ version: options.version }),
|
|
228
|
+
});
|
|
229
|
+
return normalizeSkillId(unwrapEnvelope(body));
|
|
230
|
+
}
|
|
231
|
+
export async function publishSkillHistory(options) {
|
|
232
|
+
const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}/history/publish`);
|
|
233
|
+
const { body } = await fetchTextOrThrow(url, {
|
|
234
|
+
method: "POST",
|
|
235
|
+
headers: { ...baseHeaders(options), "content-type": "application/json" },
|
|
236
|
+
body: JSON.stringify({ version: options.version }),
|
|
237
|
+
});
|
|
238
|
+
return normalizeSkillId(unwrapEnvelope(body));
|
|
239
|
+
}
|
|
240
|
+
// ── Management Content (editing-state) API ───────────────────────────────────
|
|
241
|
+
export async function getSkillManagementContent(options) {
|
|
242
|
+
const url = new URL(buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}/management/content`));
|
|
243
|
+
if (options.responseMode)
|
|
244
|
+
url.searchParams.set("response_mode", options.responseMode);
|
|
245
|
+
const { body } = await fetchTextOrThrow(url, { headers: baseHeaders(options) });
|
|
246
|
+
return unwrapEnvelope(body);
|
|
247
|
+
}
|
|
248
|
+
export async function readSkillManagementFile(options) {
|
|
249
|
+
const url = buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}/management/files/read`);
|
|
250
|
+
const { body } = await fetchTextOrThrow(url, {
|
|
251
|
+
method: "POST",
|
|
252
|
+
headers: { ...baseHeaders(options), "content-type": "application/json" },
|
|
253
|
+
body: JSON.stringify({ rel_path: options.relPath }),
|
|
254
|
+
});
|
|
255
|
+
return normalizeSkillId(unwrapEnvelope(body));
|
|
256
|
+
}
|
|
257
|
+
export async function downloadSkillManagementArchive(options) {
|
|
258
|
+
const url = new URL(buildUrl(options.baseUrl, `${SKILL_API_PREFIX}/skills/${encodeURIComponent(options.skillId)}/management/download`));
|
|
259
|
+
if (options.responseMode)
|
|
260
|
+
url.searchParams.set("response_mode", options.responseMode);
|
|
261
|
+
const { response, body } = await fetchBytesOrThrow(url, { headers: baseHeaders(options) });
|
|
262
|
+
const serverName = parseContentDisposition(response.headers.get("content-disposition"));
|
|
263
|
+
return {
|
|
264
|
+
fileName: basename(serverName || `${options.skillId}.zip`),
|
|
265
|
+
bytes: body,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
172
268
|
export function installSkillArchive(options) {
|
|
173
269
|
const targetDir = resolve(options.directory);
|
|
174
270
|
const existed = existsSync(targetDir);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `RawSpan`-flavored view of conversation trace data, for diagnose rule
|
|
3
|
+
* predicates. The HTTP / two-hop / auth concerns live in `./agent-observability`;
|
|
4
|
+
* this module only normalizes the raw `_source` documents into the minimal
|
|
5
|
+
* span shape rules read.
|
|
6
|
+
*/
|
|
7
|
+
export { TraceFetchError } from "./agent-observability.js";
|
|
8
|
+
export interface GetSpansByConversationIdOpts {
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
token: string;
|
|
11
|
+
businessDomain: string;
|
|
12
|
+
conversationId: string;
|
|
13
|
+
/** Cap on `terms` aggregation bucket count. Default 100. */
|
|
14
|
+
maxTraceIds?: number;
|
|
15
|
+
/** Cap on spans returned by the second query. Default 2000. */
|
|
16
|
+
maxSpans?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface RawSpan {
|
|
19
|
+
spanId: string;
|
|
20
|
+
parentSpanId: string | null;
|
|
21
|
+
name?: string;
|
|
22
|
+
startTimeUnixNano?: string;
|
|
23
|
+
endTimeUnixNano?: string;
|
|
24
|
+
status?: {
|
|
25
|
+
code?: string;
|
|
26
|
+
};
|
|
27
|
+
attributes?: Record<string, unknown>;
|
|
28
|
+
events?: Array<{
|
|
29
|
+
name?: string;
|
|
30
|
+
time?: string;
|
|
31
|
+
attributes?: Record<string, unknown>;
|
|
32
|
+
}>;
|
|
33
|
+
/** OTel traceId for the trace this span belongs to (when known). */
|
|
34
|
+
traceId?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface GetSpansByConversationIdResult {
|
|
37
|
+
/** Distinct traceIds observed for this conversation. */
|
|
38
|
+
traceIds: string[];
|
|
39
|
+
/** All spans across all observed traceIds, mapped to `RawSpan` shape. */
|
|
40
|
+
spans: RawSpan[];
|
|
41
|
+
/** True if the agg saw `sum_other_doc_count > 0` (more traceIds than maxTraceIds). */
|
|
42
|
+
truncated: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* ISO timestamp → nanos-since-epoch string. Preserves up to 9 fractional digits.
|
|
46
|
+
* Falls back to ms precision when the input lacks a fractional component.
|
|
47
|
+
*/
|
|
48
|
+
export declare function isoToNanos(iso: string | undefined): string | undefined;
|
|
49
|
+
export declare function getSpansByConversationId(opts: GetSpansByConversationIdOpts): Promise<GetSpansByConversationIdResult>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `RawSpan`-flavored view of conversation trace data, for diagnose rule
|
|
3
|
+
* predicates. The HTTP / two-hop / auth concerns live in `./agent-observability`;
|
|
4
|
+
* this module only normalizes the raw `_source` documents into the minimal
|
|
5
|
+
* span shape rules read.
|
|
6
|
+
*/
|
|
7
|
+
import { fetchRawSpansByConversation } from "./agent-observability.js";
|
|
8
|
+
export { TraceFetchError } from "./agent-observability.js";
|
|
9
|
+
/**
|
|
10
|
+
* ISO timestamp → nanos-since-epoch string. Preserves up to 9 fractional digits.
|
|
11
|
+
* Falls back to ms precision when the input lacks a fractional component.
|
|
12
|
+
*/
|
|
13
|
+
export function isoToNanos(iso) {
|
|
14
|
+
if (!iso)
|
|
15
|
+
return undefined;
|
|
16
|
+
// "YYYY-MM-DDTHH:MM:SS.fffffffffZ" or "...+08:00"
|
|
17
|
+
const m = iso.match(/^(.+?)\.(\d{1,9})(Z|[+-]\d{2}:?\d{2})$/);
|
|
18
|
+
if (!m) {
|
|
19
|
+
const ms = Date.parse(iso);
|
|
20
|
+
if (Number.isNaN(ms))
|
|
21
|
+
return undefined;
|
|
22
|
+
return (BigInt(ms) * 1000000n).toString();
|
|
23
|
+
}
|
|
24
|
+
const ms = Date.parse(m[1] + m[3]);
|
|
25
|
+
if (Number.isNaN(ms))
|
|
26
|
+
return undefined;
|
|
27
|
+
const frac = m[2].padEnd(9, "0").slice(0, 9);
|
|
28
|
+
const seconds = BigInt(Math.floor(ms / 1000));
|
|
29
|
+
return (seconds * 1000000000n + BigInt(frac)).toString();
|
|
30
|
+
}
|
|
31
|
+
function normalizeToRawSpan(source) {
|
|
32
|
+
const spanIdRaw = source.spanId ?? source.span_id;
|
|
33
|
+
const spanId = typeof spanIdRaw === "string" ? spanIdRaw : "";
|
|
34
|
+
if (!spanId)
|
|
35
|
+
return null;
|
|
36
|
+
const parentRaw = source.parentSpanId ?? source.parent_span_id ?? source.parentSpanID;
|
|
37
|
+
const parentSpanId = typeof parentRaw === "string" && parentRaw !== "" && parentRaw !== "0" ? parentRaw : null;
|
|
38
|
+
// Prefer pre-normalized nanos (synthetic fixtures); else derive from ISO.
|
|
39
|
+
let startTimeUnixNano;
|
|
40
|
+
let endTimeUnixNano;
|
|
41
|
+
if (typeof source.startTimeUnixNano === "string")
|
|
42
|
+
startTimeUnixNano = source.startTimeUnixNano;
|
|
43
|
+
else if (typeof source.startTime === "string")
|
|
44
|
+
startTimeUnixNano = isoToNanos(source.startTime);
|
|
45
|
+
if (typeof source.endTimeUnixNano === "string")
|
|
46
|
+
endTimeUnixNano = source.endTimeUnixNano;
|
|
47
|
+
else if (typeof source.endTime === "string")
|
|
48
|
+
endTimeUnixNano = isoToNanos(source.endTime);
|
|
49
|
+
const status = source.status;
|
|
50
|
+
const attributes = source.attributes;
|
|
51
|
+
const events = Array.isArray(source.events)
|
|
52
|
+
? source.events
|
|
53
|
+
: undefined;
|
|
54
|
+
const name = typeof source.name === "string" ? source.name : undefined;
|
|
55
|
+
const traceIdRaw = source.traceId ?? source.trace_id;
|
|
56
|
+
const traceId = typeof traceIdRaw === "string" ? traceIdRaw : undefined;
|
|
57
|
+
return {
|
|
58
|
+
spanId,
|
|
59
|
+
parentSpanId,
|
|
60
|
+
name,
|
|
61
|
+
startTimeUnixNano,
|
|
62
|
+
endTimeUnixNano,
|
|
63
|
+
status,
|
|
64
|
+
attributes,
|
|
65
|
+
events,
|
|
66
|
+
traceId,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export async function getSpansByConversationId(opts) {
|
|
70
|
+
const fetched = await fetchRawSpansByConversation({
|
|
71
|
+
baseUrl: opts.baseUrl,
|
|
72
|
+
accessToken: opts.token,
|
|
73
|
+
businessDomain: opts.businessDomain,
|
|
74
|
+
conversationId: opts.conversationId,
|
|
75
|
+
maxTraceIds: opts.maxTraceIds,
|
|
76
|
+
maxSpans: opts.maxSpans,
|
|
77
|
+
});
|
|
78
|
+
const spans = [];
|
|
79
|
+
for (const src of fetched.rawSources) {
|
|
80
|
+
const span = normalizeToRawSpan(src);
|
|
81
|
+
if (span)
|
|
82
|
+
spans.push(span);
|
|
83
|
+
}
|
|
84
|
+
return { traceIds: fetched.traceIds, spans, truncated: fetched.truncated };
|
|
85
|
+
}
|
package/dist/api/vega.d.ts
CHANGED
|
@@ -238,3 +238,56 @@ export interface ListAllVegaResourcesOptions {
|
|
|
238
238
|
/** List all Vega resources (no catalog filter). Uses GET /resources — not /resources/list, which
|
|
239
239
|
* conflicts with GET /resources/{id} on some gateways (path segment "list" is treated as an id). */
|
|
240
240
|
export declare function listAllVegaResources(options: ListAllVegaResourcesOptions): Promise<string>;
|
|
241
|
+
export interface ListTablesWithColumnsOptions {
|
|
242
|
+
baseUrl: string;
|
|
243
|
+
accessToken: string;
|
|
244
|
+
/** A vega catalog id, not a legacy data-connection datasource UUID. */
|
|
245
|
+
id: string;
|
|
246
|
+
keyword?: string;
|
|
247
|
+
limit?: number;
|
|
248
|
+
offset?: number;
|
|
249
|
+
businessDomain?: string;
|
|
250
|
+
autoScan?: boolean;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* List tables with column details from a vega catalog.
|
|
254
|
+
*
|
|
255
|
+
* Two-stage fetch:
|
|
256
|
+
* 1. GET /api/vega-backend/v1/catalogs/{id}/resources?category=table — list summaries
|
|
257
|
+
* 2. For each resource: GET /api/vega-backend/v1/resources/{rid} — pull source_metadata.columns
|
|
258
|
+
*
|
|
259
|
+
* If the catalog has no resources and `autoScan=true`, triggers a discover and
|
|
260
|
+
* retries the list once. The optional `keyword` filters summaries client-side
|
|
261
|
+
* before the per-resource detail fetches — useful to keep N+1 down to k+1.
|
|
262
|
+
*
|
|
263
|
+
* `id` is a vega catalog id.
|
|
264
|
+
*/
|
|
265
|
+
export declare function listTablesWithColumns(options: ListTablesWithColumnsOptions): Promise<string>;
|
|
266
|
+
export interface ScanMetadataOptions {
|
|
267
|
+
baseUrl: string;
|
|
268
|
+
accessToken: string;
|
|
269
|
+
id: string;
|
|
270
|
+
/** Retained for signature compatibility; ignored — vega catalog already knows its connector_type. */
|
|
271
|
+
dsType?: string;
|
|
272
|
+
businessDomain?: string;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Trigger a metadata scan for a vega catalog and wait for completion.
|
|
276
|
+
* `id` is a vega catalog id (e.g. `d7nicrcjto2s73d9g67g`), not a legacy
|
|
277
|
+
* data-connection datasource UUID.
|
|
278
|
+
*/
|
|
279
|
+
export declare function scanMetadata(options: ScanMetadataOptions): Promise<string>;
|
|
280
|
+
export interface ScanDatasourceMetadataOptions {
|
|
281
|
+
baseUrl: string;
|
|
282
|
+
accessToken: string;
|
|
283
|
+
id: string;
|
|
284
|
+
businessDomain?: string;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Trigger a metadata scan and wait for completion. `id` is a vega catalog id.
|
|
288
|
+
*
|
|
289
|
+
* @deprecated Use {@link scanMetadata} directly. This wrapper exists only for
|
|
290
|
+
* backward compatibility with callers that used the old data-connection-based
|
|
291
|
+
* `scanDatasourceMetadata` signature.
|
|
292
|
+
*/
|
|
293
|
+
export declare function scanDatasourceMetadata(options: ScanDatasourceMetadataOptions): Promise<string>;
|
package/dist/api/vega.js
CHANGED
|
@@ -488,3 +488,147 @@ export async function listAllVegaResources(options) {
|
|
|
488
488
|
businessDomain,
|
|
489
489
|
});
|
|
490
490
|
}
|
|
491
|
+
/**
|
|
492
|
+
* List tables with column details from a vega catalog.
|
|
493
|
+
*
|
|
494
|
+
* Two-stage fetch:
|
|
495
|
+
* 1. GET /api/vega-backend/v1/catalogs/{id}/resources?category=table — list summaries
|
|
496
|
+
* 2. For each resource: GET /api/vega-backend/v1/resources/{rid} — pull source_metadata.columns
|
|
497
|
+
*
|
|
498
|
+
* If the catalog has no resources and `autoScan=true`, triggers a discover and
|
|
499
|
+
* retries the list once. The optional `keyword` filters summaries client-side
|
|
500
|
+
* before the per-resource detail fetches — useful to keep N+1 down to k+1.
|
|
501
|
+
*
|
|
502
|
+
* `id` is a vega catalog id.
|
|
503
|
+
*/
|
|
504
|
+
export async function listTablesWithColumns(options) {
|
|
505
|
+
const { baseUrl, accessToken, id, keyword, limit, offset, businessDomain = "bd_public", autoScan = true, } = options;
|
|
506
|
+
async function listResourceSummaries() {
|
|
507
|
+
const body = await listVegaCatalogResources({
|
|
508
|
+
baseUrl,
|
|
509
|
+
accessToken,
|
|
510
|
+
id,
|
|
511
|
+
category: "table",
|
|
512
|
+
limit,
|
|
513
|
+
offset,
|
|
514
|
+
businessDomain,
|
|
515
|
+
});
|
|
516
|
+
const parsed = JSON.parse(body);
|
|
517
|
+
return Array.isArray(parsed) ? parsed : (parsed.entries ?? parsed.data ?? []);
|
|
518
|
+
}
|
|
519
|
+
let summaries = await listResourceSummaries();
|
|
520
|
+
if (summaries.length === 0 && autoScan) {
|
|
521
|
+
await scanMetadata({ baseUrl, accessToken, id, businessDomain });
|
|
522
|
+
summaries = await listResourceSummaries();
|
|
523
|
+
}
|
|
524
|
+
// Keyword filter applied after autoScan guard: if the catalog has tables but
|
|
525
|
+
// keyword matches none, we must NOT trigger a redundant discover.
|
|
526
|
+
if (keyword) {
|
|
527
|
+
const k = keyword.toLowerCase();
|
|
528
|
+
summaries = summaries.filter((it) => it.name.toLowerCase().includes(k));
|
|
529
|
+
}
|
|
530
|
+
const details = await Promise.all(summaries.map(async (s) => {
|
|
531
|
+
let body;
|
|
532
|
+
try {
|
|
533
|
+
body = await getVegaResource({
|
|
534
|
+
baseUrl,
|
|
535
|
+
accessToken,
|
|
536
|
+
id: s.id,
|
|
537
|
+
businessDomain,
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
catch (err) {
|
|
541
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
542
|
+
throw new Error(`vega resource ${s.id} fetch failed: ${reason}`);
|
|
543
|
+
}
|
|
544
|
+
const parsed = JSON.parse(body);
|
|
545
|
+
if (Array.isArray(parsed.entries)) {
|
|
546
|
+
const arr = parsed.entries;
|
|
547
|
+
if (arr.length === 0) {
|
|
548
|
+
throw new Error(`vega resource ${s.id} returned empty entries`);
|
|
549
|
+
}
|
|
550
|
+
return arr[0];
|
|
551
|
+
}
|
|
552
|
+
if (Array.isArray(parsed.data)) {
|
|
553
|
+
const arr = parsed.data;
|
|
554
|
+
if (arr.length === 0) {
|
|
555
|
+
throw new Error(`vega resource ${s.id} returned empty data`);
|
|
556
|
+
}
|
|
557
|
+
return arr[0];
|
|
558
|
+
}
|
|
559
|
+
return parsed;
|
|
560
|
+
}));
|
|
561
|
+
const tables = [];
|
|
562
|
+
for (const d of details) {
|
|
563
|
+
const columnsRaw = (d.source_metadata?.columns ?? []);
|
|
564
|
+
const tablePkArray = extractPrimaryKeys(d);
|
|
565
|
+
const columns = columnsRaw.map((c) => {
|
|
566
|
+
const name = String(c.name ?? c.field_name ?? "");
|
|
567
|
+
const flagged = isColumnPrimaryKey(c) || tablePkArray.includes(name);
|
|
568
|
+
return {
|
|
569
|
+
name,
|
|
570
|
+
type: String(c.type ?? c.field_type ?? "varchar"),
|
|
571
|
+
comment: typeof c.description === "string"
|
|
572
|
+
? c.description
|
|
573
|
+
: (typeof c.comment === "string" ? c.comment : undefined),
|
|
574
|
+
...(flagged ? { isPrimaryKey: true } : {}),
|
|
575
|
+
};
|
|
576
|
+
});
|
|
577
|
+
const synthesizedPks = tablePkArray.length > 0
|
|
578
|
+
? tablePkArray
|
|
579
|
+
: columns.filter((c) => c.isPrimaryKey).map((c) => c.name);
|
|
580
|
+
tables.push({
|
|
581
|
+
name: d.name,
|
|
582
|
+
columns,
|
|
583
|
+
...(synthesizedPks.length > 0 ? { primaryKeys: synthesizedPks } : {}),
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
return JSON.stringify(tables);
|
|
587
|
+
}
|
|
588
|
+
// Two PK metadata shapes are recognized — both confirmed conventions:
|
|
589
|
+
// - per-column `is_primary_key: true` (data-connection metadata standard)
|
|
590
|
+
// - per-column `column_key === "PRI"` (MySQL INFORMATION_SCHEMA pass-through)
|
|
591
|
+
// - table-level `primary_keys: string[]` (composite-PK carrier)
|
|
592
|
+
// Other plausible spellings (camelCase, singular keys, SQLite `pk` integer) are
|
|
593
|
+
// intentionally NOT recognized here — adding them speculatively risks false
|
|
594
|
+
// matches and creates code paths the test suite can't pin down. Extend only when
|
|
595
|
+
// a real backend response demonstrates the need.
|
|
596
|
+
function isColumnPrimaryKey(col) {
|
|
597
|
+
if (col.is_primary_key === true)
|
|
598
|
+
return true;
|
|
599
|
+
if (typeof col.column_key === "string" && col.column_key.toUpperCase() === "PRI")
|
|
600
|
+
return true;
|
|
601
|
+
return false;
|
|
602
|
+
}
|
|
603
|
+
function extractPrimaryKeys(table) {
|
|
604
|
+
const arr = table.primary_keys;
|
|
605
|
+
if (Array.isArray(arr)) {
|
|
606
|
+
return arr.filter((x) => typeof x === "string");
|
|
607
|
+
}
|
|
608
|
+
return [];
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Trigger a metadata scan for a vega catalog and wait for completion.
|
|
612
|
+
* `id` is a vega catalog id (e.g. `d7nicrcjto2s73d9g67g`), not a legacy
|
|
613
|
+
* data-connection datasource UUID.
|
|
614
|
+
*/
|
|
615
|
+
export async function scanMetadata(options) {
|
|
616
|
+
const { baseUrl, accessToken, id, businessDomain = "bd_public" } = options;
|
|
617
|
+
return discoverVegaCatalog({
|
|
618
|
+
baseUrl,
|
|
619
|
+
accessToken,
|
|
620
|
+
id,
|
|
621
|
+
wait: true,
|
|
622
|
+
businessDomain,
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Trigger a metadata scan and wait for completion. `id` is a vega catalog id.
|
|
627
|
+
*
|
|
628
|
+
* @deprecated Use {@link scanMetadata} directly. This wrapper exists only for
|
|
629
|
+
* backward compatibility with callers that used the old data-connection-based
|
|
630
|
+
* `scanDatasourceMetadata` signature.
|
|
631
|
+
*/
|
|
632
|
+
export async function scanDatasourceMetadata(options) {
|
|
633
|
+
return scanMetadata(options);
|
|
634
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -108,8 +108,9 @@ Usage:
|
|
|
108
108
|
kweaver config list-bd
|
|
109
109
|
kweaver config show
|
|
110
110
|
|
|
111
|
-
kweaver skill list|get|register|status|delete [options]
|
|
111
|
+
kweaver skill list|get|market-get|register|status|delete [options]
|
|
112
112
|
kweaver skill market [options]
|
|
113
|
+
kweaver skill update-metadata|update-package|history|republish|publish-history [options]
|
|
113
114
|
kweaver skill content <skill-id> [--raw] [--output file]
|
|
114
115
|
kweaver skill read-file <skill-id> <rel-path> [--raw] [--output file]
|
|
115
116
|
kweaver skill download|install <skill-id> [path] [options]
|
|
@@ -134,14 +135,15 @@ Usage:
|
|
|
134
135
|
kweaver vega query execute|sql [options]
|
|
135
136
|
kweaver vega connector-type list|get [options]
|
|
136
137
|
|
|
138
|
+
kweaver context-loader help <subcommand>
|
|
137
139
|
kweaver context-loader config set|use|list|remove|show [options] (deprecated; not supported with --token)
|
|
138
140
|
kweaver context-loader tools|resources|templates|prompts <kn-id> [--cursor]
|
|
139
141
|
kweaver context-loader resource <kn-id> <uri>
|
|
140
142
|
kweaver context-loader prompt <kn-id> <name> [--args json]
|
|
141
|
-
kweaver context-loader search-schema <kn-id> <query> [--scope object,relation,action,metric] [--max N]
|
|
143
|
+
kweaver context-loader search-schema <kn-id> <query> [--scope object,relation,action,metric] [--concept-groups ids] [--max N]
|
|
142
144
|
kweaver context-loader tool-call <kn-id> <name> --args '<json>'
|
|
143
|
-
kweaver context-loader kn-search <kn-id> <query> [--only-schema] (
|
|
144
|
-
kweaver context-loader kn-schema-search <kn-id> <query> [--max N] (
|
|
145
|
+
kweaver context-loader kn-search <kn-id> <query> [--only-schema] (deprecated; use search-schema)
|
|
146
|
+
kweaver context-loader kn-schema-search <kn-id> <query> [--max N] (deprecated; use search-schema)
|
|
145
147
|
kweaver context-loader query-object-instance|query-instance-subgraph|get-logic-properties|get-action-info|find-skills <kn-id> ...
|
|
146
148
|
(omit <kn-id> to fall back to deprecated saved config)
|
|
147
149
|
(alias: kweaver context ...)
|
|
@@ -178,11 +180,12 @@ Commands:
|
|
|
178
180
|
bkn Knowledge network (CRUD, build, validate, export, stats, push/pull,
|
|
179
181
|
object-type, relation-type, subgraph, action-type, action-execution, action-log)
|
|
180
182
|
config Per-platform configuration (business domain)
|
|
181
|
-
skill Skill registry and market (register,
|
|
183
|
+
skill Skill registry and market (register, edit, history, progressive read, download/install)
|
|
182
184
|
toolbox Agent toolbox lifecycle (create, list, publish, delete, export, import)
|
|
183
185
|
tool Tools inside a toolbox (upload OpenAPI spec, list, enable/disable)
|
|
184
186
|
vega Vega observability (catalog, resource, query/sql, connector-type, health/stats/inspect)
|
|
185
187
|
context-loader Context-loader MCP/HTTP (config, tools, resources, search-schema, tool-call, query-*, etc.)
|
|
188
|
+
trace Diagnose a single trace with rule-based analysis
|
|
186
189
|
help Show this message`);
|
|
187
190
|
}
|
|
188
191
|
export async function run(argv) {
|
|
@@ -287,6 +290,10 @@ export async function run(argv) {
|
|
|
287
290
|
if (command === "context-loader" || command === "context") {
|
|
288
291
|
return runContextLoaderCommand(rest);
|
|
289
292
|
}
|
|
293
|
+
if (command === "trace") {
|
|
294
|
+
const { runTraceCommand } = await import("./commands/trace.js");
|
|
295
|
+
return await runTraceCommand(rest);
|
|
296
|
+
}
|
|
290
297
|
console.error(`Unknown command: ${command}`);
|
|
291
298
|
printHelp();
|
|
292
299
|
return 1;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const AGENT_MODES: readonly ["default", "dolphin", "react"];
|
|
2
|
+
export type AgentMode = typeof AGENT_MODES[number];
|
|
3
|
+
export declare const AGENT_MODE_HELP = " --mode <mode> Agent mode: default, dolphin, react (default: default)\n\nAgent mode config:\n config.mode accepts \"default\", \"dolphin\", or \"react\".\n If --mode is provided, it overrides config.mode.\n If neither --mode nor config.mode is provided, the CLI sends config.mode=\"default\".\n\nReAct config:\n react_config is only valid when mode is \"react\".\n Provide it through --config or --config-path, for example:\n {\n \"mode\": \"react\",\n \"react_config\": {\n \"disable_history_in_a_conversation\": false,\n \"disable_llm_cache\": false\n }\n }";
|
|
4
|
+
export declare function parseAgentMode(value: string, flagName?: string): AgentMode;
|
|
5
|
+
export declare function normalizeAgentConfigInput(value: unknown): Record<string, unknown>;
|
|
6
|
+
export declare function applyAgentModeToConfig(config: Record<string, unknown>, explicitMode?: AgentMode): void;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export const AGENT_MODES = ["default", "dolphin", "react"];
|
|
2
|
+
const AGENT_MODE_SET = new Set(AGENT_MODES);
|
|
3
|
+
export const AGENT_MODE_HELP = ` --mode <mode> Agent mode: default, dolphin, react (default: default)
|
|
4
|
+
|
|
5
|
+
Agent mode config:
|
|
6
|
+
config.mode accepts "default", "dolphin", or "react".
|
|
7
|
+
If --mode is provided, it overrides config.mode.
|
|
8
|
+
If neither --mode nor config.mode is provided, the CLI sends config.mode="default".
|
|
9
|
+
|
|
10
|
+
ReAct config:
|
|
11
|
+
react_config is only valid when mode is "react".
|
|
12
|
+
Provide it through --config or --config-path, for example:
|
|
13
|
+
{
|
|
14
|
+
"mode": "react",
|
|
15
|
+
"react_config": {
|
|
16
|
+
"disable_history_in_a_conversation": false,
|
|
17
|
+
"disable_llm_cache": false
|
|
18
|
+
}
|
|
19
|
+
}`;
|
|
20
|
+
function formatModeValue(value) {
|
|
21
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
22
|
+
}
|
|
23
|
+
function isRecord(value) {
|
|
24
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25
|
+
}
|
|
26
|
+
function looksLikeAgentConfig(value) {
|
|
27
|
+
return [
|
|
28
|
+
"mode",
|
|
29
|
+
"input",
|
|
30
|
+
"output",
|
|
31
|
+
"llms",
|
|
32
|
+
"react_config",
|
|
33
|
+
"system_prompt",
|
|
34
|
+
"data_source",
|
|
35
|
+
"skills",
|
|
36
|
+
"memory",
|
|
37
|
+
"conversation_history_config",
|
|
38
|
+
].some((field) => field in value);
|
|
39
|
+
}
|
|
40
|
+
export function parseAgentMode(value, flagName = "--mode") {
|
|
41
|
+
const mode = value.trim();
|
|
42
|
+
if (!AGENT_MODE_SET.has(mode)) {
|
|
43
|
+
throw new Error(`${flagName} must be one of: ${AGENT_MODES.join(", ")}`);
|
|
44
|
+
}
|
|
45
|
+
return mode;
|
|
46
|
+
}
|
|
47
|
+
export function normalizeAgentConfigInput(value) {
|
|
48
|
+
if (!isRecord(value)) {
|
|
49
|
+
throw new Error("Agent config file must contain a JSON object.");
|
|
50
|
+
}
|
|
51
|
+
const nestedConfig = value.config;
|
|
52
|
+
if (isRecord(nestedConfig) && !looksLikeAgentConfig(value)) {
|
|
53
|
+
return nestedConfig;
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
export function applyAgentModeToConfig(config, explicitMode) {
|
|
58
|
+
if (explicitMode) {
|
|
59
|
+
config.mode = explicitMode;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const currentMode = config.mode;
|
|
63
|
+
if (currentMode === undefined || currentMode === null || currentMode === "") {
|
|
64
|
+
config.mode = "default";
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (typeof currentMode !== "string") {
|
|
68
|
+
throw new Error(`config.mode must be one of: ${AGENT_MODES.join(", ")}; got ${formatModeValue(currentMode)}`);
|
|
69
|
+
}
|
|
70
|
+
const mode = currentMode.trim();
|
|
71
|
+
if (!AGENT_MODE_SET.has(mode)) {
|
|
72
|
+
throw new Error(`config.mode must be one of: ${AGENT_MODES.join(", ")}; got ${formatModeValue(currentMode)}`);
|
|
73
|
+
}
|
|
74
|
+
config.mode = mode;
|
|
75
|
+
}
|