@compforge/harness-toolbox 0.4.5 → 0.4.7

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.
@@ -2,13 +2,13 @@ import {
2
2
  findPodsForService,
3
3
  findService,
4
4
  listServiceNetwork
5
- } from "./chunk-j46x7j7c.js";
5
+ } from "./chunk-xgnz10sr.js";
6
6
  import {
7
7
  findPod
8
8
  } from "./chunk-6fnhzhdb.js";
9
9
  import {
10
10
  PortForwardScope
11
- } from "./chunk-631vce5z.js";
11
+ } from "./chunk-nftzckdy.js";
12
12
 
13
13
  // src/kubernetes/service-port-forward.ts
14
14
  class ServicePortForwarder {
@@ -24,13 +24,14 @@ class ServicePortForwarder {
24
24
  this.#scope = new PortForwardScope(starter);
25
25
  }
26
26
  static async create(executor, opts, starter) {
27
- const network = await listServiceNetwork(executor, opts.namespace);
27
+ const network = await listServiceNetwork(executor, opts.namespace, opts.signal);
28
28
  return new ServicePortForwarder(opts, network.services, network.pods, starter);
29
29
  }
30
30
  get activeForwards() {
31
31
  return this.#scope.active;
32
32
  }
33
33
  forward(endpoint) {
34
+ this.opts.signal?.throwIfAborted();
34
35
  const key = `${endpoint.host}:${endpoint.port}`;
35
36
  let pending = this.#cache.get(key);
36
37
  if (!pending) {
@@ -24,7 +24,9 @@ function spawnProcess(argv, opts) {
24
24
  stdout: Readable.toWeb(child.stdout),
25
25
  stderr: Readable.toWeb(child.stderr),
26
26
  exited,
27
- kill: () => child.kill()
27
+ kill: (signal) => {
28
+ child.kill(signal);
29
+ }
28
30
  };
29
31
  }
30
32
  function sleep(ms) {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  startPortForward
3
- } from "./chunk-631vce5z.js";
3
+ } from "./chunk-nftzckdy.js";
4
4
  import {
5
5
  KubectlExecutor
6
- } from "./chunk-hmah9t8e.js";
6
+ } from "./chunk-rq5fc007.js";
7
7
  import {
8
8
  POD_RELAY_SCRIPT
9
9
  } from "./chunk-ssj93brx.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-ae84rzq5.js";
4
4
  import {
5
5
  ServicePortForwarder
6
- } from "./chunk-2171tajs.js";
6
+ } from "./chunk-1ts7pswj.js";
7
7
  import {
8
8
  KubernetesResourceTransport
9
9
  } from "./chunk-x0yhfg29.js";
@@ -15,7 +15,7 @@ import {
15
15
  } from "./chunk-rkt41za2.js";
16
16
  import {
17
17
  KubectlExecutor
18
- } from "./chunk-hmah9t8e.js";
18
+ } from "./chunk-rq5fc007.js";
19
19
 
20
20
  // src/kubernetes/client.ts
21
21
  class KubernetesClient {
@@ -3,6 +3,7 @@ import {
3
3
  awaitWithSignal
4
4
  } from "./chunk-gm4swndx.js";
5
5
  import {
6
+ TimeoutError,
6
7
  ToolboxError
7
8
  } from "./chunk-rkt41za2.js";
8
9
  import {
@@ -11,6 +12,23 @@ import {
11
12
 
12
13
  // src/opensearch/client.ts
13
14
  import { Client, Connection, errors } from "@opensearch-project/opensearch";
15
+ function describeOpenSearchError(error) {
16
+ const parts = [];
17
+ const seen = new Set;
18
+ while (error && typeof error === "object" && !seen.has(error) && parts.length < 4) {
19
+ seen.add(error);
20
+ const value = error;
21
+ const safe = (value2) => typeof value2 === "number" ? String(value2) : typeof value2 === "string" && /^[a-zA-Z0-9_.-]{1,80}$/.test(value2) ? value2 : undefined;
22
+ parts.push([
23
+ `error=${safe(value.name) ?? "Error"}`,
24
+ safe(value.code) && `code=${safe(value.code)}`,
25
+ safe(value.kind) && `kind=${safe(value.kind)}`,
26
+ safe(value.statusCode ?? value.meta?.statusCode) && `status=${safe(value.statusCode ?? value.meta?.statusCode)}`
27
+ ].filter(Boolean).join(" "));
28
+ error = value.cause;
29
+ }
30
+ return parts.join(" cause=") || "error=UnknownError";
31
+ }
14
32
  function isOpenSearchReadApi(search) {
15
33
  return typeof search.request === "function";
16
34
  }
@@ -33,8 +51,10 @@ function createClient(options) {
33
51
  }
34
52
 
35
53
  class OpenSearchEngine {
54
+ options;
36
55
  client;
37
56
  constructor(options, client) {
57
+ this.options = options;
38
58
  this.client = client ?? createClient(options);
39
59
  }
40
60
  async count(index, query) {
@@ -55,21 +75,39 @@ class OpenSearchEngine {
55
75
  });
56
76
  return response.body;
57
77
  }
58
- async ping(signal, timeoutMs) {
78
+ async ping(signal, timeoutMs = this.options.requestTimeoutMs ?? 60000) {
59
79
  signal?.throwIfAborted();
60
- const request = this.client.ping({}, timeoutMs === undefined ? undefined : { requestTimeout: timeoutMs });
61
- const abort = () => {
62
- request.abort?.();
63
- };
64
- signal?.addEventListener("abort", abort, { once: true });
80
+ const started = Date.now();
81
+ const url = new URL(this.options.node);
82
+ const target = `${url.protocol}//${url.host}`;
83
+ const log = this.options.onDiagnostic ?? (() => {});
84
+ log(`OpenSearch probe start target=${target} timeout_ms=${timeoutMs}`);
85
+ const controller = new AbortController;
86
+ const timer = setTimeout(() => controller.abort(new TimeoutError(`OpenSearch probe timed out after ${timeoutMs}ms`)), timeoutMs);
87
+ const active = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
65
88
  try {
66
- return await request;
89
+ const request = this.client.ping({}, { requestTimeout: timeoutMs });
90
+ const result = await awaitWithSignal(request, active, () => request.abort?.());
91
+ log(`OpenSearch probe ok target=${target} elapsed_ms=${Date.now() - started}`);
92
+ return result;
93
+ } catch (error) {
94
+ log(`OpenSearch probe failed target=${target} elapsed_ms=${Date.now() - started} ${describeOpenSearchError(error)}`);
95
+ throw error;
67
96
  } finally {
68
- signal?.removeEventListener("abort", abort);
97
+ clearTimeout(timer);
69
98
  }
70
99
  }
71
- close() {
72
- return this.client.close();
100
+ async close() {
101
+ const controller = new AbortController;
102
+ const timer = setTimeout(() => controller.abort(new TimeoutError("OpenSearch close timed out after 2000ms")), 2000);
103
+ try {
104
+ await awaitWithSignal(this.client.close(), controller.signal);
105
+ } catch (error) {
106
+ this.options.onDiagnostic?.(`OpenSearch close failed ${describeOpenSearchError(error)}`);
107
+ throw error;
108
+ } finally {
109
+ clearTimeout(timer);
110
+ }
73
111
  }
74
112
  }
75
113
  function openSearchRetryReason(error) {
@@ -112,6 +150,7 @@ class OpenSearchClient {
112
150
  open: async (transport, attempt) => {
113
151
  if (transport.kind !== "tcp")
114
152
  throw new Error("OpenSearch requires a TCP transport");
153
+ this.lifecycle.onDiagnostic?.(`OpenSearch route start transport=${transport.name} target=${original.protocol}//${original.host} timeout_ms=${attempt.remainingMs()}`);
115
154
  const endpoint = await transport.connect({
116
155
  host: original.hostname,
117
156
  port: Number(original.port || (original.protocol === "https:" ? 443 : 80)),
@@ -121,7 +160,7 @@ class OpenSearchClient {
121
160
  const url = new URL(original);
122
161
  url.hostname = endpoint.host;
123
162
  url.port = String(endpoint.port);
124
- const engine = new OpenSearchEngine({ ...target, node: url.toString(), servername: endpoint.servername ?? target.servername ?? original.hostname });
163
+ const engine = new OpenSearchEngine({ ...target, onDiagnostic: this.lifecycle.onDiagnostic, node: url.toString(), servername: endpoint.servername ?? target.servername ?? original.hostname });
125
164
  try {
126
165
  await engine.ping(attempt.signal, attempt.remainingMs());
127
166
  return { connection: engine, transport: transport.name };
@@ -134,6 +173,7 @@ class OpenSearchClient {
134
173
  retryReason: openSearchRetryReason
135
174
  });
136
175
  } catch (error) {
176
+ this.lifecycle.onDiagnostic?.(`OpenSearch connect failed ${describeOpenSearchError(error)}`);
137
177
  this.signal.throwIfAborted();
138
178
  if (error instanceof ToolboxError && error.kind === "timeout")
139
179
  throw error;
@@ -193,4 +233,4 @@ async function openOpenSearch(source, lifecycle = {}) {
193
233
  return client;
194
234
  }
195
235
 
196
- export { isOpenSearchReadApi, OpenSearchEngine, OpenSearchClient, openOpenSearch };
236
+ export { describeOpenSearchError, isOpenSearchReadApi, OpenSearchEngine, OpenSearchClient, openOpenSearch };
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  buildKubectlArgs
3
- } from "./chunk-hmah9t8e.js";
3
+ } from "./chunk-rq5fc007.js";
4
4
  import {
5
5
  spawnProcess
6
- } from "./chunk-mn6dwsvh.js";
6
+ } from "./chunk-9shz0bw1.js";
7
7
 
8
8
  // src/kubernetes/port-forward.ts
9
9
  async function startPortForward(opts) {
10
+ opts.signal?.throwIfAborted();
10
11
  const target = opts.target ?? (opts.service ? { kind: "service", name: opts.service } : undefined);
11
12
  if (!target)
12
13
  return { ok: false, reason: "port-forward 缺少 Service/Pod 目标" };
@@ -24,8 +25,51 @@ async function startPortForward(opts) {
24
25
  return { ok: false, reason: err instanceof Error ? err.message : String(err) };
25
26
  }
26
27
  const timeoutMs = opts.timeoutMs ?? 15000;
27
- const stderrPromise = new Response(proc.stderr).text();
28
+ const log = opts.onDiagnostic ?? (() => {});
29
+ const started = Date.now();
30
+ log(`port-forward start target=${target.kind}/${target.name} namespace=${opts.namespace ?? "default"} remote_port=${opts.remotePort} timeout_ms=${timeoutMs}`);
31
+ let stderr = "";
32
+ let loggedBytes = 0;
33
+ const stderrReader = proc.stderr.getReader();
34
+ const stderrDone = (async () => {
35
+ const decoder2 = new TextDecoder;
36
+ for (;; ) {
37
+ const chunk = await stderrReader.read();
38
+ if (chunk.done)
39
+ break;
40
+ const text = decoder2.decode(chunk.value, { stream: true }).replace(/(https?:\/\/)[^\s/@]+:[^\s/@]+@/g, "$1[redacted]@").replace(/([?&](?:token|password|secret|key)=)[^&\s]+/gi, "$1[redacted]").replace(/((?:authorization|password|token)[:=]\s*)[^\r\n]+/gi, "$1[redacted]");
41
+ stderr = (stderr + text).slice(-8192);
42
+ if (loggedBytes < 8192) {
43
+ const diagnostic = text.slice(0, 8192 - loggedBytes);
44
+ loggedBytes += diagnostic.length;
45
+ log(`port-forward stderr: ${diagnostic.trim()}`);
46
+ }
47
+ }
48
+ })().catch(() => {});
49
+ let stopped = false;
50
+ let cancelWait;
51
+ const cancelled = new Promise((resolve) => {
52
+ cancelWait = () => resolve("cancelled");
53
+ });
54
+ const abort = () => {
55
+ log(`port-forward cancelled elapsed_ms=${Date.now() - started}`);
56
+ stop();
57
+ cancelWait();
58
+ };
59
+ const stop = () => {
60
+ if (stopped)
61
+ return;
62
+ stopped = true;
63
+ opts.signal?.removeEventListener("abort", abort);
64
+ proc.kill("SIGKILL");
65
+ stderrReader.cancel().catch(() => {});
66
+ reader.cancel().catch(() => {});
67
+ };
28
68
  const reader = proc.stdout.getReader();
69
+ opts.signal?.addEventListener("abort", abort, { once: true });
70
+ if (opts.signal?.aborted)
71
+ abort();
72
+ proc.exited.then(() => opts.signal?.removeEventListener("abort", abort), () => opts.signal?.removeEventListener("abort", abort));
29
73
  const decoder = new TextDecoder;
30
74
  const deadline = Date.now() + timeoutMs;
31
75
  let out = "";
@@ -36,6 +80,7 @@ async function startPortForward(opts) {
36
80
  let timer;
37
81
  const chunk = await Promise.race([
38
82
  reader.read(),
83
+ cancelled,
39
84
  new Promise((resolve) => {
40
85
  timer = setTimeout(() => resolve("timeout"), remain);
41
86
  }),
@@ -43,10 +88,13 @@ async function startPortForward(opts) {
43
88
  ]).finally(() => {
44
89
  clearTimeout(timer);
45
90
  });
91
+ opts.signal?.throwIfAborted();
92
+ if (chunk === "cancelled")
93
+ throw opts.signal?.reason;
46
94
  if (chunk === "timeout")
47
95
  break;
48
96
  if (typeof chunk === "object" && "error" in chunk) {
49
- proc.kill();
97
+ stop();
50
98
  return { ok: false, reason: chunk.error instanceof Error ? chunk.error.message : String(chunk.error) };
51
99
  }
52
100
  if (chunk === "exited" || chunk.done)
@@ -54,16 +102,18 @@ async function startPortForward(opts) {
54
102
  out += decoder.decode(chunk.value);
55
103
  const m = out.match(/Forwarding from 127\.0\.0\.1:(\d+)/);
56
104
  if (m) {
105
+ log(`port-forward listening local=127.0.0.1:${m[1]} elapsed_ms=${Date.now() - started}`);
57
106
  return {
58
107
  ok: true,
59
- value: { target, localPort: Number(m[1]), command: argv, stop: () => proc.kill() }
108
+ value: { target, localPort: Number(m[1]), command: argv, stop }
60
109
  };
61
110
  }
62
111
  }
63
- proc.kill();
64
- const stderr = await stderrPromise.catch(() => "");
112
+ await Promise.resolve();
113
+ stop();
65
114
  const reason = stderr.trim().split(`
66
115
  `)[0] || `port-forward 未就绪(${timeoutMs}ms 超时)`;
116
+ log(`port-forward failed elapsed_ms=${Date.now() - started} reason=${reason}`);
67
117
  return { ok: false, reason };
68
118
  }
69
119
 
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  spawnProcess
3
- } from "./chunk-mn6dwsvh.js";
3
+ } from "./chunk-9shz0bw1.js";
4
4
 
5
5
  // src/kubernetes/executor.ts
6
6
  function buildKubectlArgs(opts, sub) {
@@ -53,11 +53,13 @@ function findPodsForService(services, pods, serviceName, namespace) {
53
53
  return [];
54
54
  return pods.filter((pod) => pod.namespace === namespace && pod.phase === "Running" && selector.every(([name, value]) => pod.labels[name] === value)).sort((left, right) => left.name.localeCompare(right.name));
55
55
  }
56
- async function listServiceNetwork(executor, namespace) {
56
+ async function listServiceNetwork(executor, namespace, signal) {
57
+ signal?.throwIfAborted();
57
58
  const [serviceResult, podResult] = await Promise.all([
58
- executor.run(["get", "services", "-o", "json"], { timeoutMs: 20000 }),
59
- executor.run(["get", "pods", "-o", "json"], { timeoutMs: 20000 })
59
+ executor.run(["get", "services", "-o", "json"], { timeoutMs: 20000, signal }),
60
+ executor.run(["get", "pods", "-o", "json"], { timeoutMs: 20000, signal })
60
61
  ]);
62
+ signal?.throwIfAborted();
61
63
  if (!serviceResult.ok) {
62
64
  throw new Error(`读取 Service 失败:${serviceResult.stderr.trim() || `exit=${serviceResult.exitCode}`}`);
63
65
  }
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  KubernetesClient
3
- } from "../chunk-g2bac2jd.js";
3
+ } from "../chunk-m391jmpw.js";
4
4
  import"../chunk-ae84rzq5.js";
5
- import"../chunk-2171tajs.js";
6
- import"../chunk-j46x7j7c.js";
5
+ import"../chunk-1ts7pswj.js";
6
+ import"../chunk-xgnz10sr.js";
7
7
  import"../chunk-6fnhzhdb.js";
8
8
  import"../chunk-x0yhfg29.js";
9
9
  import"../chunk-dpcge1xt.js";
@@ -11,9 +11,9 @@ import"../chunk-r3rnsvwv.js";
11
11
  import"../chunk-a9htb6cr.js";
12
12
  import"../chunk-rkt41za2.js";
13
13
  import"../chunk-v3hxvnrc.js";
14
- import"../chunk-631vce5z.js";
15
- import"../chunk-hmah9t8e.js";
16
- import"../chunk-mn6dwsvh.js";
14
+ import"../chunk-nftzckdy.js";
15
+ import"../chunk-rq5fc007.js";
16
+ import"../chunk-9shz0bw1.js";
17
17
  export {
18
18
  KubernetesClient
19
19
  };
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  KubernetesClient
3
- } from "../chunk-g2bac2jd.js";
3
+ } from "../chunk-m391jmpw.js";
4
4
  import"../chunk-ae84rzq5.js";
5
- import"../chunk-2171tajs.js";
6
- import"../chunk-j46x7j7c.js";
5
+ import"../chunk-1ts7pswj.js";
6
+ import"../chunk-xgnz10sr.js";
7
7
  import"../chunk-6fnhzhdb.js";
8
8
  import"../chunk-x0yhfg29.js";
9
9
  import"../chunk-dpcge1xt.js";
@@ -13,9 +13,9 @@ import {
13
13
  } from "../chunk-a9htb6cr.js";
14
14
  import"../chunk-rkt41za2.js";
15
15
  import"../chunk-v3hxvnrc.js";
16
- import"../chunk-631vce5z.js";
17
- import"../chunk-hmah9t8e.js";
18
- import"../chunk-mn6dwsvh.js";
16
+ import"../chunk-nftzckdy.js";
17
+ import"../chunk-rq5fc007.js";
18
+ import"../chunk-9shz0bw1.js";
19
19
 
20
20
  // src/kubernetes/environment.ts
21
21
  class KubernetesEnvironment {
@@ -3,8 +3,8 @@ import {
3
3
  buildExecArgs,
4
4
  buildKubectlArgs,
5
5
  runArgv
6
- } from "../chunk-hmah9t8e.js";
7
- import"../chunk-mn6dwsvh.js";
6
+ } from "../chunk-rq5fc007.js";
7
+ import"../chunk-9shz0bw1.js";
8
8
  export {
9
9
  runArgv,
10
10
  buildKubectlArgs,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  findPodsForService,
3
3
  parseServices
4
- } from "../chunk-j46x7j7c.js";
4
+ } from "../chunk-xgnz10sr.js";
5
5
  import {
6
6
  parsePods
7
7
  } from "../chunk-6fnhzhdb.js";
@@ -17,6 +17,7 @@ export interface PortForwardResult {
17
17
  }
18
18
  export type StartPortForward = typeof startPortForward;
19
19
  /**
20
+ * @spec Caller cancellation stops both startup and an active forward, preserving the original abort reason.
20
21
  * 起 `kubectl port-forward svc/<service> 0:<remotePort>` 并等待就绪。
21
22
  * 本地端口让 kubectl 自选(0:),从 stdout 的 "Forwarding from 127.0.0.1:<port>" 解析,
22
23
  * 避免固定端口在运维机上撞占用。调用方负责在采集结束后 stop()。
@@ -26,6 +27,8 @@ export declare function startPortForward(opts: KubectlOptions & {
26
27
  target?: PortForwardTarget;
27
28
  remotePort: number;
28
29
  timeoutMs?: number;
30
+ signal?: AbortSignal;
31
+ onDiagnostic?: (line: string) => void;
29
32
  }): Promise<PortForwardResult>;
30
33
  /** 同一次诊断可能按拓扑建立多个 forward;scope 保证异常路径也能一次性回收。 */
31
34
  export declare class PortForwardScope {
@@ -37,6 +40,8 @@ export declare class PortForwardScope {
37
40
  target: PortForwardTarget;
38
41
  remotePort: number;
39
42
  timeoutMs?: number;
43
+ signal?: AbortSignal;
44
+ onDiagnostic?: (line: string) => void;
40
45
  }): Promise<PortForwardResult>;
41
46
  stop(): void;
42
47
  }
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  PortForwardScope,
3
3
  startPortForward
4
- } from "../chunk-631vce5z.js";
5
- import"../chunk-hmah9t8e.js";
6
- import"../chunk-mn6dwsvh.js";
4
+ } from "../chunk-nftzckdy.js";
5
+ import"../chunk-rq5fc007.js";
6
+ import"../chunk-9shz0bw1.js";
7
7
  export {
8
8
  startPortForward,
9
9
  PortForwardScope
@@ -20,6 +20,8 @@ export declare class ServicePortForwarder {
20
20
  private constructor();
21
21
  static create(executor: Executor, opts: KubectlOptions & {
22
22
  namespace: string;
23
+ signal?: AbortSignal;
24
+ onDiagnostic?: (line: string) => void;
23
25
  }, starter?: StartPortForward): Promise<ServicePortForwarder>;
24
26
  get activeForwards(): readonly import("./port-forward").PortForward[];
25
27
  forward(endpoint: KubernetesEndpoint): Promise<ForwardedEndpoint>;
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  ServicePortForwarder
3
- } from "../chunk-2171tajs.js";
4
- import"../chunk-j46x7j7c.js";
3
+ } from "../chunk-1ts7pswj.js";
4
+ import"../chunk-xgnz10sr.js";
5
5
  import"../chunk-6fnhzhdb.js";
6
- import"../chunk-631vce5z.js";
7
- import"../chunk-hmah9t8e.js";
8
- import"../chunk-mn6dwsvh.js";
6
+ import"../chunk-nftzckdy.js";
7
+ import"../chunk-rq5fc007.js";
8
+ import"../chunk-9shz0bw1.js";
9
9
  export {
10
10
  ServicePortForwarder
11
11
  };
@@ -25,7 +25,7 @@ export declare function findService(services: readonly KubernetesService[], endp
25
25
  export declare function findServicesForPod(services: readonly KubernetesService[], pod: KubernetesPod): KubernetesService[];
26
26
  /** Service → Pod 由 Kubernetes selector 决定,不让上层用 Pod 名称前缀猜测。 */
27
27
  export declare function findPodsForService(services: readonly KubernetesService[], pods: readonly KubernetesPod[], serviceName: string, namespace: string): KubernetesPod[];
28
- export declare function listServiceNetwork(executor: Executor, namespace: string): Promise<{
28
+ export declare function listServiceNetwork(executor: Executor, namespace: string, signal?: AbortSignal): Promise<{
29
29
  services: KubernetesService[];
30
30
  pods: KubernetesPod[];
31
31
  }>;
@@ -5,7 +5,7 @@ import {
5
5
  listServiceNetwork,
6
6
  parseServices,
7
7
  serviceIdentity
8
- } from "../chunk-j46x7j7c.js";
8
+ } from "../chunk-xgnz10sr.js";
9
9
  import"../chunk-6fnhzhdb.js";
10
10
  export {
11
11
  serviceIdentity,
@@ -10,10 +10,10 @@ import"../chunk-gm4swndx.js";
10
10
  import"../chunk-rkt41za2.js";
11
11
  import"../chunk-v3hxvnrc.js";
12
12
  import"../chunk-h8fwx0k7.js";
13
- import"../chunk-wv4jwhvj.js";
14
- import"../chunk-631vce5z.js";
15
- import"../chunk-hmah9t8e.js";
16
- import"../chunk-mn6dwsvh.js";
13
+ import"../chunk-fqrknvr8.js";
14
+ import"../chunk-nftzckdy.js";
15
+ import"../chunk-rq5fc007.js";
16
+ import"../chunk-9shz0bw1.js";
17
17
  import"../chunk-ssj93brx.js";
18
18
  export {
19
19
  openMysql,
@@ -22,10 +22,10 @@ import"../chunk-gm4swndx.js";
22
22
  import"../chunk-rkt41za2.js";
23
23
  import"../chunk-v3hxvnrc.js";
24
24
  import"../chunk-h8fwx0k7.js";
25
- import"../chunk-wv4jwhvj.js";
26
- import"../chunk-631vce5z.js";
27
- import"../chunk-hmah9t8e.js";
28
- import"../chunk-mn6dwsvh.js";
25
+ import"../chunk-fqrknvr8.js";
26
+ import"../chunk-nftzckdy.js";
27
+ import"../chunk-rq5fc007.js";
28
+ import"../chunk-9shz0bw1.js";
29
29
  import"../chunk-ssj93brx.js";
30
30
  export {
31
31
  withReadScope,
@@ -7,6 +7,8 @@ export interface OpenSearchAuth {
7
7
  }
8
8
  export interface OpenSearchOptions {
9
9
  node: string;
10
+ /** Bounded operational facts; never protocol bodies or credentials. */
11
+ onDiagnostic?: (line: string) => void;
10
12
  auth: OpenSearchAuth;
11
13
  requestTimeoutMs?: number;
12
14
  /** Per-route mapping and probe budget; query deadlines remain independent. */
@@ -41,6 +43,11 @@ export interface OpenSearchClientApi {
41
43
  };
42
44
  close(): Promise<void>;
43
45
  }
46
+ /** Safe error-chain facts for logs; driver messages/meta can contain credentials and response bodies. */
47
+ export declare function describeOpenSearchError(error: unknown): string;
48
+ export interface OpenSearchLifecycle extends ClientLifecycle {
49
+ onDiagnostic?: (line: string) => void;
50
+ }
44
51
  /** OpenSearch-specific read APIs stay outside the engine-neutral SearchEngine contract. */
45
52
  export interface OpenSearchReadApi extends SearchEngine {
46
53
  request(path: string, query?: SearchQuery): Promise<unknown>;
@@ -48,11 +55,13 @@ export interface OpenSearchReadApi extends SearchEngine {
48
55
  export declare function isOpenSearchReadApi(search: SearchEngine): search is OpenSearchReadApi;
49
56
  /** Official OpenSearch client behind the engine-neutral SearchEngine contract. */
50
57
  export declare class OpenSearchEngine implements OpenSearchReadApi {
58
+ private readonly options;
51
59
  private readonly client;
52
60
  constructor(options: OpenSearchOptions, client?: OpenSearchClientApi);
53
61
  count(index: string, query: SearchQuery): Promise<number>;
54
62
  search(index: string, body: SearchQuery): Promise<SearchResult>;
55
63
  request(path: string, query?: SearchQuery): Promise<unknown>;
64
+ /** @spec Probe deadlines abort the underlying request even when the driver stalls. */
56
65
  ping(signal?: AbortSignal, timeoutMs?: number): Promise<unknown>;
57
66
  close(): Promise<void>;
58
67
  }
@@ -66,7 +75,7 @@ export declare class OpenSearchClient implements ManagedClient, OpenSearchReadAp
66
75
  private readonly source;
67
76
  private readonly lifecycle;
68
77
  readonly signal: AbortSignal;
69
- constructor(source: ConnectionSource<OpenSearchOptions>, lifecycle?: ClientLifecycle);
78
+ constructor(source: ConnectionSource<OpenSearchOptions>, lifecycle?: OpenSearchLifecycle);
70
79
  initialize(): Promise<void>;
71
80
  count(index: string, query: SearchQuery): Promise<number>;
72
81
  search(index: string, body: SearchQuery): Promise<SearchResult>;
@@ -75,4 +84,4 @@ export declare class OpenSearchClient implements ManagedClient, OpenSearchReadAp
75
84
  close(): Promise<void>;
76
85
  dispose(): Promise<void>;
77
86
  }
78
- export declare function openOpenSearch(source: ConnectionSource<OpenSearchOptions>, lifecycle?: ClientLifecycle): Promise<OpenSearchClient>;
87
+ export declare function openOpenSearch(source: ConnectionSource<OpenSearchOptions>, lifecycle?: OpenSearchLifecycle): Promise<OpenSearchClient>;
@@ -1,20 +1,22 @@
1
1
  import {
2
2
  OpenSearchClient,
3
3
  OpenSearchEngine,
4
+ describeOpenSearchError,
4
5
  isOpenSearchReadApi,
5
6
  openOpenSearch
6
- } from "../chunk-sbt20n84.js";
7
+ } from "../chunk-m4d29vfd.js";
7
8
  import"../chunk-gm4swndx.js";
8
9
  import"../chunk-rkt41za2.js";
9
10
  import"../chunk-h8fwx0k7.js";
10
- import"../chunk-wv4jwhvj.js";
11
- import"../chunk-631vce5z.js";
12
- import"../chunk-hmah9t8e.js";
13
- import"../chunk-mn6dwsvh.js";
11
+ import"../chunk-fqrknvr8.js";
12
+ import"../chunk-nftzckdy.js";
13
+ import"../chunk-rq5fc007.js";
14
+ import"../chunk-9shz0bw1.js";
14
15
  import"../chunk-ssj93brx.js";
15
16
  export {
16
17
  openOpenSearch,
17
18
  isOpenSearchReadApi,
19
+ describeOpenSearchError,
18
20
  OpenSearchEngine,
19
21
  OpenSearchClient
20
22
  };
@@ -8,22 +8,24 @@ import"../chunk-djk4kmxb.js";
8
8
  import {
9
9
  OpenSearchClient,
10
10
  OpenSearchEngine,
11
+ describeOpenSearchError,
11
12
  isOpenSearchReadApi,
12
13
  openOpenSearch
13
- } from "../chunk-sbt20n84.js";
14
+ } from "../chunk-m4d29vfd.js";
14
15
  import"../chunk-gm4swndx.js";
15
16
  import"../chunk-rkt41za2.js";
16
17
  import"../chunk-h8fwx0k7.js";
17
- import"../chunk-wv4jwhvj.js";
18
- import"../chunk-631vce5z.js";
19
- import"../chunk-hmah9t8e.js";
20
- import"../chunk-mn6dwsvh.js";
18
+ import"../chunk-fqrknvr8.js";
19
+ import"../chunk-nftzckdy.js";
20
+ import"../chunk-rq5fc007.js";
21
+ import"../chunk-9shz0bw1.js";
21
22
  import"../chunk-ssj93brx.js";
22
23
  export {
23
24
  searchAfterPages,
24
25
  parseOpenSearchEndpoint,
25
26
  openOpenSearch,
26
27
  isOpenSearchReadApi,
28
+ describeOpenSearchError,
27
29
  OpenSearchEngine,
28
30
  OpenSearchClient
29
31
  };
@@ -2,7 +2,7 @@ export interface RuntimeProcess {
2
2
  stdout: ReadableStream<Uint8Array>;
3
3
  stderr: ReadableStream<Uint8Array>;
4
4
  exited: Promise<number>;
5
- kill(): void;
5
+ kill(signal?: NodeJS.Signals): void;
6
6
  }
7
7
  export interface SpawnProcessOptions {
8
8
  stdin?: string | Uint8Array | ReadableStream<Uint8Array>;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  sleep,
3
3
  spawnProcess
4
- } from "../chunk-mn6dwsvh.js";
4
+ } from "../chunk-9shz0bw1.js";
5
5
  export {
6
6
  spawnProcess,
7
7
  sleep
@@ -9,10 +9,10 @@ import"../chunk-gm4swndx.js";
9
9
  import"../chunk-5tbzf9wd.js";
10
10
  import"../chunk-rkt41za2.js";
11
11
  import"../chunk-h8fwx0k7.js";
12
- import"../chunk-wv4jwhvj.js";
13
- import"../chunk-631vce5z.js";
14
- import"../chunk-hmah9t8e.js";
15
- import"../chunk-mn6dwsvh.js";
12
+ import"../chunk-fqrknvr8.js";
13
+ import"../chunk-nftzckdy.js";
14
+ import"../chunk-rq5fc007.js";
15
+ import"../chunk-9shz0bw1.js";
16
16
  import"../chunk-ssj93brx.js";
17
17
  export {
18
18
  parseRedisInfo,
@@ -15,10 +15,10 @@ import {
15
15
  } from "../chunk-5tbzf9wd.js";
16
16
  import"../chunk-rkt41za2.js";
17
17
  import"../chunk-h8fwx0k7.js";
18
- import"../chunk-wv4jwhvj.js";
19
- import"../chunk-631vce5z.js";
20
- import"../chunk-hmah9t8e.js";
21
- import"../chunk-mn6dwsvh.js";
18
+ import"../chunk-fqrknvr8.js";
19
+ import"../chunk-nftzckdy.js";
20
+ import"../chunk-rq5fc007.js";
21
+ import"../chunk-9shz0bw1.js";
22
22
  import"../chunk-ssj93brx.js";
23
23
  export {
24
24
  redisGroupedSampleSizes,
@@ -7,10 +7,10 @@ import"../chunk-zp1s833x.js";
7
7
  import"../chunk-v3hxvnrc.js";
8
8
  import"../chunk-x4ntb898.js";
9
9
  import"../chunk-h8fwx0k7.js";
10
- import"../chunk-wv4jwhvj.js";
11
- import"../chunk-631vce5z.js";
12
- import"../chunk-hmah9t8e.js";
13
- import"../chunk-mn6dwsvh.js";
10
+ import"../chunk-fqrknvr8.js";
11
+ import"../chunk-nftzckdy.js";
12
+ import"../chunk-rq5fc007.js";
13
+ import"../chunk-9shz0bw1.js";
14
14
  import"../chunk-ssj93brx.js";
15
15
  export {
16
16
  S3DataSource
package/dist/s3/index.js CHANGED
@@ -9,10 +9,10 @@ import {
9
9
  import"../chunk-v3hxvnrc.js";
10
10
  import"../chunk-x4ntb898.js";
11
11
  import"../chunk-h8fwx0k7.js";
12
- import"../chunk-wv4jwhvj.js";
13
- import"../chunk-631vce5z.js";
14
- import"../chunk-hmah9t8e.js";
15
- import"../chunk-mn6dwsvh.js";
12
+ import"../chunk-fqrknvr8.js";
13
+ import"../chunk-nftzckdy.js";
14
+ import"../chunk-rq5fc007.js";
15
+ import"../chunk-9shz0bw1.js";
16
16
  import"../chunk-ssj93brx.js";
17
17
  export {
18
18
  S3DataSource,
@@ -6,10 +6,10 @@ import {
6
6
  } from "../chunk-h8fwx0k7.js";
7
7
  import {
8
8
  PodRelayTransport
9
- } from "../chunk-wv4jwhvj.js";
10
- import"../chunk-631vce5z.js";
11
- import"../chunk-hmah9t8e.js";
12
- import"../chunk-mn6dwsvh.js";
9
+ } from "../chunk-fqrknvr8.js";
10
+ import"../chunk-nftzckdy.js";
11
+ import"../chunk-rq5fc007.js";
12
+ import"../chunk-9shz0bw1.js";
13
13
  import"../chunk-ssj93brx.js";
14
14
  export {
15
15
  isConnectionNetworkError,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  PodRelayTransport
3
- } from "../chunk-wv4jwhvj.js";
4
- import"../chunk-631vce5z.js";
5
- import"../chunk-hmah9t8e.js";
6
- import"../chunk-mn6dwsvh.js";
3
+ } from "../chunk-fqrknvr8.js";
4
+ import"../chunk-nftzckdy.js";
5
+ import"../chunk-rq5fc007.js";
6
+ import"../chunk-9shz0bw1.js";
7
7
  import"../chunk-ssj93brx.js";
8
8
  export {
9
9
  PodRelayTransport
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compforge/harness-toolbox",
3
- "version": "0.4.5",
3
+ "version": "0.4.7",
4
4
  "description": "Shared infrastructure clients, transports and bounded data capture",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -116,9 +116,6 @@
116
116
  "@types/node": "^22",
117
117
  "@types/ws": "^8.18.1"
118
118
  },
119
- "overrides": {
120
- "@compforge/harness-common": "file:../common"
121
- },
122
119
  "publishConfig": {
123
120
  "access": "public"
124
121
  },