@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
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Single source of truth for `/api/agent-observability/v1/traces/_search` —
3
+ * the OpenSearch-style endpoint that backs both `kweaver agent trace` and
4
+ * `kweaver trace diagnose`.
5
+ *
6
+ * Owns: endpoint URL, auth/headers (via `./headers.ts`), the two-hop strategy
7
+ * (conversation_id → traceIds → spans), and HTTP error handling.
8
+ *
9
+ * Does NOT own normalization: callers receive raw OpenSearch `_source` objects
10
+ * and shape them as needed (TraceSpan for UI rendering, RawSpan for diagnose
11
+ * rules). This keeps the wire contract in one place while letting each consumer
12
+ * pick its own minimal field set.
13
+ */
14
+ export declare const TRACE_SEARCH_PATH = "/api/agent-observability/v1/traces/_search";
15
+ export declare class TraceFetchError extends Error {
16
+ readonly status?: number | undefined;
17
+ readonly url?: string | undefined;
18
+ constructor(message: string, status?: number | undefined, url?: string | undefined);
19
+ }
20
+ export interface FetchRawSpansByConversationOpts {
21
+ baseUrl: string;
22
+ accessToken: string;
23
+ businessDomain: string;
24
+ conversationId: string;
25
+ /** Cap on `terms` aggregation bucket count. Default 100. */
26
+ maxTraceIds?: number;
27
+ /** Cap on spans returned by the second query. Default 2000. */
28
+ maxSpans?: number;
29
+ }
30
+ export interface FetchRawSpansByConversationResult {
31
+ /** Distinct traceIds observed for this conversation, in agg-bucket order. */
32
+ traceIds: string[];
33
+ /** Raw `_source` objects, unmodified. Callers do their own normalization. */
34
+ rawSources: Array<Record<string, unknown>>;
35
+ /** True if the agg saw `sum_other_doc_count > 0` (more traceIds than maxTraceIds). */
36
+ truncated: boolean;
37
+ }
38
+ export declare function postTraceSearch(baseUrl: string, accessToken: string, businessDomain: string, body: unknown): Promise<Record<string, unknown>>;
39
+ /**
40
+ * Two-hop fetch of all `_source` documents belonging to a conversation.
41
+ *
42
+ * Hop 1: aggregate `traceId.keyword` for spans tagged with
43
+ * `attributes.gen_ai.conversation.id.keyword == conversationId`.
44
+ * Hop 2: fetch every span whose `traceId.keyword` is in the agg buckets.
45
+ *
46
+ * Fixture-compat fast path: when the first response carries no `aggregations`
47
+ * but does carry `hits.hits`, that is taken as a flat spans payload and hop 2
48
+ * is skipped. Existing e2e fixtures (single OpenSearch payload per file) thus
49
+ * remain usable with a single mock-fetch response.
50
+ */
51
+ export declare function fetchRawSpansByConversation(opts: FetchRawSpansByConversationOpts): Promise<FetchRawSpansByConversationResult>;
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Single source of truth for `/api/agent-observability/v1/traces/_search` —
3
+ * the OpenSearch-style endpoint that backs both `kweaver agent trace` and
4
+ * `kweaver trace diagnose`.
5
+ *
6
+ * Owns: endpoint URL, auth/headers (via `./headers.ts`), the two-hop strategy
7
+ * (conversation_id → traceIds → spans), and HTTP error handling.
8
+ *
9
+ * Does NOT own normalization: callers receive raw OpenSearch `_source` objects
10
+ * and shape them as needed (TraceSpan for UI rendering, RawSpan for diagnose
11
+ * rules). This keeps the wire contract in one place while letting each consumer
12
+ * pick its own minimal field set.
13
+ */
14
+ import { buildHeaders } from "./headers.js";
15
+ export const TRACE_SEARCH_PATH = "/api/agent-observability/v1/traces/_search";
16
+ export class TraceFetchError extends Error {
17
+ status;
18
+ url;
19
+ constructor(message, status, url) {
20
+ super(message);
21
+ this.status = status;
22
+ this.url = url;
23
+ this.name = "TraceFetchError";
24
+ }
25
+ }
26
+ export async function postTraceSearch(baseUrl, accessToken, businessDomain, body) {
27
+ const url = `${baseUrl.replace(/\/+$/, "")}${TRACE_SEARCH_PATH}`;
28
+ const res = await fetch(url, {
29
+ method: "POST",
30
+ headers: {
31
+ "Content-Type": "application/json",
32
+ ...buildHeaders(accessToken, businessDomain),
33
+ },
34
+ body: JSON.stringify(body),
35
+ });
36
+ const text = await res.text();
37
+ if (!res.ok) {
38
+ throw new TraceFetchError(`trace search failed: HTTP ${res.status} ${res.statusText} — ${text.slice(0, 200)}`, res.status, url);
39
+ }
40
+ if (!text)
41
+ return {};
42
+ try {
43
+ return JSON.parse(text);
44
+ }
45
+ catch (err) {
46
+ throw new TraceFetchError(`trace search: invalid JSON response — ${err.message}`);
47
+ }
48
+ }
49
+ /**
50
+ * Two-hop fetch of all `_source` documents belonging to a conversation.
51
+ *
52
+ * Hop 1: aggregate `traceId.keyword` for spans tagged with
53
+ * `attributes.gen_ai.conversation.id.keyword == conversationId`.
54
+ * Hop 2: fetch every span whose `traceId.keyword` is in the agg buckets.
55
+ *
56
+ * Fixture-compat fast path: when the first response carries no `aggregations`
57
+ * but does carry `hits.hits`, that is taken as a flat spans payload and hop 2
58
+ * is skipped. Existing e2e fixtures (single OpenSearch payload per file) thus
59
+ * remain usable with a single mock-fetch response.
60
+ */
61
+ export async function fetchRawSpansByConversation(opts) {
62
+ const { baseUrl, accessToken, businessDomain, conversationId } = opts;
63
+ const maxTraceIds = opts.maxTraceIds ?? 100;
64
+ const maxSpans = opts.maxSpans ?? 2000;
65
+ const aggResult = await postTraceSearch(baseUrl, accessToken, businessDomain, {
66
+ size: 0,
67
+ query: { term: { "attributes.gen_ai.conversation.id.keyword": conversationId } },
68
+ aggs: { tids: { terms: { field: "traceId.keyword", size: maxTraceIds } } },
69
+ });
70
+ const aggregations = aggResult.aggregations;
71
+ if (!aggregations) {
72
+ const directHits = aggResult.hits?.hits;
73
+ if (Array.isArray(directHits)) {
74
+ const rawSources = [];
75
+ const traceIds = new Set();
76
+ for (const h of directHits) {
77
+ if (!h._source)
78
+ continue;
79
+ rawSources.push(h._source);
80
+ const tid = h._source.traceId ?? h._source.trace_id;
81
+ if (typeof tid === "string" && tid.length > 0)
82
+ traceIds.add(tid);
83
+ }
84
+ return { traceIds: [...traceIds], rawSources, truncated: false };
85
+ }
86
+ }
87
+ const tids = aggregations?.tids;
88
+ const buckets = tids?.buckets ?? [];
89
+ const truncated = (tids?.sum_other_doc_count ?? 0) > 0;
90
+ const traceIds = buckets
91
+ .map((b) => b.key)
92
+ .filter((k) => typeof k === "string" && k.length > 0);
93
+ if (traceIds.length === 0) {
94
+ return { traceIds: [], rawSources: [], truncated: false };
95
+ }
96
+ const spansResult = await postTraceSearch(baseUrl, accessToken, businessDomain, {
97
+ size: maxSpans,
98
+ query: { terms: { "traceId.keyword": traceIds } },
99
+ sort: [{ startTime: "asc" }],
100
+ });
101
+ const hits = spansResult.hits?.hits ?? [];
102
+ const rawSources = [];
103
+ for (const h of hits) {
104
+ if (h._source)
105
+ rawSources.push(h._source);
106
+ }
107
+ return { traceIds, rawSources, truncated };
108
+ }
@@ -5,6 +5,7 @@ export interface ContextLoaderCallOptions {
5
5
  accessToken: string;
6
6
  }
7
7
  export interface SearchSchemaScope {
8
+ concept_groups?: string[];
8
9
  include_object_types?: boolean;
9
10
  include_relation_types?: boolean;
10
11
  include_action_types?: boolean;
@@ -61,14 +61,10 @@ export interface TracesByConversationResult {
61
61
  */
62
62
  export declare function listConversations(opts: ListConversationsOptions): Promise<string>;
63
63
  /**
64
- * Fetch all spans belonging to a conversation via trace-ai's OpenSearch-style _search.
65
- *
66
- * Two-hop strategy (see kweaver-sdk#115):
67
- * 1. Aggregate traceIds for spans tagged with gen_ai.conversation.id == conversationId.
68
- * 2. Fetch every span sharing those traceIds — this recovers pipeline spans
69
- * (HTTP entry, internal RPCs, prompt-build) that are not tagged with conversation_id.
70
- *
71
- * Returns a structured result; callers can format as tree/perf/evidence views or stringify.
64
+ * Fetch all spans belonging to a conversation, shaped as `TraceSpan[]` for UI
65
+ * rendering (tree/perf/evidence/reasoning views). The wire-level two-hop and
66
+ * auth/header concerns live in `./agent-observability`; this function only
67
+ * normalizes the raw `_source` documents.
72
68
  */
73
69
  export declare function getTracesByConversation(opts: GetTracesOptions): Promise<TracesByConversationResult>;
74
70
  /**
@@ -1,4 +1,5 @@
1
1
  import { buildHeaders } from "./headers.js";
2
+ import { fetchRawSpansByConversation } from "./agent-observability.js";
2
3
  function buildConversationsUrl(baseUrl, agentKey) {
3
4
  const base = baseUrl.replace(/\/+$/, "");
4
5
  return `${base}/api/agent-factory/v1/app/${agentKey}/conversation`;
@@ -29,32 +30,6 @@ export async function listConversations(opts) {
29
30
  }
30
31
  return body || "[]";
31
32
  }
32
- function buildTraceSearchUrl(baseUrl) {
33
- const base = baseUrl.replace(/\/+$/, "");
34
- return `${base}/api/agent-observability/v1/traces/_search`;
35
- }
36
- async function postTraceSearch(baseUrl, accessToken, businessDomain, body) {
37
- const response = await fetch(buildTraceSearchUrl(baseUrl), {
38
- method: "POST",
39
- headers: {
40
- "Content-Type": "application/json",
41
- ...buildHeaders(accessToken, businessDomain),
42
- },
43
- body: JSON.stringify(body),
44
- });
45
- const text = await response.text();
46
- if (!response.ok) {
47
- throw new Error(`getTracesByConversation failed: HTTP ${response.status} ${response.statusText} — ${text.slice(0, 200)}`);
48
- }
49
- if (!text)
50
- return {};
51
- try {
52
- return JSON.parse(text);
53
- }
54
- catch (err) {
55
- throw new Error(`getTracesByConversation: invalid JSON response — ${err.message}`);
56
- }
57
- }
58
33
  function computeDurationNanos(source) {
59
34
  if (typeof source.durationInNanos === "number")
60
35
  return source.durationInNanos;
@@ -113,45 +88,28 @@ function normalizeSpan(source) {
113
88
  };
114
89
  }
115
90
  /**
116
- * Fetch all spans belonging to a conversation via trace-ai's OpenSearch-style _search.
117
- *
118
- * Two-hop strategy (see kweaver-sdk#115):
119
- * 1. Aggregate traceIds for spans tagged with gen_ai.conversation.id == conversationId.
120
- * 2. Fetch every span sharing those traceIds — this recovers pipeline spans
121
- * (HTTP entry, internal RPCs, prompt-build) that are not tagged with conversation_id.
122
- *
123
- * Returns a structured result; callers can format as tree/perf/evidence views or stringify.
91
+ * Fetch all spans belonging to a conversation, shaped as `TraceSpan[]` for UI
92
+ * rendering (tree/perf/evidence/reasoning views). The wire-level two-hop and
93
+ * auth/header concerns live in `./agent-observability`; this function only
94
+ * normalizes the raw `_source` documents.
124
95
  */
125
96
  export async function getTracesByConversation(opts) {
126
- const { baseUrl, accessToken, conversationId, businessDomain = "bd_public", maxTraceIds = 100, maxSpans = 2000, } = opts;
127
- const aggResult = await postTraceSearch(baseUrl, accessToken, businessDomain, {
128
- size: 0,
129
- query: { term: { "attributes.gen_ai.conversation.id.keyword": conversationId } },
130
- aggs: { tids: { terms: { field: "traceId.keyword", size: maxTraceIds } } },
131
- });
132
- const aggregations = aggResult.aggregations;
133
- const tids = aggregations?.tids;
134
- const buckets = tids?.buckets ?? [];
135
- const truncated = (tids?.sum_other_doc_count ?? 0) > 0;
136
- const traceIds = buckets.map((b) => b.key).filter((k) => typeof k === "string" && k.length > 0);
137
- if (traceIds.length === 0) {
138
- return { conversationId, traceIds: [], spans: [], truncated: false };
139
- }
140
- const spansResult = await postTraceSearch(baseUrl, accessToken, businessDomain, {
141
- size: maxSpans,
142
- query: { terms: { "traceId.keyword": traceIds } },
143
- sort: [{ startTime: "asc" }],
97
+ const { baseUrl, accessToken, conversationId, businessDomain = "bd_public", maxTraceIds, maxSpans, } = opts;
98
+ const fetched = await fetchRawSpansByConversation({
99
+ baseUrl,
100
+ accessToken,
101
+ businessDomain,
102
+ conversationId,
103
+ maxTraceIds,
104
+ maxSpans,
144
105
  });
145
- const hits = spansResult.hits?.hits ?? [];
146
106
  const spans = [];
147
- for (const hit of hits) {
148
- if (!hit._source)
149
- continue;
150
- const span = normalizeSpan(hit._source);
107
+ for (const src of fetched.rawSources) {
108
+ const span = normalizeSpan(src);
151
109
  if (span)
152
110
  spans.push(span);
153
111
  }
154
- return { conversationId, traceIds, spans, truncated };
112
+ return { conversationId, traceIds: fetched.traceIds, spans, truncated: fetched.truncated };
155
113
  }
156
114
  /**
157
115
  * List messages for a conversation.
@@ -58,23 +58,5 @@ export interface ListTablesOptions {
58
58
  businessDomain?: string;
59
59
  }
60
60
  export declare function listTables(options: ListTablesOptions): Promise<string>;
61
- export interface ListTablesWithColumnsOptions extends ListTablesOptions {
62
- autoScan?: boolean;
63
- }
64
- /** List tables with column details. Optionally triggers metadata scan if no tables found. */
65
- export declare function listTablesWithColumns(options: ListTablesWithColumnsOptions): Promise<string>;
66
- export interface ScanMetadataOptions {
67
- baseUrl: string;
68
- accessToken: string;
69
- id: string;
70
- dsType?: string;
71
- businessDomain?: string;
72
- }
73
- export declare function scanMetadata(options: ScanMetadataOptions): Promise<string>;
74
- export interface ScanDatasourceMetadataOptions {
75
- baseUrl: string;
76
- accessToken: string;
77
- id: string;
78
- businessDomain?: string;
79
- }
80
- export declare function scanDatasourceMetadata(options: ScanDatasourceMetadataOptions): Promise<string>;
61
+ export { listTablesWithColumns, scanMetadata, scanDatasourceMetadata, } from "./vega.js";
62
+ export type { ListTablesWithColumnsOptions, ScanMetadataOptions, ScanDatasourceMetadataOptions, } from "./vega.js";
@@ -130,126 +130,10 @@ export async function listTables(options) {
130
130
  }
131
131
  return body;
132
132
  }
133
- /** List tables with column details. Optionally triggers metadata scan if no tables found. */
134
- export async function listTablesWithColumns(options) {
135
- const { id, autoScan = true, ...rest } = options;
136
- let body = await listTables({ ...rest, id });
137
- const parsed = JSON.parse(body);
138
- let items = Array.isArray(parsed) ? parsed : (parsed.entries ?? parsed.data ?? []);
139
- if (items.length === 0 && autoScan) {
140
- await scanMetadata({
141
- baseUrl: rest.baseUrl,
142
- accessToken: rest.accessToken,
143
- id,
144
- businessDomain: rest.businessDomain,
145
- });
146
- body = await listTables({ ...rest, id });
147
- const parsed2 = JSON.parse(body);
148
- items = Array.isArray(parsed2) ? parsed2 : (parsed2.entries ?? parsed2.data ?? []);
149
- }
150
- const base = rest.baseUrl.replace(/\/+$/, "");
151
- const tables = [];
152
- for (const t of items) {
153
- const tableId = String(t.id ?? "");
154
- const tableName = String(t.name ?? "");
155
- let columnsRaw = (t.columns ?? t.fields ?? []);
156
- if (columnsRaw.length === 0 && tableId) {
157
- const tableUrl = `${base}/api/data-connection/v1/metadata/table/${encodeURIComponent(tableId)}?limit=-1`;
158
- const colResponse = await fetch(tableUrl, {
159
- method: "GET",
160
- headers: buildHeaders(rest.accessToken, rest.businessDomain ?? "bd_public"),
161
- });
162
- const colData = (await colResponse.json());
163
- columnsRaw = Array.isArray(colData) ? colData : (colData.entries ?? colData.data ?? []);
164
- }
165
- const tablePkArray = extractPrimaryKeys(t);
166
- const columns = columnsRaw.map((c) => {
167
- const name = String(c.name ?? c.field_name ?? "");
168
- const flagged = isColumnPrimaryKey(c) || tablePkArray.includes(name);
169
- return {
170
- name,
171
- type: String(c.type ?? c.field_type ?? "varchar"),
172
- comment: typeof c.comment === "string" ? c.comment : undefined,
173
- ...(flagged ? { isPrimaryKey: true } : {}),
174
- };
175
- });
176
- // Reconcile: if backend gave per-column flags but no table-level array,
177
- // synthesize one so downstream callers have a single PK source of truth.
178
- const synthesizedPks = tablePkArray.length > 0
179
- ? tablePkArray
180
- : columns.filter((c) => c.isPrimaryKey).map((c) => c.name);
181
- tables.push({
182
- name: tableName,
183
- columns,
184
- ...(synthesizedPks.length > 0 ? { primaryKeys: synthesizedPks } : {}),
185
- });
186
- }
187
- return JSON.stringify(tables);
188
- }
189
- // Two PK metadata shapes are recognized — both confirmed conventions:
190
- // - per-column `is_primary_key: true` (data-connection metadata standard)
191
- // - per-column `column_key === "PRI"` (MySQL INFORMATION_SCHEMA pass-through)
192
- // - table-level `primary_keys: string[]` (composite-PK carrier)
193
- // Other plausible spellings (camelCase, singular keys, SQLite `pk` integer) are
194
- // intentionally NOT recognized here — adding them speculatively risks false
195
- // matches and creates code paths the test suite can't pin down. Extend only when
196
- // a real backend response demonstrates the need.
197
- function isColumnPrimaryKey(col) {
198
- if (col.is_primary_key === true)
199
- return true;
200
- if (typeof col.column_key === "string" && col.column_key.toUpperCase() === "PRI")
201
- return true;
202
- return false;
203
- }
204
- function extractPrimaryKeys(table) {
205
- const arr = table.primary_keys;
206
- if (Array.isArray(arr)) {
207
- return arr.filter((x) => typeof x === "string");
208
- }
209
- return [];
210
- }
211
- export async function scanMetadata(options) {
212
- const { baseUrl, accessToken, id, dsType = "mysql", businessDomain = "bd_public", } = options;
213
- const base = baseUrl.replace(/\/+$/, "");
214
- const scanUrl = `${base}/api/data-connection/v1/metadata/scan`;
215
- const statusUrl = (taskId) => `${base}/api/data-connection/v1/metadata/scan/${taskId}`;
216
- const scanBody = JSON.stringify({
217
- scan_name: `sdk_scan_${id.slice(0, 8)}`,
218
- type: 0,
219
- ds_info: { ds_id: id, ds_type: dsType },
220
- use_default_template: true,
221
- use_multi_threads: true,
222
- status: "open",
223
- });
224
- const scanResponse = await fetch(scanUrl, {
225
- method: "POST",
226
- headers: {
227
- ...buildHeaders(accessToken, businessDomain),
228
- "content-type": "application/json",
229
- },
230
- body: scanBody,
231
- });
232
- const scanResult = await scanResponse.json();
233
- const taskId = scanResult.id ?? "";
234
- for (let i = 0; i < 30; i += 1) {
235
- const delay = Math.min(2000 * Math.pow(1.5, i), 15000);
236
- await new Promise((r) => setTimeout(r, delay));
237
- const statusResponse = await fetch(statusUrl(taskId), {
238
- method: "GET",
239
- headers: buildHeaders(accessToken, businessDomain),
240
- });
241
- const statusData = (await statusResponse.json());
242
- if (statusData.status === "success" || statusData.status === "fail") {
243
- break;
244
- }
245
- }
246
- return taskId;
247
- }
248
- // Looks up a datasource's type then triggers a metadata scan, so callers
249
- // don't have to repeat the GET-then-scan dance whenever a flow needs the
250
- // platform catalog refreshed (after import-csv, before discovering tables).
251
- export async function scanDatasourceMetadata(options) {
252
- const dsBody = await getDatasource(options);
253
- const dsType = JSON.parse(dsBody).type ?? "mysql";
254
- return scanMetadata({ ...options, dsType });
255
- }
133
+ // ── Vega catalog re-exports (backward compatibility) ─────────────────────────
134
+ //
135
+ // listTablesWithColumns, scanMetadata, and scanDatasourceMetadata now live in
136
+ // vega.ts (they talk exclusively to vega-backend, not data-connection).
137
+ // Re-exported here so existing callers don't break — new code should import
138
+ // from "../api/vega.js" directly.
139
+ export { listTablesWithColumns, scanMetadata, scanDatasourceMetadata, } from "./vega.js";
@@ -18,4 +18,9 @@ export interface KnSearchHttpOptions {
18
18
  businessDomain?: string;
19
19
  onlySchema?: boolean;
20
20
  }
21
+ /**
22
+ * @deprecated Use Context Loader `search_schema` for new schema discovery integrations.
23
+ * The HTTP `kn_search` endpoint is kept only as a compatibility entry point
24
+ * and may not receive new `search_schema` capabilities.
25
+ */
21
26
  export declare function knSearchHttp(options: KnSearchHttpOptions): Promise<string>;
@@ -22,6 +22,11 @@ export async function semanticSearch(options) {
22
22
  }
23
23
  return body;
24
24
  }
25
+ /**
26
+ * @deprecated Use Context Loader `search_schema` for new schema discovery integrations.
27
+ * The HTTP `kn_search` endpoint is kept only as a compatibility entry point
28
+ * and may not receive new `search_schema` capabilities.
29
+ */
25
30
  export async function knSearchHttp(options) {
26
31
  const { baseUrl, accessToken, knId, query, businessDomain = "bd_public", onlySchema = false, } = options;
27
32
  const base = baseUrl.replace(/\/+$/, "");
@@ -1,11 +1,13 @@
1
1
  export type SkillStatus = "unpublish" | "published" | "offline";
2
2
  export type SkillFileType = "zip" | "content";
3
+ export type SkillEditableStatus = SkillStatus | "editing";
4
+ export type SkillCategory = "other_category" | "system";
3
5
  export interface SkillSummary {
4
6
  id: string;
5
7
  name: string;
6
8
  description?: string;
7
9
  version?: string;
8
- status?: SkillStatus;
10
+ status?: SkillEditableStatus;
9
11
  source?: string;
10
12
  create_user?: string;
11
13
  create_time?: number;
@@ -29,7 +31,7 @@ export interface SkillContentIndex {
29
31
  id: string;
30
32
  url: string;
31
33
  files: SkillFileSummary[];
32
- status?: SkillStatus;
34
+ status?: SkillEditableStatus;
33
35
  }
34
36
  export interface SkillFileReadResult {
35
37
  id: string;
@@ -54,6 +56,22 @@ export interface UpdateSkillStatusResult {
54
56
  id: string;
55
57
  status: SkillStatus;
56
58
  }
59
+ export interface UpdateSkillMetadataResult {
60
+ id: string;
61
+ version?: string;
62
+ status?: SkillEditableStatus;
63
+ }
64
+ export interface UpdateSkillPackageResult {
65
+ id: string;
66
+ version?: string;
67
+ status?: SkillEditableStatus;
68
+ }
69
+ export interface SkillReleaseHistoryInfo extends SkillSummary {
70
+ category?: SkillCategory;
71
+ release_desc?: string;
72
+ release_user?: string;
73
+ release_time?: number;
74
+ }
57
75
  export interface SkillListResult {
58
76
  total_count?: number;
59
77
  total?: number;
@@ -104,6 +122,23 @@ export interface RegisterSkillZipOptions extends SkillApiBaseOptions {
104
122
  source?: string;
105
123
  extendInfo?: Record<string, unknown>;
106
124
  }
125
+ export interface UpdateSkillMetadataOptions extends SkillApiBaseOptions {
126
+ skillId: string;
127
+ name: string;
128
+ description: string;
129
+ category: SkillCategory;
130
+ source?: string;
131
+ extendInfo?: Record<string, unknown>;
132
+ }
133
+ export interface UpdateSkillPackageContentOptions extends SkillApiBaseOptions {
134
+ skillId: string;
135
+ content: string;
136
+ }
137
+ export interface UpdateSkillPackageZipOptions extends SkillApiBaseOptions {
138
+ skillId: string;
139
+ filename: string;
140
+ bytes: Uint8Array;
141
+ }
107
142
  export interface UpdateSkillStatusOptions extends SkillApiBaseOptions {
108
143
  skillId: string;
109
144
  status: SkillStatus;
@@ -119,23 +154,61 @@ export interface DownloadedSkillArchive {
119
154
  fileName: string;
120
155
  bytes: Uint8Array;
121
156
  }
157
+ export interface SkillHistoryVersionOptions extends SkillApiBaseOptions {
158
+ skillId: string;
159
+ version: string;
160
+ }
122
161
  export interface InstallSkillArchiveOptions {
123
162
  bytes: Uint8Array;
124
163
  directory: string;
125
164
  force?: boolean;
126
165
  }
166
+ export interface SkillManagementContentData {
167
+ skill_id: string;
168
+ name: string;
169
+ description: string;
170
+ version: string;
171
+ status: SkillEditableStatus;
172
+ source: string;
173
+ file_type: "zip" | "content";
174
+ url?: string;
175
+ content?: string;
176
+ files: SkillFileSummary[];
177
+ }
178
+ export interface GetSkillManagementContentOptions extends SkillApiBaseOptions {
179
+ skillId: string;
180
+ responseMode?: "url" | "content";
181
+ }
182
+ export interface ReadSkillManagementFileOptions extends SkillApiBaseOptions {
183
+ skillId: string;
184
+ relPath: string;
185
+ }
186
+ export interface DownloadSkillManagementOptions extends SkillApiBaseOptions {
187
+ skillId: string;
188
+ responseMode?: "url" | "content";
189
+ }
127
190
  export declare function listSkills(options: ListSkillsOptions): Promise<SkillListResult>;
128
191
  export declare function listSkillMarket(options: ListSkillMarketOptions): Promise<SkillListResult>;
129
192
  export declare function getSkill(options: GetSkillOptions): Promise<SkillInfo>;
193
+ export declare function getSkillMarketDetail(options: GetSkillOptions): Promise<SkillInfo>;
130
194
  export declare function deleteSkill(options: GetSkillOptions): Promise<DeleteSkillResult>;
131
195
  export declare function updateSkillStatus(options: UpdateSkillStatusOptions): Promise<UpdateSkillStatusResult>;
196
+ export declare function updateSkillMetadata(options: UpdateSkillMetadataOptions): Promise<UpdateSkillMetadataResult>;
132
197
  export declare function registerSkillContent(options: RegisterSkillContentOptions): Promise<RegisterSkillResult>;
133
198
  export declare function registerSkillZip(options: RegisterSkillZipOptions): Promise<RegisterSkillResult>;
199
+ export declare function updateSkillPackageContent(options: UpdateSkillPackageContentOptions): Promise<UpdateSkillPackageResult>;
200
+ export declare function updateSkillPackageZip(options: UpdateSkillPackageZipOptions): Promise<UpdateSkillPackageResult>;
134
201
  export declare function getSkillContentIndex(options: GetSkillOptions): Promise<SkillContentIndex>;
135
202
  export declare function fetchSkillContent(options: GetSkillOptions): Promise<string>;
136
203
  export declare function readSkillFile(options: ReadSkillFileOptions): Promise<SkillFileReadResult>;
137
204
  export declare function fetchSkillFile(options: ReadSkillFileOptions): Promise<Uint8Array>;
138
205
  export declare function downloadSkill(options: DownloadSkillOptions): Promise<DownloadedSkillArchive>;
206
+ export declare function listSkillHistory(options: GetSkillOptions): Promise<SkillReleaseHistoryInfo[]>;
207
+ export declare function republishSkillHistory(options: SkillHistoryVersionOptions): Promise<UpdateSkillPackageResult>;
208
+ export declare function publishSkillHistory(options: SkillHistoryVersionOptions): Promise<UpdateSkillPackageResult>;
209
+ export declare function getSkillManagementContent(options: GetSkillManagementContentOptions): Promise<SkillManagementContentData>;
210
+ export declare function readSkillManagementFile(options: ReadSkillManagementFileOptions): Promise<SkillFileReadResult>;
211
+ export declare function downloadSkillManagementArchive(options: DownloadSkillManagementOptions): Promise<DownloadedSkillArchive>;
139
212
  export declare function installSkillArchive(options: InstallSkillArchiveOptions): {
140
213
  directory: string;
141
214
  };