qyl-mcp-server 0.1.0

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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +41 -0
  3. package/dist/atomic-json-store.d.ts +37 -0
  4. package/dist/atomic-json-store.js +143 -0
  5. package/dist/atomic-json-store.js.map +1 -0
  6. package/dist/ci.d.ts +51 -0
  7. package/dist/ci.js +158 -0
  8. package/dist/ci.js.map +1 -0
  9. package/dist/collector.d.ts +43 -0
  10. package/dist/collector.js +163 -0
  11. package/dist/collector.js.map +1 -0
  12. package/dist/config.d.ts +14 -0
  13. package/dist/config.js +39 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/contract-validation.d.ts +146 -0
  16. package/dist/contract-validation.js +350 -0
  17. package/dist/contract-validation.js.map +1 -0
  18. package/dist/data.d.ts +46 -0
  19. package/dist/data.js +138 -0
  20. package/dist/data.js.map +1 -0
  21. package/dist/demo.d.ts +23 -0
  22. package/dist/demo.js +836 -0
  23. package/dist/demo.js.map +1 -0
  24. package/dist/execution-evidence.d.ts +13 -0
  25. package/dist/execution-evidence.js +81 -0
  26. package/dist/execution-evidence.js.map +1 -0
  27. package/dist/execution-result.d.ts +5 -0
  28. package/dist/execution-result.js +17 -0
  29. package/dist/execution-result.js.map +1 -0
  30. package/dist/http-security.d.ts +36 -0
  31. package/dist/http-security.js +101 -0
  32. package/dist/http-security.js.map +1 -0
  33. package/dist/log-body.d.ts +3 -0
  34. package/dist/log-body.js +12 -0
  35. package/dist/log-body.js.map +1 -0
  36. package/dist/main.d.ts +51 -0
  37. package/dist/main.js +215 -0
  38. package/dist/main.js.map +1 -0
  39. package/dist/mcp-app.html +218 -0
  40. package/dist/mcp-dashboard.html +223 -0
  41. package/dist/mcp-errors.d.ts +5 -0
  42. package/dist/mcp-errors.js +15 -0
  43. package/dist/mcp-errors.js.map +1 -0
  44. package/dist/mcp-semconv.d.ts +68 -0
  45. package/dist/mcp-semconv.js +208 -0
  46. package/dist/mcp-semconv.js.map +1 -0
  47. package/dist/native-execution.d.ts +132 -0
  48. package/dist/native-execution.js +508 -0
  49. package/dist/native-execution.js.map +1 -0
  50. package/dist/observability-suppression.d.ts +8 -0
  51. package/dist/observability-suppression.js +15 -0
  52. package/dist/observability-suppression.js.map +1 -0
  53. package/dist/secret-redactor.d.ts +30 -0
  54. package/dist/secret-redactor.js +255 -0
  55. package/dist/secret-redactor.js.map +1 -0
  56. package/dist/server.d.ts +25 -0
  57. package/dist/server.js +207 -0
  58. package/dist/server.js.map +1 -0
  59. package/dist/stats.d.ts +18 -0
  60. package/dist/stats.js +141 -0
  61. package/dist/stats.js.map +1 -0
  62. package/dist/summaries.d.ts +14 -0
  63. package/dist/summaries.js +128 -0
  64. package/dist/summaries.js.map +1 -0
  65. package/dist/telemetry-redaction.d.ts +6 -0
  66. package/dist/telemetry-redaction.js +28 -0
  67. package/dist/telemetry-redaction.js.map +1 -0
  68. package/dist/telemetry.d.ts +72 -0
  69. package/dist/telemetry.js +362 -0
  70. package/dist/telemetry.js.map +1 -0
  71. package/dist/tools.d.ts +17 -0
  72. package/dist/tools.js +111 -0
  73. package/dist/tools.js.map +1 -0
  74. package/dist/wire.d.ts +10 -0
  75. package/dist/wire.js +7 -0
  76. package/dist/wire.js.map +1 -0
  77. package/package.json +91 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 ancplua
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # qyl-mcp-server
2
+
3
+ qyl telemetry MCP server: trace explorer, MCP dashboard, log search, and CI-run
4
+ inspection for a live [qyl](https://github.com/ANcpLua/qyl) collector — or an
5
+ explicit, visibly labelled demo mode.
6
+
7
+ ```bash
8
+ npx qyl-mcp-server --stdio # stdio MCP server
9
+ npx qyl-mcp-server # Streamable HTTP on loopback
10
+ ```
11
+
12
+ Works standalone with any MCP client, and composes with the qyl local stack —
13
+ `qyl up --mcp-stdio npx qyl-mcp-server --stdio` supervises it next to the
14
+ collector with reads and OTLP export pre-wired.
15
+
16
+ ## Tools
17
+
18
+ `fetch_telemetry`, `list_traces`, `get_trace`, `list_sessions`, `search_logs`,
19
+ `display_traces`, `display_mcp_dashboard`, `ci_log` — all published with
20
+ read-only safety annotations. The two `display_*` tools return MCP Apps UI
21
+ resources (single-file viewers).
22
+
23
+ Every inbound `tools/call` is recorded natively: validated result, lifecycle,
24
+ duration, redacted JSON-RPC timeline, and trace/span correlation are persisted
25
+ atomically to `~/.qyl/mcp-native-executions.json`.
26
+
27
+ ## Configuration
28
+
29
+ | Variable | Meaning |
30
+ | --- | --- |
31
+ | `QYL_COLLECTOR_URL` | qyl read API base; default `http://127.0.0.1:5100`. Also the OTLP base when set. |
32
+ | `QYL_API_KEY` | Collector read and OTLP credential. |
33
+ | `QYL_OTLP_ENDPOINT` | Optional OTLP base for self-telemetry. |
34
+ | `QYL_DEMO=1` | Explicit generated demo telemetry. Collector failure never silently substitutes demo data. |
35
+ | `QYL_MCP_TELEMETRY=0` | Disable MCP spans and duration metrics. |
36
+ | `QYL_MCP_NATIVE_STATE_PATH` | Override the native execution-evidence path. |
37
+
38
+ Secrets are redacted before results reach the model, structured content, or
39
+ durable evidence.
40
+
41
+ Full documentation: [github.com/ANcpLua/qyl.mcp](https://github.com/ANcpLua/qyl.mcp)
@@ -0,0 +1,37 @@
1
+ export type PersistenceErrorKind = "invalid_json" | "invalid_state" | "write_failed";
2
+ export declare class PersistenceError extends Error {
3
+ readonly kind: PersistenceErrorKind;
4
+ constructor(kind: PersistenceErrorKind, message: string, options?: ErrorOptions);
5
+ }
6
+ export interface AtomicJsonStoreOptions<T> {
7
+ initial: () => T;
8
+ /** Validates untrusted data loaded from disk and returns its normalized representation. */
9
+ parse: (value: unknown) => T;
10
+ /** Redacts or rejects sensitive state before it can reach disk. */
11
+ prepareForWrite: (value: T) => T;
12
+ }
13
+ /**
14
+ * A single-process, serialized JSON store with restrictive permissions and atomic replacement.
15
+ * Domain services remain responsible for workspace scoping; this class guarantees that a failed
16
+ * validation or write never replaces the last known-good document.
17
+ */
18
+ export declare class AtomicJsonStore<T> {
19
+ private readonly filePath;
20
+ private readonly options;
21
+ private state;
22
+ private initialization;
23
+ private tail;
24
+ constructor(filePath: string, options: AtomicJsonStoreOptions<T>);
25
+ initialize(): Promise<void>;
26
+ read(): Promise<T>;
27
+ replace(value: T): Promise<T>;
28
+ transact<R>(mutate: (draft: T) => R | Promise<R>): Promise<{
29
+ state: T;
30
+ result: R;
31
+ }>;
32
+ private load;
33
+ private commit;
34
+ private writePrepared;
35
+ private enqueue;
36
+ private requireState;
37
+ }
@@ -0,0 +1,143 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { constants } from "node:fs";
3
+ import { chmod, mkdir, open, readFile, rename, rm } from "node:fs/promises";
4
+ import { dirname } from "node:path";
5
+ export class PersistenceError extends Error {
6
+ kind;
7
+ constructor(kind, message, options) {
8
+ super(message, options);
9
+ this.kind = kind;
10
+ this.name = "PersistenceError";
11
+ }
12
+ }
13
+ /**
14
+ * A single-process, serialized JSON store with restrictive permissions and atomic replacement.
15
+ * Domain services remain responsible for workspace scoping; this class guarantees that a failed
16
+ * validation or write never replaces the last known-good document.
17
+ */
18
+ export class AtomicJsonStore {
19
+ filePath;
20
+ options;
21
+ state;
22
+ initialization;
23
+ tail = Promise.resolve();
24
+ constructor(filePath, options) {
25
+ this.filePath = filePath;
26
+ this.options = options;
27
+ }
28
+ async initialize() {
29
+ this.initialization ??= this.load();
30
+ return this.initialization;
31
+ }
32
+ async read() {
33
+ await this.initialize();
34
+ // Reads participate in the same happens-before order as writes. This is
35
+ // required for deletion guards and idempotency lookups: returning the
36
+ // cached document while an earlier transaction is still pending can
37
+ // expose stale ownership or active-work state.
38
+ await this.tail;
39
+ return clone(this.requireState());
40
+ }
41
+ async replace(value) {
42
+ return this.enqueue(async () => this.commit(value));
43
+ }
44
+ async transact(mutate) {
45
+ return this.enqueue(async () => {
46
+ const draft = clone(this.requireState());
47
+ const result = await mutate(draft);
48
+ const state = await this.commit(draft);
49
+ return { state, result };
50
+ });
51
+ }
52
+ async load() {
53
+ let text;
54
+ try {
55
+ text = await readFile(this.filePath, "utf8");
56
+ }
57
+ catch (error) {
58
+ if (isNodeError(error, "ENOENT")) {
59
+ this.state = await this.writePrepared(this.options.initial());
60
+ return;
61
+ }
62
+ throw error;
63
+ }
64
+ let parsed;
65
+ try {
66
+ parsed = JSON.parse(text);
67
+ }
68
+ catch (error) {
69
+ throw new PersistenceError("invalid_json", `Persisted qyl.mcp state at '${this.filePath}' is not valid JSON.`, { cause: error });
70
+ }
71
+ try {
72
+ this.state = clone(this.options.parse(parsed));
73
+ }
74
+ catch (error) {
75
+ throw new PersistenceError("invalid_state", `Persisted qyl.mcp state at '${this.filePath}' does not satisfy the current schema.`, { cause: error });
76
+ }
77
+ }
78
+ async commit(value) {
79
+ await this.initialize();
80
+ const normalized = await this.writePrepared(value);
81
+ this.state = normalized;
82
+ return clone(normalized);
83
+ }
84
+ async writePrepared(value) {
85
+ let normalized;
86
+ try {
87
+ const prepared = this.options.prepareForWrite(clone(value));
88
+ normalized = this.options.parse(prepared);
89
+ }
90
+ catch (error) {
91
+ throw new PersistenceError("invalid_state", "qyl.mcp refused to persist state that is invalid or contains unsupported sensitive data.", { cause: error });
92
+ }
93
+ const json = JSON.stringify(normalized, null, 2);
94
+ if (json === undefined) {
95
+ throw new PersistenceError("invalid_state", "qyl.mcp state cannot be represented as JSON.");
96
+ }
97
+ try {
98
+ await writeAtomically(this.filePath, `${json}\n`);
99
+ }
100
+ catch (error) {
101
+ throw new PersistenceError("write_failed", `qyl.mcp could not persist state at '${this.filePath}'.`, { cause: error });
102
+ }
103
+ return clone(normalized);
104
+ }
105
+ enqueue(operation) {
106
+ const queued = this.tail.then(operation, operation);
107
+ this.tail = queued.then(() => undefined, () => undefined);
108
+ return queued;
109
+ }
110
+ requireState() {
111
+ if (this.state === undefined) {
112
+ throw new Error("AtomicJsonStore must be initialized before accessing state.");
113
+ }
114
+ return this.state;
115
+ }
116
+ }
117
+ async function writeAtomically(filePath, contents) {
118
+ const directory = dirname(filePath);
119
+ await mkdir(directory, { recursive: true, mode: 0o700 });
120
+ const temporaryPath = `${filePath}.${randomUUID()}.tmp`;
121
+ const handle = await open(temporaryPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY, 0o600);
122
+ let renamed = false;
123
+ try {
124
+ await handle.writeFile(contents, "utf8");
125
+ await handle.sync();
126
+ await handle.close();
127
+ await rename(temporaryPath, filePath);
128
+ renamed = true;
129
+ await chmod(filePath, 0o600);
130
+ }
131
+ finally {
132
+ await handle.close().catch(() => undefined);
133
+ if (!renamed)
134
+ await rm(temporaryPath, { force: true }).catch(() => undefined);
135
+ }
136
+ }
137
+ function clone(value) {
138
+ return structuredClone(value);
139
+ }
140
+ function isNodeError(error, code) {
141
+ return error instanceof Error && "code" in error && error.code === code;
142
+ }
143
+ //# sourceMappingURL=atomic-json-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic-json-store.js","sourceRoot":"","sources":["../src/atomic-json-store.ts"],"names":[],"mappings":"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"}
package/dist/ci.d.ts ADDED
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Qyl's CI dogfooding block (the fourth tool block next to traces, sessions,
3
+ * and logs): answers "which CI leg hung on what" from qyl's OWN telemetry
4
+ * instead of wrapping the GitHub API.
5
+ *
6
+ * Emitter convention (what CI runs must send to appear here):
7
+ * - resource `service.name` starts with "qyl-ci" (e.g. "qyl-ci-smoke"),
8
+ * - `session.id` identifies one workflow run (e.g. "nuget-publish-<run_id>"),
9
+ * - one span per phase, named after the phase, carrying a `ci.leg` string
10
+ * attribute (e.g. "macos-latest"); a failed phase sets span status error.
11
+ *
12
+ * The input/output schemas are deliberately inline zod, not
13
+ * publishedContractSchema: this is an operational view over already-published
14
+ * OTel contract data, not a new wire contract. If it graduates, it moves to
15
+ * qyl-api-schema first.
16
+ */
17
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
18
+ import { z } from "zod";
19
+ import type { Mode, QylSession, QylTrace } from "./wire.js";
20
+ /** Resource service-name prefix that marks telemetry as CI-emitted. */
21
+ export declare const CI_SERVICE_PREFIX = "qyl-ci";
22
+ declare const CiRunSummarySchema: z.ZodObject<{
23
+ run_id: z.ZodString;
24
+ state: z.ZodString;
25
+ start_time: z.ZodString;
26
+ duration_ms: z.ZodOptional<z.ZodNumber>;
27
+ error_count: z.ZodNumber;
28
+ services: z.ZodArray<z.ZodString>;
29
+ }, z.core.$strip>;
30
+ declare const CiPhaseSchema: z.ZodObject<{
31
+ leg: z.ZodString;
32
+ phase: z.ZodString;
33
+ status: z.ZodEnum<{
34
+ error: "error";
35
+ ok: "ok";
36
+ unset: "unset";
37
+ }>;
38
+ duration_ms: z.ZodNumber;
39
+ message: z.ZodOptional<z.ZodString>;
40
+ }, z.core.$strip>;
41
+ type CiRunSummary = z.infer<typeof CiRunSummarySchema>;
42
+ type CiPhase = z.infer<typeof CiPhaseSchema>;
43
+ /** CI sessions are the ones that carry at least one qyl-ci service. */
44
+ export declare function filterCiSessions(sessions: QylSession[]): QylSession[];
45
+ /** Flatten a run's traces into per-leg phases, failures first. */
46
+ export declare function collectCiPhases(traces: QylTrace[]): CiPhase[];
47
+ export declare function summarizeCiRuns(runs: CiRunSummary[], mode: Mode): string;
48
+ export declare function summarizeCiRun(runId: string, phases: CiPhase[], mode: Mode): string;
49
+ /** Register the CI dogfooding block. */
50
+ export declare function registerCiTools(server: McpServer): void;
51
+ export {};
package/dist/ci.js ADDED
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Qyl's CI dogfooding block (the fourth tool block next to traces, sessions,
3
+ * and logs): answers "which CI leg hung on what" from qyl's OWN telemetry
4
+ * instead of wrapping the GitHub API.
5
+ *
6
+ * Emitter convention (what CI runs must send to appear here):
7
+ * - resource `service.name` starts with "qyl-ci" (e.g. "qyl-ci-smoke"),
8
+ * - `session.id` identifies one workflow run (e.g. "nuget-publish-<run_id>"),
9
+ * - one span per phase, named after the phase, carrying a `ci.leg` string
10
+ * attribute (e.g. "macos-latest"); a failed phase sets span status error.
11
+ *
12
+ * The input/output schemas are deliberately inline zod, not
13
+ * publishedContractSchema: this is an operational view over already-published
14
+ * OTel contract data, not a new wire contract. If it graduates, it moves to
15
+ * qyl-api-schema first.
16
+ */
17
+ import { z } from "zod";
18
+ import { fetchSessions, fetchSessionTraces } from "./data.js";
19
+ import { telemetryToolResult } from "./telemetry-redaction.js";
20
+ import { READ_ONLY_TELEMETRY_TOOL_ANNOTATIONS, toolError } from "./tools.js";
21
+ /** Resource service-name prefix that marks telemetry as CI-emitted. */
22
+ export const CI_SERVICE_PREFIX = "qyl-ci";
23
+ const CiLogInputSchema = z.object({
24
+ run_id: z
25
+ .string()
26
+ .min(1)
27
+ .optional()
28
+ .describe("Session id of one CI run for a per-leg phase breakdown; omit to list recent runs."),
29
+ limit: z
30
+ .number()
31
+ .int()
32
+ .min(1)
33
+ .max(50)
34
+ .optional()
35
+ .describe("Maximum CI runs to list (default 10)."),
36
+ });
37
+ const CiRunSummarySchema = z.object({
38
+ run_id: z.string(),
39
+ state: z.string(),
40
+ start_time: z.string(),
41
+ duration_ms: z.number().optional(),
42
+ error_count: z.number(),
43
+ services: z.array(z.string()),
44
+ });
45
+ const CiPhaseSchema = z.object({
46
+ leg: z.string(),
47
+ phase: z.string(),
48
+ status: z.enum(["ok", "error", "unset"]),
49
+ duration_ms: z.number(),
50
+ message: z.string().optional(),
51
+ });
52
+ const CiLogOutputSchema = z.object({
53
+ runs: z.array(CiRunSummarySchema).optional(),
54
+ run_id: z.string().optional(),
55
+ phases: z.array(CiPhaseSchema).optional(),
56
+ mode: z.enum(["live", "demo"]),
57
+ });
58
+ /** CI sessions are the ones that carry at least one qyl-ci service. */
59
+ export function filterCiSessions(sessions) {
60
+ return sessions.filter((session) => session.services.some((service) => service.startsWith(CI_SERVICE_PREFIX)));
61
+ }
62
+ function spanLeg(span) {
63
+ const attribute = span.attributes?.find((entry) => entry.key === "ci.leg");
64
+ return typeof attribute?.value === "string"
65
+ ? attribute.value
66
+ : span.resource["service.name"];
67
+ }
68
+ /** Flatten a run's traces into per-leg phases, failures first. */
69
+ export function collectCiPhases(traces) {
70
+ const phases = traces.flatMap((trace) => trace.spans.map((span) => ({
71
+ leg: spanLeg(span),
72
+ phase: span.name,
73
+ status: span.status.code === 2 ? "error" : span.status.code === 1 ? "ok" : "unset",
74
+ duration_ms: Math.max(0, Math.round((span.end_time_unix_nano - span.start_time_unix_nano) / 1_000_000)),
75
+ ...(span.status.message ? { message: span.status.message } : {}),
76
+ })));
77
+ return phases.sort((a, b) => a.status === b.status
78
+ ? a.leg.localeCompare(b.leg) || a.phase.localeCompare(b.phase)
79
+ : a.status === "error"
80
+ ? -1
81
+ : b.status === "error"
82
+ ? 1
83
+ : 0);
84
+ }
85
+ export function summarizeCiRuns(runs, mode) {
86
+ if (runs.length === 0) {
87
+ return `No CI runs found (${mode} mode). CI telemetry appears once runs emit ` +
88
+ `spans with a '${CI_SERVICE_PREFIX}*' service.name.`;
89
+ }
90
+ const lines = runs.map((run) => {
91
+ const failure = run.error_count > 0 ? `${run.error_count} error(s)` : "clean";
92
+ const duration = run.duration_ms === undefined ? "?" : `${Math.round(run.duration_ms / 1000)}s`;
93
+ return `- ${run.run_id} [${run.state}] ${run.start_time} ${duration} — ${failure}`;
94
+ });
95
+ return `${runs.length} CI run(s) (${mode} mode), pass a run_id for the per-leg breakdown:\n${lines.join("\n")}`;
96
+ }
97
+ export function summarizeCiRun(runId, phases, mode) {
98
+ if (phases.length === 0) {
99
+ return `CI run ${runId} has no phase spans (${mode} mode).`;
100
+ }
101
+ const legs = new Map();
102
+ for (const phase of phases) {
103
+ const existing = legs.get(phase.leg);
104
+ if (existing)
105
+ existing.push(phase);
106
+ else
107
+ legs.set(phase.leg, [phase]);
108
+ }
109
+ const lines = [];
110
+ for (const [leg, legPhases] of legs) {
111
+ const failed = legPhases.filter((phase) => phase.status === "error");
112
+ lines.push(`${failed.length > 0 ? "✗" : "✓"} ${leg}`);
113
+ for (const phase of failed.length > 0 ? failed : legPhases) {
114
+ const detail = phase.message ? ` — ${phase.message}` : "";
115
+ lines.push(` ${phase.status === "error" ? "✗" : "·"} ${phase.phase} (${phase.duration_ms}ms)${detail}`);
116
+ }
117
+ }
118
+ return `CI run ${runId} (${mode} mode):\n${lines.join("\n")}`;
119
+ }
120
+ /** Register the CI dogfooding block. */
121
+ export function registerCiTools(server) {
122
+ server.registerTool("ci_log", {
123
+ title: "CI Log",
124
+ description: "Read qyl's own CI runs from its telemetry (dogfooding — no GitHub API). " +
125
+ "Without arguments: recent CI runs (sessions whose service.name starts with " +
126
+ `'${CI_SERVICE_PREFIX}'). With run_id: per-leg phase breakdown, failures first, ` +
127
+ "so 'which leg hung on what' is answerable even when GitHub's log API is down.",
128
+ inputSchema: CiLogInputSchema.shape,
129
+ outputSchema: CiLogOutputSchema.shape,
130
+ annotations: READ_ONLY_TELEMETRY_TOOL_ANNOTATIONS,
131
+ }, async (args) => {
132
+ try {
133
+ if (args.run_id) {
134
+ const { traces, mode } = await fetchSessionTraces(args.run_id, 100);
135
+ const phases = collectCiPhases(traces);
136
+ const output = { run_id: args.run_id, phases, mode };
137
+ return telemetryToolResult(summarizeCiRun(args.run_id, phases, mode), output);
138
+ }
139
+ const { sessions, mode } = await fetchSessions(50, undefined);
140
+ const runs = filterCiSessions(sessions)
141
+ .slice(0, args.limit ?? 10)
142
+ .map((session) => ({
143
+ run_id: session["session.id"],
144
+ state: session.state,
145
+ start_time: session.start_time,
146
+ ...(session.duration_ms === undefined ? {} : { duration_ms: session.duration_ms }),
147
+ error_count: session.error_count,
148
+ services: session.services,
149
+ }));
150
+ const output = { runs, mode };
151
+ return telemetryToolResult(summarizeCiRuns(runs, mode), output);
152
+ }
153
+ catch (err) {
154
+ return toolError(err);
155
+ }
156
+ });
157
+ }
158
+ //# sourceMappingURL=ci.js.map
package/dist/ci.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci.js","sourceRoot":"","sources":["../src/ci.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,oCAAoC,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG7E,uEAAuE;AACvE,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AAE1C,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CAAC,mFAAmF,CAAC;IAChG,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,QAAQ,EAAE;SACV,QAAQ,CAAC,uCAAuC,CAAC;CACrD,CAAC,CAAC;AAEH,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;CAC9B,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACxC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,QAAQ,EAAE;IAC5C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE;IACzC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,CAAC,CAAC;AAOH,uEAAuE;AACvE,MAAM,UAAU,gBAAgB,CAAC,QAAsB;IACrD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAC1E,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,IAAa;IAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC;IAC3E,OAAO,OAAO,SAAS,EAAE,KAAK,KAAK,QAAQ;QACzC,CAAC,CAAC,SAAS,CAAC,KAAK;QACjB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;AACpC,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,eAAe,CAAC,MAAkB;IAChD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CACtC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAW,EAAE,CAAC,CAAC;QAClC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC;QAClB,KAAK,EAAE,IAAI,CAAC,IAAI;QAChB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO;QAClF,WAAW,EAAE,IAAI,CAAC,GAAG,CACnB,CAAC,EACD,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,SAAS,CAAC,CAC9E;QACD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjE,CAAC,CAAC,CACJ,CAAC;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC1B,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QACnB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC;QAC9D,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO;YACpB,CAAC,CAAC,CAAC,CAAC;YACJ,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO;gBACpB,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC,CAAC,CACV,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAoB,EAAE,IAAU;IAC9D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,qBAAqB,IAAI,8CAA8C;YAC5E,iBAAiB,iBAAiB,kBAAkB,CAAC;IACzD,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QAC7B,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,WAAW,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;QAC9E,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC;QAChG,OAAO,KAAK,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,UAAU,IAAI,QAAQ,MAAM,OAAO,EAAE,CAAC;IACrF,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,IAAI,CAAC,MAAM,eAAe,IAAI,qDAAqD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAClH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,MAAiB,EAAE,IAAU;IACzE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,UAAU,KAAK,wBAAwB,IAAI,SAAS,CAAC;IAC9D,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC1C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,QAAQ;YAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;;YAC9B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC;QACrE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC;QACtD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;YAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,WAAW,MAAM,MAAM,EAAE,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;IACD,OAAO,UAAU,KAAK,KAAK,IAAI,YAAY,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAChE,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,eAAe,CAAC,MAAiB;IAC/C,MAAM,CAAC,YAAY,CACjB,QAAQ,EACR;QACE,KAAK,EAAE,QAAQ;QACf,WAAW,EACT,0EAA0E;YAC1E,6EAA6E;YAC7E,IAAI,iBAAiB,4DAA4D;YACjF,+EAA+E;QACjF,WAAW,EAAE,gBAAgB,CAAC,KAAK;QACnC,YAAY,EAAE,iBAAiB,CAAC,KAAK;QACrC,WAAW,EAAE,oCAAoC;KAClD,EACD,KAAK,EAAE,IAAgB,EAA2B,EAAE;QAClD,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;gBACpE,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;gBACvC,MAAM,MAAM,GAAgB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;gBAClE,OAAO,mBAAmB,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;YAChF,CAAC;YACD,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,aAAa,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;YAC9D,MAAM,IAAI,GAAG,gBAAgB,CAAC,QAAQ,CAAC;iBACpC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;iBAC1B,GAAG,CAAC,CAAC,OAAO,EAAgB,EAAE,CAAC,CAAC;gBAC/B,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC;gBAC7B,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;gBAClF,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;aAC3B,CAAC,CAAC,CAAC;YACN,MAAM,MAAM,GAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAC3C,OAAO,mBAAmB,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;QAClE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Collector REST client + live/demo mode selection.
3
+ *
4
+ * QYL_DEMO=1 selects explicit demo mode. Every other invocation is live;
5
+ * connection, HTTP, JSON, and contract failures surface to the caller rather
6
+ * than silently substituting generated telemetry or invented defaults.
7
+ */
8
+ import type { LogRecord, SessionEntity, Trace } from "@ancplua/qyl-api-schema/types";
9
+ import { z } from "zod";
10
+ import type { Mode } from "./wire.js";
11
+ /** Error with a message already suitable for showing to the model/user. */
12
+ export declare class CollectorError extends Error {
13
+ readonly connectionError: boolean;
14
+ readonly status?: number | undefined;
15
+ constructor(message: string, connectionError?: boolean, status?: number | undefined);
16
+ }
17
+ /** Normalize RFC 3339 spelling, then enforce the public Trace schema exactly. */
18
+ export declare function parseCollectorTrace(value: unknown, context?: string): Trace;
19
+ /** Normalize RFC 3339 spelling, then enforce the public Session schema exactly. */
20
+ export declare function parseCollectorSession(value: unknown, context?: string): SessionEntity;
21
+ /** Enforce the public LogRecord schema without alternate wire encodings. */
22
+ export declare function parseCollectorLog(value: unknown, context?: string): LogRecord;
23
+ interface ParsedCollectorPage<T> {
24
+ items: T[];
25
+ hasMore: boolean;
26
+ }
27
+ /**
28
+ * Normalize endpoint items, then validate the complete operation-specific
29
+ * response body. The supplied schema must be an Operations.*.Response.200
30
+ * definition from the generated contract.
31
+ */
32
+ export declare function parseCollectorPage<T, TPage extends {
33
+ items: T[];
34
+ has_more: boolean;
35
+ }>(value: unknown, context: string, pageSchema: z.ZodType<TPage>, parseItem: (item: unknown, context: string) => T): ParsedCollectorPage<T>;
36
+ /**
37
+ * GET a collector endpoint. Query params are camelCase per the collector API;
38
+ * `undefined` values are omitted. All response data remains unknown until the
39
+ * endpoint-specific generated contract parser accepts it.
40
+ */
41
+ export declare function collectorGet(pathname: string, params?: Record<string, string | number | boolean | undefined>): Promise<unknown>;
42
+ export declare function resolveMode(): Promise<Mode>;
43
+ export {};