@tiangong-ai/cli 0.0.13 → 0.0.15

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 (63) hide show
  1. package/AGENTS.md +4 -2
  2. package/README.md +59 -2
  3. package/dist/args.d.ts +13 -0
  4. package/dist/args.js +72 -0
  5. package/dist/args.js.map +1 -0
  6. package/dist/cli.d.ts +5 -21
  7. package/dist/cli.js +27 -445
  8. package/dist/cli.js.map +1 -1
  9. package/dist/data.d.ts +3 -0
  10. package/dist/data.js +16 -0
  11. package/dist/data.js.map +1 -0
  12. package/dist/edge-search.d.ts +54 -0
  13. package/dist/edge-search.js +108 -0
  14. package/dist/edge-search.js.map +1 -0
  15. package/dist/education/commands.d.ts +2 -0
  16. package/dist/education/commands.js +144 -0
  17. package/dist/education/commands.js.map +1 -0
  18. package/dist/education/config.d.ts +24 -0
  19. package/dist/education/config.js +127 -0
  20. package/dist/education/config.js.map +1 -0
  21. package/dist/education/types.d.ts +1 -0
  22. package/dist/education/types.js +2 -0
  23. package/dist/education/types.js.map +1 -0
  24. package/dist/env.d.ts +2 -0
  25. package/dist/env.js +42 -0
  26. package/dist/env.js.map +1 -0
  27. package/dist/errors.d.ts +24 -0
  28. package/dist/errors.js +53 -0
  29. package/dist/errors.js.map +1 -0
  30. package/dist/http.d.ts +28 -0
  31. package/dist/http.js +80 -0
  32. package/dist/http.js.map +1 -0
  33. package/dist/io.d.ts +11 -0
  34. package/dist/io.js +33 -0
  35. package/dist/io.js.map +1 -0
  36. package/dist/kb/client.d.ts +19 -0
  37. package/dist/kb/client.js +71 -0
  38. package/dist/kb/client.js.map +1 -0
  39. package/dist/kb/config.d.ts +12 -0
  40. package/dist/kb/config.js +26 -0
  41. package/dist/kb/config.js.map +1 -0
  42. package/dist/kb/pipeline-health.d.ts +10 -0
  43. package/dist/kb/pipeline-health.js +68 -0
  44. package/dist/kb/pipeline-health.js.map +1 -0
  45. package/dist/kb/selector.d.ts +3 -0
  46. package/dist/kb/selector.js +40 -0
  47. package/dist/kb/selector.js.map +1 -0
  48. package/dist/kb/status.d.ts +19 -0
  49. package/dist/kb/status.js +74 -0
  50. package/dist/kb/status.js.map +1 -0
  51. package/dist/research/commands.d.ts +2 -0
  52. package/dist/research/commands.js +147 -0
  53. package/dist/research/commands.js.map +1 -0
  54. package/dist/research/config.d.ts +23 -0
  55. package/dist/research/config.js +120 -0
  56. package/dist/research/config.js.map +1 -0
  57. package/dist/research/types.d.ts +1 -0
  58. package/dist/research/types.js +2 -0
  59. package/dist/research/types.js.map +1 -0
  60. package/dist/strict-args.d.ts +8 -0
  61. package/dist/strict-args.js +63 -0
  62. package/dist/strict-args.js.map +1 -0
  63. package/package.json +2 -2
package/dist/http.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ export type ResponseLike = {
2
+ ok: boolean;
3
+ status: number;
4
+ headers: {
5
+ get(name: string): string | null;
6
+ };
7
+ text(): Promise<string>;
8
+ };
9
+ export type FetchLike = (input: string, init?: RequestInit) => Promise<ResponseLike>;
10
+ export interface HttpJsonConfig {
11
+ apiBaseUrl: string;
12
+ apiPathPrefix: string;
13
+ apiKey: string;
14
+ timeoutSeconds: number;
15
+ }
16
+ export declare function jsonRequest(config: HttpJsonConfig, path: string, init?: RequestInit & {
17
+ headers?: Record<string, string>;
18
+ }): Promise<unknown>;
19
+ export declare function jsonRequestUrl(url: string, init?: RequestInit & {
20
+ headers?: HeadersInit;
21
+ }, timeoutSeconds?: number): Promise<unknown>;
22
+ export declare function postJson(options: {
23
+ url: string;
24
+ headers: Record<string, string>;
25
+ body: unknown;
26
+ timeoutMs: number;
27
+ fetchImpl: FetchLike;
28
+ }): Promise<unknown>;
package/dist/http.js ADDED
@@ -0,0 +1,80 @@
1
+ import { CliError, HttpError } from "./errors.js";
2
+ const RETRYABLE_HTTP_STATUSES = new Set([408, 425, 429, 500, 502, 503, 504]);
3
+ export async function jsonRequest(config, path, init = {}) {
4
+ const url = `${config.apiBaseUrl}${config.apiPathPrefix}/${path.replace(/^\/+/, "")}`;
5
+ const headers = new Headers(init.headers);
6
+ headers.set("Authorization", `Bearer ${config.apiKey}`);
7
+ return jsonRequestUrl(url, { ...init, headers }, config.timeoutSeconds);
8
+ }
9
+ export async function jsonRequestUrl(url, init = {}, timeoutSeconds = 120) {
10
+ const headers = new Headers(init.headers);
11
+ headers.set("Accept", "application/json");
12
+ if (init.body && !(init.body instanceof FormData)) {
13
+ headers.set("Content-Type", "application/json");
14
+ }
15
+ let response;
16
+ try {
17
+ response = await fetch(url, {
18
+ ...init,
19
+ headers,
20
+ signal: AbortSignal.timeout(timeoutSeconds * 1000),
21
+ });
22
+ }
23
+ catch (error) {
24
+ throw new HttpError(`Request failed for ${url}: ${error instanceof Error ? error.message : String(error)}`, undefined, undefined, true);
25
+ }
26
+ const text = await response.text();
27
+ if (!response.ok) {
28
+ throw new HttpError(`HTTP ${response.status} from ${url}: ${text}`, response.status, retryAfterSeconds(response.headers), RETRYABLE_HTTP_STATUSES.has(response.status));
29
+ }
30
+ if (!text.trim())
31
+ return {};
32
+ try {
33
+ return JSON.parse(text);
34
+ }
35
+ catch {
36
+ throw new CliError(`Expected JSON from ${url}, got: ${text.slice(0, 200)}`);
37
+ }
38
+ }
39
+ async function parseResponse(response, url) {
40
+ const rawText = await response.text();
41
+ const contentType = response.headers.get("content-type") ?? "";
42
+ if (!response.ok) {
43
+ throw new CliError(`HTTP ${response.status} returned from ${url}`, {
44
+ code: "REMOTE_REQUEST_FAILED",
45
+ exitCode: 1,
46
+ details: rawText,
47
+ });
48
+ }
49
+ if (contentType.includes("application/json")) {
50
+ try {
51
+ return JSON.parse(rawText);
52
+ }
53
+ catch (error) {
54
+ throw new CliError(`Remote response was not valid JSON for ${url}`, {
55
+ code: "REMOTE_INVALID_JSON",
56
+ exitCode: 1,
57
+ details: String(error),
58
+ });
59
+ }
60
+ }
61
+ return rawText;
62
+ }
63
+ export async function postJson(options) {
64
+ const signal = AbortSignal.timeout(options.timeoutMs);
65
+ const response = await options.fetchImpl(options.url, {
66
+ method: "POST",
67
+ headers: options.headers,
68
+ body: JSON.stringify(options.body),
69
+ signal,
70
+ });
71
+ return parseResponse(response, options.url);
72
+ }
73
+ function retryAfterSeconds(headers) {
74
+ const value = headers.get("Retry-After");
75
+ if (!value)
76
+ return undefined;
77
+ const parsed = Number(value);
78
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
79
+ }
80
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/io.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ export interface Output {
2
+ write(text: string): unknown;
3
+ }
4
+ export interface CliIO {
5
+ env: NodeJS.ProcessEnv;
6
+ stdout: Output;
7
+ stderr: Output;
8
+ }
9
+ export declare function write(output: Output, text: string): void;
10
+ export declare function readJsonInput(inputPath: string): unknown;
11
+ export declare function stringifyJson(value: unknown, compact: boolean): string;
package/dist/io.js ADDED
@@ -0,0 +1,33 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { CliError } from "./errors.js";
3
+ export function write(output, text) {
4
+ output.write(text);
5
+ }
6
+ export function readJsonInput(inputPath) {
7
+ if (!inputPath) {
8
+ throw new CliError("Missing required --input value.", {
9
+ code: "INPUT_REQUIRED",
10
+ exitCode: 2,
11
+ });
12
+ }
13
+ if (!existsSync(inputPath)) {
14
+ throw new CliError(`Input file not found: ${inputPath}`, {
15
+ code: "INPUT_NOT_FOUND",
16
+ exitCode: 2,
17
+ });
18
+ }
19
+ try {
20
+ return JSON.parse(readFileSync(inputPath, "utf8"));
21
+ }
22
+ catch (error) {
23
+ throw new CliError(`Input file is not valid JSON: ${inputPath}`, {
24
+ code: "INPUT_INVALID_JSON",
25
+ exitCode: 2,
26
+ details: String(error),
27
+ });
28
+ }
29
+ }
30
+ export function stringifyJson(value, compact) {
31
+ return `${JSON.stringify(value, null, compact ? undefined : 2)}\n`;
32
+ }
33
+ //# sourceMappingURL=io.js.map
package/dist/io.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"io.js","sourceRoot":"","sources":["../src/io.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAYvC,MAAM,UAAU,KAAK,CAAC,MAAc,EAAE,IAAY;IAChD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,QAAQ,CAAC,iCAAiC,EAAE;YACpD,IAAI,EAAE,gBAAgB;YACtB,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,QAAQ,CAAC,yBAAyB,SAAS,EAAE,EAAE;YACvD,IAAI,EAAE,iBAAiB;YACvB,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAY,CAAC;IAChE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,QAAQ,CAAC,iCAAiC,SAAS,EAAE,EAAE;YAC/D,IAAI,EAAE,oBAAoB;YAC1B,QAAQ,EAAE,CAAC;YACX,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC;SACvB,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,OAAgB;IAC5D,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACrE,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { KbConfig } from "./config.js";
2
+ export interface CollectionSelector {
3
+ field: "primary_collection_id" | "collection_path" | "collection_key" | "collection_name";
4
+ value: string;
5
+ }
6
+ export interface CollectionItem {
7
+ id?: string;
8
+ key?: string;
9
+ path?: string;
10
+ name?: string;
11
+ [key: string]: unknown;
12
+ }
13
+ export declare function resolveCollection(config: KbConfig, selector: CollectionSelector, options: {
14
+ includeSchema: boolean;
15
+ }): Promise<unknown>;
16
+ export declare function resolveSelectorFields(config: KbConfig, selector: CollectionSelector): Promise<Record<string, string>>;
17
+ export declare function listCollections(config: KbConfig, capability: string, limit: number): Promise<CollectionItem[]>;
18
+ export declare function collectionKey(item: CollectionItem): string | undefined;
19
+ export declare function collectionPath(item: CollectionItem): string | undefined;
@@ -0,0 +1,71 @@
1
+ import { isObject, responseData, stringField } from "../data.js";
2
+ import { CliError } from "../errors.js";
3
+ import { jsonRequest } from "../http.js";
4
+ export async function resolveCollection(config, selector, options) {
5
+ const params = new URLSearchParams({ action: "upload" });
6
+ params.set(selector.field, selector.value);
7
+ if (options.includeSchema)
8
+ params.set("include_schema", "true");
9
+ return jsonRequest(config, `collections/resolve?${params.toString()}`);
10
+ }
11
+ export async function resolveSelectorFields(config, selector) {
12
+ if (selector.field !== "collection_name") {
13
+ return { [selector.field]: selector.value };
14
+ }
15
+ const matches = (await listCollections(config, "upload", 100)).filter((item) => item.name === selector.value);
16
+ if (matches.length === 0)
17
+ throw new CliError(`No uploadable collection matched name: ${selector.value}`);
18
+ if (matches.length > 1) {
19
+ const choices = matches.map((item) => item.key ?? item.path ?? item.id ?? "").join(", ");
20
+ throw new CliError(`Collection name is not unique: ${selector.value}. Use --collection-key or --collection-path. Matches: ${choices}`);
21
+ }
22
+ const match = matches[0];
23
+ const key = collectionKey(match);
24
+ if (key)
25
+ return { collection_key: key };
26
+ const path = collectionPath(match);
27
+ if (path)
28
+ return { collection_path: path };
29
+ if (typeof match.id === "string" && match.id)
30
+ return { primary_collection_id: match.id };
31
+ throw new CliError(`Collection matched name ${selector.value}, but response had no key, path, or id.`);
32
+ }
33
+ export async function listCollections(config, capability, limit) {
34
+ const collections = [];
35
+ let offset = 0;
36
+ while (true) {
37
+ const payload = await jsonRequest(config, `collections?${new URLSearchParams({
38
+ capability,
39
+ limit: String(limit),
40
+ offset: String(offset),
41
+ }).toString()}`);
42
+ const page = collectionItems(payload);
43
+ collections.push(...page);
44
+ if (page.length < limit)
45
+ return collections;
46
+ offset += limit;
47
+ }
48
+ }
49
+ export function collectionKey(item) {
50
+ return (stringField(item, "key") ??
51
+ stringField(item, "collectionKey") ??
52
+ stringField(item, "collection_key"));
53
+ }
54
+ export function collectionPath(item) {
55
+ return (stringField(item, "path") ??
56
+ stringField(item, "collectionPath") ??
57
+ stringField(item, "collection_path"));
58
+ }
59
+ function collectionItems(payload) {
60
+ const data = responseData(payload);
61
+ if (Array.isArray(data))
62
+ return data.filter(isObject);
63
+ if (isObject(data) && Array.isArray(data.collections))
64
+ return data.collections.filter(isObject);
65
+ if (isObject(data) && Array.isArray(data.data))
66
+ return data.data.filter(isObject);
67
+ if (isObject(payload) && Array.isArray(payload.data))
68
+ return payload.data.filter(isObject);
69
+ throw new CliError("Collection list response did not contain a data array.");
70
+ }
71
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/kb/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { type ParsedArgs } from "../args.js";
2
+ export declare const DEFAULT_API_BASE_URL = "https://thuenv.tiangong.world:7300";
3
+ export declare const DEFAULT_API_PATH_PREFIX = "/api/v1/kb";
4
+ export interface KbConfig {
5
+ apiBaseUrl: string;
6
+ apiPathPrefix: string;
7
+ apiKey: string;
8
+ timeoutSeconds: number;
9
+ }
10
+ export declare function resolveKbConfig(args: ParsedArgs, env: NodeJS.ProcessEnv, options?: {
11
+ requireKey?: boolean;
12
+ }): KbConfig;
@@ -0,0 +1,26 @@
1
+ import { getString, positiveNumberValue } from "../args.js";
2
+ import { firstEnv } from "../env.js";
3
+ import { CliError } from "../errors.js";
4
+ export const DEFAULT_API_BASE_URL = "https://thuenv.tiangong.world:7300";
5
+ export const DEFAULT_API_PATH_PREFIX = "/api/v1/kb";
6
+ export function resolveKbConfig(args, env, options = {}) {
7
+ const requireKey = options.requireKey ?? true;
8
+ const apiKey = getString(args, "api-key") ?? firstEnv(env, "TIANGONG_AI_API_KEY", "TIANGONG_KB_API_KEY") ?? "";
9
+ if (requireKey && !apiKey) {
10
+ throw new CliError("Missing API key. Provide --api-key or set TIANGONG_AI_API_KEY.");
11
+ }
12
+ return {
13
+ apiBaseUrl: (getString(args, "api-base-url") ??
14
+ firstEnv(env, "TIANGONG_KB_API_BASE_URL") ??
15
+ DEFAULT_API_BASE_URL).replace(/\/+$/, ""),
16
+ apiPathPrefix: normalizePrefix(getString(args, "api-path-prefix") ??
17
+ firstEnv(env, "TIANGONG_KB_API_PATH_PREFIX") ??
18
+ DEFAULT_API_PATH_PREFIX),
19
+ apiKey,
20
+ timeoutSeconds: positiveNumberValue(getString(args, "timeout") ?? firstEnv(env, "TIANGONG_KB_TIMEOUT"), 120, "--timeout"),
21
+ };
22
+ }
23
+ function normalizePrefix(value) {
24
+ return `/${value.replace(/^\/+|\/+$/g, "")}`;
25
+ }
26
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/kb/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAmB,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,CAAC,MAAM,oBAAoB,GAAG,oCAAoC,CAAC;AACzE,MAAM,CAAC,MAAM,uBAAuB,GAAG,YAAY,CAAC;AASpD,MAAM,UAAU,eAAe,CAC7B,IAAgB,EAChB,GAAsB,EACtB,UAAoC,EAAE;IAEtC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;IAC9C,MAAM,MAAM,GACV,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,qBAAqB,EAAE,qBAAqB,CAAC,IAAI,EAAE,CAAC;IAClG,IAAI,UAAU,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,QAAQ,CAAC,gEAAgE,CAAC,CAAC;IACvF,CAAC;IAED,OAAO;QACL,UAAU,EAAE,CACV,SAAS,CAAC,IAAI,EAAE,cAAc,CAAC;YAC/B,QAAQ,CAAC,GAAG,EAAE,0BAA0B,CAAC;YACzC,oBAAoB,CACrB,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACrB,aAAa,EAAE,eAAe,CAC5B,SAAS,CAAC,IAAI,EAAE,iBAAiB,CAAC;YAChC,QAAQ,CAAC,GAAG,EAAE,6BAA6B,CAAC;YAC5C,uBAAuB,CAC1B;QACD,MAAM;QACN,cAAc,EAAE,mBAAmB,CACjC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,qBAAqB,CAAC,EAClE,GAAG,EACH,WAAW,CACZ;KACF,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { KbConfig } from "./config.js";
2
+ export interface BulkPipelineHealthSnapshot {
3
+ healthy: boolean;
4
+ pressure: "ok" | "degraded" | "paused" | "unknown";
5
+ recommendedAction: "continue" | "slow_down" | "pause_top_up";
6
+ recommendedPollAfterSeconds: number;
7
+ checkedAt?: string | undefined;
8
+ message?: string | undefined;
9
+ }
10
+ export declare function readBulkPipelineHealth(config: KbConfig, fallbackPollAfterSeconds: number, selectorFields?: Record<string, string>): Promise<BulkPipelineHealthSnapshot>;
@@ -0,0 +1,68 @@
1
+ import { isObject, responseData, stringField } from "../data.js";
2
+ import { CliError, HttpError } from "../errors.js";
3
+ import { jsonRequest } from "../http.js";
4
+ export async function readBulkPipelineHealth(config, fallbackPollAfterSeconds, selectorFields = {}) {
5
+ try {
6
+ const payload = await jsonRequest(config, pipelineHealthPath(selectorFields));
7
+ return pipelineHealthFromPayload(payload, fallbackPollAfterSeconds);
8
+ }
9
+ catch (error) {
10
+ if (error instanceof HttpError && error.status && [404, 405, 501].includes(error.status)) {
11
+ return {
12
+ healthy: true,
13
+ pressure: "unknown",
14
+ recommendedAction: "continue",
15
+ recommendedPollAfterSeconds: fallbackPollAfterSeconds,
16
+ message: "Pipeline health endpoint is unavailable; continuing without backpressure.",
17
+ };
18
+ }
19
+ if (error instanceof HttpError) {
20
+ return {
21
+ healthy: false,
22
+ pressure: "paused",
23
+ recommendedAction: "pause_top_up",
24
+ recommendedPollAfterSeconds: error.retryAfterSeconds ?? Math.max(fallbackPollAfterSeconds, 30),
25
+ message: error.message,
26
+ };
27
+ }
28
+ return {
29
+ healthy: false,
30
+ pressure: "paused",
31
+ recommendedAction: "pause_top_up",
32
+ recommendedPollAfterSeconds: Math.max(fallbackPollAfterSeconds, 30),
33
+ message: error instanceof Error ? error.message : String(error),
34
+ };
35
+ }
36
+ }
37
+ function pipelineHealthPath(selectorFields) {
38
+ const params = new URLSearchParams();
39
+ for (const key of ["primary_collection_id", "collection_path", "collection_key"]) {
40
+ const value = selectorFields[key];
41
+ if (value)
42
+ params.set(key, value);
43
+ }
44
+ const query = params.toString();
45
+ return query ? `pipeline/health?${query}` : "pipeline/health";
46
+ }
47
+ function pipelineHealthFromPayload(payload, fallbackPollAfterSeconds) {
48
+ const data = responseData(payload);
49
+ if (!isObject(data)) {
50
+ throw new CliError("Pipeline health response did not contain an object payload.");
51
+ }
52
+ const action = stringField(data, "recommendedAction");
53
+ if (action !== "continue" && action !== "slow_down" && action !== "pause_top_up") {
54
+ throw new CliError("Pipeline health response did not contain a valid recommendedAction.");
55
+ }
56
+ const pressure = stringField(data, "pressure");
57
+ const pollAfter = Number(data.recommendedPollAfterSeconds);
58
+ return {
59
+ healthy: typeof data.healthy === "boolean" ? data.healthy : action === "continue",
60
+ pressure: pressure === "ok" || pressure === "degraded" || pressure === "paused" ? pressure : "unknown",
61
+ recommendedAction: action,
62
+ recommendedPollAfterSeconds: Number.isFinite(pollAfter) && pollAfter > 0 ? pollAfter : fallbackPollAfterSeconds,
63
+ checkedAt: stringField(data, "checkedAt"),
64
+ message: stringField(data, "message") ??
65
+ (isObject(data.indexPreflight) ? stringField(data.indexPreflight, "message") : undefined),
66
+ };
67
+ }
68
+ //# sourceMappingURL=pipeline-health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-health.js","sourceRoot":"","sources":["../../src/kb/pipeline-health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type ParsedArgs } from "../args.js";
2
+ import type { CollectionSelector } from "./client.js";
3
+ export declare function resolveCollectionSelector(args: ParsedArgs, env: NodeJS.ProcessEnv): CollectionSelector;
@@ -0,0 +1,40 @@
1
+ import { getString } from "../args.js";
2
+ import { firstEnv } from "../env.js";
3
+ import { CliError } from "../errors.js";
4
+ export function resolveCollectionSelector(args, env) {
5
+ const selectors = [];
6
+ addSelector(selectors, "primary_collection_id", getString(args, "collection-id"));
7
+ addSelector(selectors, "collection_path", getString(args, "collection-path"));
8
+ addSelector(selectors, "collection_key", getString(args, "collection-key"));
9
+ addSelector(selectors, "collection_name", getString(args, "collection-name"));
10
+ if (selectors.length > 1) {
11
+ throw new CliError("Provide exactly one collection selector.");
12
+ }
13
+ if (selectors.length === 1)
14
+ return selectors[0];
15
+ const envName = firstEnv(env, "TIANGONG_KB_DEFAULT_COLLECTION_NAME");
16
+ if (envName)
17
+ return { field: "collection_name", value: envName };
18
+ const legacyName = firstEnv(env, "TIANGONG_KB_DEFAULT_COLLECTION_ID");
19
+ if (legacyName) {
20
+ if (isUuid(legacyName)) {
21
+ throw new CliError("TIANGONG_KB_DEFAULT_COLLECTION_ID is treated as a collection name. Use --collection-id for UUID uploads.");
22
+ }
23
+ return { field: "collection_name", value: legacyName };
24
+ }
25
+ const envPath = firstEnv(env, "TIANGONG_KB_DEFAULT_COLLECTION_PATH");
26
+ if (envPath)
27
+ return { field: "collection_path", value: envPath };
28
+ const envKey = firstEnv(env, "TIANGONG_KB_DEFAULT_COLLECTION_KEY");
29
+ if (envKey)
30
+ return { field: "collection_key", value: envKey };
31
+ throw new CliError("Missing collection selector. Provide --collection-name, --collection-key, --collection-path, --collection-id, or set TIANGONG_KB_DEFAULT_COLLECTION_NAME.");
32
+ }
33
+ function addSelector(selectors, field, value) {
34
+ if (value)
35
+ selectors.push({ field, value });
36
+ }
37
+ function isUuid(value) {
38
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
39
+ }
40
+ //# sourceMappingURL=selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.js","sourceRoot":"","sources":["../../src/kb/selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAmB,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGxC,MAAM,UAAU,yBAAyB,CACvC,IAAgB,EAChB,GAAsB;IAEtB,MAAM,SAAS,GAAyB,EAAE,CAAC;IAC3C,WAAW,CAAC,SAAS,EAAE,uBAAuB,EAAE,SAAS,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC;IAClF,WAAW,CAAC,SAAS,EAAE,iBAAiB,EAAE,SAAS,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC9E,WAAW,CAAC,SAAS,EAAE,gBAAgB,EAAE,SAAS,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC5E,WAAW,CAAC,SAAS,EAAE,iBAAiB,EAAE,SAAS,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAE9E,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,QAAQ,CAAC,0CAA0C,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC,CAAC,CAAuB,CAAC;IAEtE,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,EAAE,qCAAqC,CAAC,CAAC;IACrE,IAAI,OAAO;QAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAEjE,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,EAAE,mCAAmC,CAAC,CAAC;IACtE,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,QAAQ,CAChB,0GAA0G,CAC3G,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IACzD,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,EAAE,qCAAqC,CAAC,CAAC;IACrE,IAAI,OAAO;QAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAEjE,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,oCAAoC,CAAC,CAAC;IACnE,IAAI,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAE9D,MAAM,IAAI,QAAQ,CAChB,2JAA2J,CAC5J,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAClB,SAA+B,EAC/B,KAAkC,EAClC,KAAyB;IAEzB,IAAI,KAAK;QAAE,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,4EAA4E,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAClG,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { KbConfig } from "./config.js";
2
+ export interface BulkStatusItem {
3
+ documentId: string;
4
+ status?: string | undefined;
5
+ terminal?: boolean | undefined;
6
+ opensearchIndexed?: boolean | undefined;
7
+ pineconeIndexed?: boolean | undefined;
8
+ indexRecordCount?: number | undefined;
9
+ lastError?: string | undefined;
10
+ lastErrorStage?: string | undefined;
11
+ itemError?: {
12
+ code: string;
13
+ message: string;
14
+ retryable: boolean;
15
+ };
16
+ raw: unknown;
17
+ }
18
+ export declare function batchDocumentStatuses(config: KbConfig, documentIds: string[]): Promise<BulkStatusItem[]>;
19
+ export declare function getDocumentStatus(config: KbConfig, documentId: string): Promise<unknown>;
@@ -0,0 +1,74 @@
1
+ import { isObject, responseData, stringField } from "../data.js";
2
+ import { HttpError } from "../errors.js";
3
+ import { jsonRequest } from "../http.js";
4
+ const KB_DOCUMENT_STATUS_BATCH_LIMIT = 100;
5
+ export async function batchDocumentStatuses(config, documentIds) {
6
+ const statuses = [];
7
+ for (let index = 0; index < documentIds.length; index += KB_DOCUMENT_STATUS_BATCH_LIMIT) {
8
+ const chunk = documentIds.slice(index, index + KB_DOCUMENT_STATUS_BATCH_LIMIT);
9
+ try {
10
+ const payload = await jsonRequest(config, "documents/status:batch", {
11
+ method: "POST",
12
+ body: JSON.stringify({ documentIds: chunk }),
13
+ });
14
+ statuses.push(...batchStatusItems(payload));
15
+ }
16
+ catch (error) {
17
+ if (error instanceof HttpError && error.status && [404, 405, 501].includes(error.status)) {
18
+ statuses.push(...(await Promise.all(chunk.map(async (documentId) => statusItemFromPayload(await getDocumentStatus(config, documentId), documentId)))));
19
+ continue;
20
+ }
21
+ throw error;
22
+ }
23
+ }
24
+ return statuses;
25
+ }
26
+ export async function getDocumentStatus(config, documentId) {
27
+ return jsonRequest(config, `documents/${encodeURIComponent(documentId)}/status`);
28
+ }
29
+ function batchStatusItems(payload) {
30
+ const data = responseData(payload);
31
+ const items = isObject(data) && Array.isArray(data.documents)
32
+ ? data.documents
33
+ : isObject(data) && Array.isArray(data.results)
34
+ ? data.results
35
+ : Array.isArray(data)
36
+ ? data
37
+ : [];
38
+ return items.filter(isObject).map((item) => batchStatusItemFromPayload(item));
39
+ }
40
+ function statusItemFromPayload(payload, fallbackDocumentId = "") {
41
+ const data = responseData(payload);
42
+ const item = isObject(data) ? data : {};
43
+ return {
44
+ documentId: stringField(item, "documentId") ?? stringField(item, "document_id") ?? fallbackDocumentId,
45
+ status: stringField(item, "status"),
46
+ terminal: typeof item.terminal === "boolean" ? item.terminal : undefined,
47
+ opensearchIndexed: typeof item.opensearchIndexed === "boolean" ? item.opensearchIndexed : undefined,
48
+ pineconeIndexed: typeof item.pineconeIndexed === "boolean" ? item.pineconeIndexed : undefined,
49
+ indexRecordCount: typeof item.indexRecordCount === "number" ? item.indexRecordCount : undefined,
50
+ lastError: typeof item.lastError === "string" ? item.lastError : undefined,
51
+ lastErrorStage: typeof item.lastErrorStage === "string" ? item.lastErrorStage : undefined,
52
+ raw: payload,
53
+ };
54
+ }
55
+ function batchStatusItemFromPayload(item) {
56
+ const documentId = stringField(item, "documentId") ?? stringField(item, "document_id") ?? "";
57
+ if (item.ok === true && isObject(item.status)) {
58
+ return statusItemFromPayload(item.status, documentId);
59
+ }
60
+ if (item.ok === false && isObject(item.error)) {
61
+ const error = item.error;
62
+ return {
63
+ documentId,
64
+ itemError: {
65
+ code: stringField(error, "code") ?? "STATUS_ITEM_ERROR",
66
+ message: stringField(error, "message") ?? "Document status lookup failed.",
67
+ retryable: typeof error.retryable === "boolean" ? error.retryable : false,
68
+ },
69
+ raw: item,
70
+ };
71
+ }
72
+ return statusItemFromPayload(item, documentId);
73
+ }
74
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/kb/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { CliIO } from "../io.js";
2
+ export declare function runResearchCommand(argv: string[], io: CliIO): Promise<number>;