@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.
Files changed (190) hide show
  1. package/README.md +39 -5
  2. package/README.zh.md +37 -5
  3. package/dist/agent-providers/index.d.ts +7 -0
  4. package/dist/agent-providers/index.js +5 -0
  5. package/dist/agent-providers/prompt-template.d.ts +62 -0
  6. package/dist/agent-providers/prompt-template.js +105 -0
  7. package/dist/agent-providers/prompts/rubric-judge-v1.prompt.md +51 -0
  8. package/dist/agent-providers/prompts/within-trace-synthesizer-v1.prompt.md +60 -0
  9. package/dist/agent-providers/providers/claude-code-subprocess.d.ts +74 -0
  10. package/dist/agent-providers/providers/claude-code-subprocess.js +259 -0
  11. package/dist/agent-providers/providers/stub.d.ts +47 -0
  12. package/dist/agent-providers/providers/stub.js +77 -0
  13. package/dist/agent-providers/registry.d.ts +45 -0
  14. package/dist/agent-providers/registry.js +77 -0
  15. package/dist/agent-providers/types.d.ts +91 -0
  16. package/dist/agent-providers/types.js +25 -0
  17. package/dist/api/agent-chat.js +8 -6
  18. package/dist/api/agent-observability.d.ts +51 -0
  19. package/dist/api/agent-observability.js +108 -0
  20. package/dist/api/context-loader.d.ts +1 -0
  21. package/dist/api/conversations.d.ts +4 -8
  22. package/dist/api/conversations.js +16 -58
  23. package/dist/api/datasources.d.ts +2 -20
  24. package/dist/api/datasources.js +7 -123
  25. package/dist/api/semantic-search.d.ts +5 -0
  26. package/dist/api/semantic-search.js +5 -0
  27. package/dist/api/skills.d.ts +75 -2
  28. package/dist/api/skills.js +108 -12
  29. package/dist/api/trace.d.ts +49 -0
  30. package/dist/api/trace.js +85 -0
  31. package/dist/api/vega.d.ts +53 -0
  32. package/dist/api/vega.js +144 -0
  33. package/dist/cli.js +12 -5
  34. package/dist/commands/agent/mode.d.ts +6 -0
  35. package/dist/commands/agent/mode.js +75 -0
  36. package/dist/commands/agent.js +101 -29
  37. package/dist/commands/bkn-ops.js +12 -6
  38. package/dist/commands/bkn-utils.d.ts +9 -0
  39. package/dist/commands/bkn-utils.js +17 -0
  40. package/dist/commands/context-loader.js +608 -38
  41. package/dist/commands/ds.js +7 -2
  42. package/dist/commands/skill.d.ts +21 -1
  43. package/dist/commands/skill.js +389 -1
  44. package/dist/commands/trace.d.ts +39 -0
  45. package/dist/commands/trace.js +668 -0
  46. package/dist/index.d.ts +2 -2
  47. package/dist/index.js +1 -1
  48. package/dist/resources/bkn.d.ts +5 -0
  49. package/dist/resources/bkn.js +5 -0
  50. package/dist/resources/datasources.js +2 -1
  51. package/dist/resources/skills.d.ts +17 -1
  52. package/dist/resources/skills.js +32 -1
  53. package/dist/trace-ai/diagnose/agent-binding.d.ts +67 -0
  54. package/dist/trace-ai/diagnose/agent-binding.js +257 -0
  55. package/dist/trace-ai/diagnose/builtin-rules/excessive-tool-calls-per-turn.d.ts +2 -0
  56. package/dist/trace-ai/diagnose/builtin-rules/excessive-tool-calls-per-turn.js +15 -0
  57. package/dist/trace-ai/diagnose/builtin-rules/excessive-tool-calls-per-turn.yaml +16 -0
  58. package/dist/trace-ai/diagnose/builtin-rules/llm-response-truncated-no-continue.d.ts +2 -0
  59. package/dist/trace-ai/diagnose/builtin-rules/llm-response-truncated-no-continue.js +44 -0
  60. package/dist/trace-ai/diagnose/builtin-rules/llm-response-truncated-no-continue.yaml +15 -0
  61. package/dist/trace-ai/diagnose/builtin-rules/register.d.ts +1 -0
  62. package/dist/trace-ai/diagnose/builtin-rules/register.js +11 -0
  63. package/dist/trace-ai/diagnose/builtin-rules/retrieval-empty-no-fallback.d.ts +2 -0
  64. package/dist/trace-ai/diagnose/builtin-rules/retrieval-empty-no-fallback.js +29 -0
  65. package/dist/trace-ai/diagnose/builtin-rules/retrieval-empty-no-fallback.yaml +15 -0
  66. package/dist/trace-ai/diagnose/builtin-rules/tool-error-swallowed.d.ts +2 -0
  67. package/dist/trace-ai/diagnose/builtin-rules/tool-error-swallowed.js +45 -0
  68. package/dist/trace-ai/diagnose/builtin-rules/tool-error-swallowed.yaml +15 -0
  69. package/dist/trace-ai/diagnose/builtin-rules/tool-loop-no-state-change.d.ts +2 -0
  70. package/dist/trace-ai/diagnose/builtin-rules/tool-loop-no-state-change.js +38 -0
  71. package/dist/trace-ai/diagnose/builtin-rules/tool-loop-no-state-change.yaml +16 -0
  72. package/dist/trace-ai/diagnose/builtin-rules/tool-retry-intent-mismatch.yaml +68 -0
  73. package/dist/trace-ai/diagnose/index.d.ts +32 -0
  74. package/dist/trace-ai/diagnose/index.js +246 -0
  75. package/dist/trace-ai/diagnose/output-schema-converter.d.ts +24 -0
  76. package/dist/trace-ai/diagnose/output-schema-converter.js +81 -0
  77. package/dist/trace-ai/diagnose/predicate-registry.d.ts +7 -0
  78. package/dist/trace-ai/diagnose/predicate-registry.js +30 -0
  79. package/dist/trace-ai/diagnose/query-extractor.d.ts +14 -0
  80. package/dist/trace-ai/diagnose/query-extractor.js +45 -0
  81. package/dist/trace-ai/diagnose/report-assembler.d.ts +31 -0
  82. package/dist/trace-ai/diagnose/report-assembler.js +100 -0
  83. package/dist/trace-ai/diagnose/report-markdown.d.ts +18 -0
  84. package/dist/trace-ai/diagnose/report-markdown.js +192 -0
  85. package/dist/trace-ai/diagnose/rule-loader.d.ts +11 -0
  86. package/dist/trace-ai/diagnose/rule-loader.js +120 -0
  87. package/dist/trace-ai/diagnose/schemas.d.ts +184 -0
  88. package/dist/trace-ai/diagnose/schemas.js +154 -0
  89. package/dist/trace-ai/diagnose/signal-probe.d.ts +17 -0
  90. package/dist/trace-ai/diagnose/signal-probe.js +39 -0
  91. package/dist/trace-ai/diagnose/synthesizer-agent.d.ts +40 -0
  92. package/dist/trace-ai/diagnose/synthesizer-agent.js +158 -0
  93. package/dist/trace-ai/diagnose/synthesizer-template.d.ts +2 -0
  94. package/dist/trace-ai/diagnose/synthesizer-template.js +49 -0
  95. package/dist/trace-ai/diagnose/trace-shaper.d.ts +3 -0
  96. package/dist/trace-ai/diagnose/trace-shaper.js +73 -0
  97. package/dist/trace-ai/diagnose/types.d.ts +173 -0
  98. package/dist/trace-ai/diagnose/types.js +1 -0
  99. package/dist/trace-ai/eval-set/assertion-evaluator.d.ts +29 -0
  100. package/dist/trace-ai/eval-set/assertion-evaluator.js +100 -0
  101. package/dist/trace-ai/eval-set/builder.d.ts +36 -0
  102. package/dist/trace-ai/eval-set/builder.js +126 -0
  103. package/dist/trace-ai/eval-set/index.d.ts +15 -0
  104. package/dist/trace-ai/eval-set/index.js +10 -0
  105. package/dist/trace-ai/eval-set/output-writer.d.ts +27 -0
  106. package/dist/trace-ai/eval-set/output-writer.js +126 -0
  107. package/dist/trace-ai/eval-set/query-picker.d.ts +37 -0
  108. package/dist/trace-ai/eval-set/query-picker.js +147 -0
  109. package/dist/trace-ai/eval-set/redactor.d.ts +42 -0
  110. package/dist/trace-ai/eval-set/redactor.js +133 -0
  111. package/dist/trace-ai/eval-set/rubric-templates/answer-match-reference.prompt.md +19 -0
  112. package/dist/trace-ai/eval-set/schemas.d.ts +136 -0
  113. package/dist/trace-ai/eval-set/schemas.js +130 -0
  114. package/dist/trace-ai/eval-set/semantic-match-provider.d.ts +33 -0
  115. package/dist/trace-ai/eval-set/semantic-match-provider.js +51 -0
  116. package/dist/trace-ai/eval-set/test-runner.d.ts +34 -0
  117. package/dist/trace-ai/eval-set/test-runner.js +153 -0
  118. package/dist/trace-ai/eval-set/types.d.ts +46 -0
  119. package/dist/trace-ai/eval-set/types.js +8 -0
  120. package/dist/trace-ai/exp/bundle-writer.d.ts +10 -0
  121. package/dist/trace-ai/exp/bundle-writer.js +54 -0
  122. package/dist/trace-ai/exp/claude-binary.d.ts +5 -0
  123. package/dist/trace-ai/exp/claude-binary.js +30 -0
  124. package/dist/trace-ai/exp/coordinator.d.ts +45 -0
  125. package/dist/trace-ai/exp/coordinator.js +203 -0
  126. package/dist/trace-ai/exp/eval-runner.d.ts +14 -0
  127. package/dist/trace-ai/exp/eval-runner.js +47 -0
  128. package/dist/trace-ai/exp/exp-store/abort-signal.d.ts +3 -0
  129. package/dist/trace-ai/exp/exp-store/abort-signal.js +27 -0
  130. package/dist/trace-ai/exp/exp-store/candidate-lineage-yaml.d.ts +4 -0
  131. package/dist/trace-ai/exp/exp-store/candidate-lineage-yaml.js +37 -0
  132. package/dist/trace-ai/exp/exp-store/events-jsonl.d.ts +17 -0
  133. package/dist/trace-ai/exp/exp-store/events-jsonl.js +60 -0
  134. package/dist/trace-ai/exp/exp-store/exp-registry.d.ts +6 -0
  135. package/dist/trace-ai/exp/exp-store/exp-registry.js +41 -0
  136. package/dist/trace-ai/exp/exp-store/index.d.ts +46 -0
  137. package/dist/trace-ai/exp/exp-store/index.js +59 -0
  138. package/dist/trace-ai/exp/exp-store/lock.d.ts +3 -0
  139. package/dist/trace-ai/exp/exp-store/lock.js +73 -0
  140. package/dist/trace-ai/exp/exp-store/mission-md.d.ts +3 -0
  141. package/dist/trace-ai/exp/exp-store/mission-md.js +37 -0
  142. package/dist/trace-ai/exp/exp-store/readme-template.d.ts +5 -0
  143. package/dist/trace-ai/exp/exp-store/readme-template.js +25 -0
  144. package/dist/trace-ai/exp/exp-store/round-yaml.d.ts +3 -0
  145. package/dist/trace-ai/exp/exp-store/round-yaml.js +33 -0
  146. package/dist/trace-ai/exp/index.d.ts +8 -0
  147. package/dist/trace-ai/exp/index.js +238 -0
  148. package/dist/trace-ai/exp/info.d.ts +35 -0
  149. package/dist/trace-ai/exp/info.js +120 -0
  150. package/dist/trace-ai/exp/patch/agent-config.d.ts +1 -0
  151. package/dist/trace-ai/exp/patch/agent-config.js +26 -0
  152. package/dist/trace-ai/exp/patch/index.d.ts +2 -0
  153. package/dist/trace-ai/exp/patch/index.js +13 -0
  154. package/dist/trace-ai/exp/patch/skill.d.ts +1 -0
  155. package/dist/trace-ai/exp/patch/skill.js +24 -0
  156. package/dist/trace-ai/exp/providers/synthesizer-client.d.ts +14 -0
  157. package/dist/trace-ai/exp/providers/synthesizer-client.js +39 -0
  158. package/dist/trace-ai/exp/providers/triage-client.d.ts +19 -0
  159. package/dist/trace-ai/exp/providers/triage-client.js +51 -0
  160. package/dist/trace-ai/exp/schemas.d.ts +147 -0
  161. package/dist/trace-ai/exp/schemas.js +50 -0
  162. package/dist/trace-ai/exp/scoring.d.ts +2 -0
  163. package/dist/trace-ai/exp/scoring.js +46 -0
  164. package/dist/trace-ai/scan/aggregator.d.ts +20 -0
  165. package/dist/trace-ai/scan/aggregator.js +26 -0
  166. package/dist/trace-ai/scan/artifacts/paths.d.ts +12 -0
  167. package/dist/trace-ai/scan/artifacts/paths.js +18 -0
  168. package/dist/trace-ai/scan/artifacts/writer.d.ts +67 -0
  169. package/dist/trace-ai/scan/artifacts/writer.js +96 -0
  170. package/dist/trace-ai/scan/batched-rubric.d.ts +55 -0
  171. package/dist/trace-ai/scan/batched-rubric.js +159 -0
  172. package/dist/trace-ai/scan/cross-trace-synthesizer.d.ts +24 -0
  173. package/dist/trace-ai/scan/cross-trace-synthesizer.js +93 -0
  174. package/dist/trace-ai/scan/index.d.ts +31 -0
  175. package/dist/trace-ai/scan/index.js +390 -0
  176. package/dist/trace-ai/scan/prompts/builtin/cross-trace-synthesizer-v1.prompt.md +44 -0
  177. package/dist/trace-ai/scan/prompts/builtin/rubric-judge-batch-v1.prompt.md +44 -0
  178. package/dist/trace-ai/scan/runner.d.ts +25 -0
  179. package/dist/trace-ai/scan/runner.js +42 -0
  180. package/dist/trace-ai/scan/sampler.d.ts +18 -0
  181. package/dist/trace-ai/scan/sampler.js +81 -0
  182. package/dist/trace-ai/scan/scan-summary-markdown.d.ts +2 -0
  183. package/dist/trace-ai/scan/scan-summary-markdown.js +71 -0
  184. package/dist/trace-ai/scan/scan-summary-schema.d.ts +73 -0
  185. package/dist/trace-ai/scan/scan-summary-schema.js +61 -0
  186. package/dist/trace-ai/scan/single-agent-validator.d.ts +23 -0
  187. package/dist/trace-ai/scan/single-agent-validator.js +42 -0
  188. package/dist/trace-ai/scan/traces-list-parser.d.ts +15 -0
  189. package/dist/trace-ai/scan/traces-list-parser.js +46 -0
  190. package/package.json +14 -4
@@ -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", "content");
108
- // Backend's gin form-binder rejects plain string field for `file`
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 registerSkillZip(options) {
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: "POST",
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
+ }
@@ -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] (compat HTTP)
144
- kweaver context-loader kn-schema-search <kn-id> <query> [--max N] (compat HTTP)
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, search, progressive read, download/install)
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
+ }