@kici-dev/compiler 0.1.16 → 0.1.18

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 (138) hide show
  1. package/dist/auth/headless-detect.js +1 -1
  2. package/dist/cli-banner.js +1 -1
  3. package/dist/cli.js +56 -19
  4. package/dist/commands/approve.js +1 -1
  5. package/dist/commands/compile.js +19 -17
  6. package/dist/commands/diagnostics.d.ts +7 -0
  7. package/dist/commands/diagnostics.js +58 -0
  8. package/dist/commands/docs.js +1 -1
  9. package/dist/commands/drain-worker.js +1 -1
  10. package/dist/commands/endpoints.js +1 -1
  11. package/dist/commands/fixture.js +1 -1
  12. package/dist/commands/held-run-client.js +1 -1
  13. package/dist/commands/held-run-resolve.js +1 -1
  14. package/dist/commands/hook.js +1 -1
  15. package/dist/commands/index.d.ts +16 -4
  16. package/dist/commands/index.js +10 -4
  17. package/dist/commands/init.js +2 -2
  18. package/dist/commands/login.d.ts +0 -2
  19. package/dist/commands/login.js +1 -3
  20. package/dist/commands/logout.js +1 -1
  21. package/dist/commands/orchestrators.d.ts +25 -0
  22. package/dist/commands/orchestrators.js +115 -0
  23. package/dist/commands/org.js +1 -1
  24. package/dist/commands/reject.js +1 -1
  25. package/dist/commands/run.d.ts +2 -9
  26. package/dist/commands/run.js +256 -315
  27. package/dist/commands/runs/cancel.d.ts +6 -0
  28. package/dist/commands/runs/cancel.js +32 -0
  29. package/dist/commands/runs/list.d.ts +6 -0
  30. package/dist/commands/runs/list.js +49 -0
  31. package/dist/commands/runs/logs.d.ts +7 -0
  32. package/dist/commands/runs/logs.js +67 -0
  33. package/dist/commands/runs/rerun.d.ts +5 -0
  34. package/dist/commands/runs/rerun.js +21 -0
  35. package/dist/commands/runs/show.d.ts +5 -0
  36. package/dist/commands/runs/show.js +65 -0
  37. package/dist/commands/secrets-list.d.ts +7 -9
  38. package/dist/commands/secrets-list.js +40 -64
  39. package/dist/commands/test.d.ts +4 -0
  40. package/dist/commands/test.js +4 -6
  41. package/dist/commands/types.d.ts +3 -5
  42. package/dist/commands/types.js +13 -37
  43. package/dist/commands/verify-attestation.d.ts +12 -0
  44. package/dist/commands/verify-attestation.js +69 -0
  45. package/dist/commands/watch.js +1 -1
  46. package/dist/commands/workflows.js +14 -34
  47. package/dist/errors/capability-gap.js +1 -1
  48. package/dist/errors/formatter.js +1 -1
  49. package/dist/errors/index.js +1 -1
  50. package/dist/execution/executor.js +1 -1
  51. package/dist/execution/index.js +1 -1
  52. package/dist/execution/sdk-alias.js +1 -1
  53. package/dist/execution/ts-loader.js +1 -1
  54. package/dist/fixtures/compiler.js +1 -1
  55. package/dist/fixtures/defaults/index.js +1 -1
  56. package/dist/format.js +1 -1
  57. package/dist/generators/secrets-dts.js +2 -2
  58. package/dist/hooks/detector.js +1 -1
  59. package/dist/hooks/index.js +1 -1
  60. package/dist/hooks/installer.js +1 -1
  61. package/dist/hooks/templates.js +1 -1
  62. package/dist/index.js +1 -1
  63. package/dist/llm-context/llms-full.txt +1549 -1282
  64. package/dist/llm-context/llms.txt +6 -2
  65. package/dist/local-executor/dag-scheduler.js +1 -1
  66. package/dist/local-executor/index.js +1 -1
  67. package/dist/local-executor/job-runner.js +40 -18
  68. package/dist/local-executor/materializer.js +1 -1
  69. package/dist/local-executor/output-streamer.js +1 -1
  70. package/dist/local-executor/payload-generator.js +1 -1
  71. package/dist/local-executor/picker.js +1 -1
  72. package/dist/local-executor/runs-on-display.d.ts +9 -0
  73. package/dist/local-executor/runs-on-display.js +23 -0
  74. package/dist/local-executor/secret-loader.js +1 -1
  75. package/dist/local-executor/to-event-payload.js +1 -1
  76. package/dist/local-executor/types.js +1 -1
  77. package/dist/local-executor/workflow-lock.js +0 -0
  78. package/dist/lockfile/generator.d.ts +9 -5
  79. package/dist/lockfile/generator.js +58 -38
  80. package/dist/lockfile/hash-files.js +1 -1
  81. package/dist/lockfile/hasher.js +1 -1
  82. package/dist/lockfile/index.js +1 -1
  83. package/dist/lockfile/purity-analyzer.js +1 -1
  84. package/dist/postinstall.js +1 -1
  85. package/dist/provenance-trust-root.d.ts +14 -0
  86. package/dist/provenance-trust-root.js +49 -0
  87. package/dist/remote/config.d.ts +6 -2
  88. package/dist/remote/config.js +7 -4
  89. package/dist/remote/dashboard-client.d.ts +92 -0
  90. package/dist/remote/dashboard-client.js +168 -0
  91. package/dist/remote/encryption.js +3 -4
  92. package/dist/remote/history.js +1 -1
  93. package/dist/remote/oauth.js +1 -1
  94. package/dist/remote/oidc-discovery.js +1 -1
  95. package/dist/remote/output/json.js +1 -1
  96. package/dist/remote/output/junit.js +1 -1
  97. package/dist/remote/output/streaming.js +1 -1
  98. package/dist/remote/output/summary.js +1 -1
  99. package/dist/remote/platform-client.d.ts +142 -0
  100. package/dist/remote/platform-client.js +187 -0
  101. package/dist/remote/prod-defaults.js +1 -1
  102. package/dist/remote/render.d.ts +11 -0
  103. package/dist/remote/render.js +48 -0
  104. package/dist/remote/secret-upload.js +1 -1
  105. package/dist/remote/uploader.d.ts +9 -0
  106. package/dist/remote/uploader.js +51 -4
  107. package/dist/templates/agents-md.d.ts +1 -1
  108. package/dist/templates/agents-md.js +8 -3
  109. package/dist/templates/index.js +1 -1
  110. package/dist/templates/package-json.js +4 -5
  111. package/dist/templates/tsconfig-json.js +1 -1
  112. package/dist/templates/workflows/hello-world.js +2 -2
  113. package/dist/templates/workflows/hello-world.ts +1 -1
  114. package/dist/templates/workflows/pr-checks.js +3 -3
  115. package/dist/templates/workflows/pr-checks.ts +2 -2
  116. package/dist/test-runner/dry-run.js +1 -1
  117. package/dist/test-runner/event-types.js +1 -1
  118. package/dist/test-runner/git-detector.js +1 -1
  119. package/dist/test-runner/index.js +1 -1
  120. package/dist/test-runner/job-executor.js +3 -2
  121. package/dist/test-runner/output-formatter.js +1 -1
  122. package/dist/test-runner/payload-builder.js +1 -1
  123. package/dist/test-runner/rule-evaluator.js +1 -1
  124. package/dist/test-runner/secrets-file.js +1 -1
  125. package/dist/test-runner/step-context.js +10 -6
  126. package/dist/types.d.ts +29 -8
  127. package/dist/types.js +2 -1
  128. package/dist/validation/index.js +1 -1
  129. package/dist/validation/validator.js +1 -1
  130. package/dist/workflows/hello-world.ts +1 -1
  131. package/dist/workflows/pr-checks.ts +2 -2
  132. package/package.json +10 -9
  133. package/sbom.spdx.json +465 -410
  134. package/dist/commands/cancel.js +0 -124
  135. package/dist/commands/status.js +0 -212
  136. package/dist/remote/client.js +0 -203
  137. package/dist/remote/observer.js +0 -174
  138. /package/dist/{chunk-gOLHoazu.js → chunk-BTugEXQM.js} +0 -0
@@ -1,124 +0,0 @@
1
- import "../chunk-gOLHoazu.js";
2
- import { loadGlobalConfig } from "../remote/config.js";
3
- import pc from "picocolors";
4
- import { logger, toErrorMessage } from "@kici-dev/core";
5
- //#region src/commands/cancel.ts
6
- /**
7
- * kici cancel command
8
- *
9
- * Cancels a specific run by ID, or all in-progress runs on a branch.
10
- * Uses the Platform dashboard API (PAT auth) or orchestrator API (direct mode).
11
- */
12
- /**
13
- * Cancel a run or all runs on a branch.
14
- *
15
- * @param runId - Run ID to cancel (optional if --branch is provided)
16
- * @param options - Cancel options
17
- * @returns true on success, false on error
18
- */
19
- async function cancelCommand(runId, options = {}) {
20
- try {
21
- const config = await loadGlobalConfig();
22
- const token = config.pat ?? config.token;
23
- if (!token) {
24
- logger.error(pc.red("Not authenticated. Run `kici login` to get started."));
25
- return false;
26
- }
27
- const endpoint = config.platformEndpoint ?? config.endpoint;
28
- if (!endpoint) {
29
- logger.error(pc.red("No endpoint configured. Run `kici login` to configure."));
30
- return false;
31
- }
32
- if (options.branch) return await cancelByBranch(endpoint, token, config.activeOrgId, options.branch);
33
- if (!runId) {
34
- logger.error(pc.red("Please provide a run ID or use --branch to cancel by branch."));
35
- return false;
36
- }
37
- return await cancelRun(endpoint, token, config.activeOrgId, runId, options.force ?? false);
38
- } catch (error) {
39
- const message = toErrorMessage(error);
40
- logger.error(pc.red(`Error: ${message}`));
41
- return false;
42
- }
43
- }
44
- /**
45
- * Cancel a specific run by ID.
46
- */
47
- async function cancelRun(endpoint, token, orgId, runId, force) {
48
- if (!orgId) {
49
- logger.error(pc.red("No active organization. Run `kici org use <name>` to set one."));
50
- return false;
51
- }
52
- const action = force ? "Force-cancelling" : "Cancelling";
53
- logger.info(`${action} run ${pc.cyan(runId)}...`);
54
- const url = `${endpoint}/api/v1/orgs/${orgId}/runs/${runId}/cancel`;
55
- const response = await fetch(url, {
56
- method: "POST",
57
- headers: {
58
- "Content-Type": "application/json",
59
- Authorization: `Bearer ${token}`
60
- },
61
- body: JSON.stringify({ force })
62
- });
63
- if (response.ok) {
64
- const jobs = (await response.json()).cancelledJobs ?? 0;
65
- logger.info(pc.green(`Run ${runId} cancelled (${jobs} job${jobs !== 1 ? "s" : ""} affected).`));
66
- return true;
67
- }
68
- return handleApiError(response, runId);
69
- }
70
- /**
71
- * Cancel all in-progress runs on a branch.
72
- */
73
- async function cancelByBranch(endpoint, token, orgId, branch) {
74
- if (!orgId) {
75
- logger.error(pc.red("No active organization. Run `kici org use <name>` to set one."));
76
- return false;
77
- }
78
- logger.info(`Cancelling all in-progress runs on branch ${pc.cyan(branch)}...`);
79
- const url = `${endpoint}/api/v1/orgs/${orgId}/runs/cancel-by-branch`;
80
- const response = await fetch(url, {
81
- method: "POST",
82
- headers: {
83
- "Content-Type": "application/json",
84
- Authorization: `Bearer ${token}`
85
- },
86
- body: JSON.stringify({ branch })
87
- });
88
- if (response.ok) {
89
- const runs = (await response.json()).cancelledRuns ?? 0;
90
- if (runs === 0) logger.info(pc.yellow(`No in-progress runs found on branch ${branch}.`));
91
- else logger.info(pc.green(`Cancelled ${runs} run${runs !== 1 ? "s" : ""} on branch ${branch}.`));
92
- return true;
93
- }
94
- return handleApiError(response);
95
- }
96
- /**
97
- * Handle API error responses with clear user-facing messages.
98
- */
99
- async function handleApiError(response, runId) {
100
- let errorDetail;
101
- try {
102
- errorDetail = (await response.json()).error;
103
- } catch {}
104
- switch (response.status) {
105
- case 401:
106
- logger.error(pc.red("Authentication failed. Run `kici login` to re-authenticate."));
107
- break;
108
- case 403:
109
- logger.error(pc.red(`Access denied${errorDetail ? `: ${errorDetail}` : ""}.`));
110
- break;
111
- case 404:
112
- logger.error(pc.red(`Run not found${runId ? `: ${runId}` : ""}.`));
113
- break;
114
- case 409:
115
- logger.error(pc.yellow(errorDetail ?? `Run ${runId ?? ""} is already in a terminal state.`));
116
- break;
117
- default: logger.error(pc.red(errorDetail ?? `Request failed with status ${response.status}.`));
118
- }
119
- return false;
120
- }
121
- //#endregion
122
- export { cancelCommand };
123
-
124
- //# sourceMappingURL=cancel.js.map
@@ -1,212 +0,0 @@
1
- import "../chunk-gOLHoazu.js";
2
- import { formatCapabilityGapError } from "../errors/capability-gap.js";
3
- import { AuthenticationError, ConnectionError, NotFoundError, OrchestratorClient } from "../remote/client.js";
4
- import { loadGlobalConfig } from "../remote/config.js";
5
- import { RunHistory } from "../remote/history.js";
6
- import { StreamingFormatter } from "../remote/output/streaming.js";
7
- import { observeCompletion } from "./run.js";
8
- import pc from "picocolors";
9
- import { formatDuration, logger, toErrorMessage } from "@kici-dev/core";
10
- //#region src/commands/status.ts
11
- /**
12
- * kici status command
13
- *
14
- * Shows the status and details of a test run, with optional log streaming.
15
- * Looks up local history first, then fetches from the orchestrator for
16
- * up-to-date status and logs.
17
- */
18
- const CLI_VERSION = "0.1.16";
19
- /**
20
- * Show status and details of a test run.
21
- *
22
- * Default mode: show run summary table from local history + orchestrator.
23
- * --logs: stream full logs from the orchestrator.
24
- * --job <name>: filter logs to a specific job.
25
- * --json: output raw JSON.
26
- *
27
- * @param runId - The run ID to inspect
28
- * @param options - Status display options
29
- * @returns true on success, false on error
30
- */
31
- async function statusCommand(runId, options = {}) {
32
- try {
33
- const history = new RunHistory();
34
- await history.load();
35
- const localEntry = history.getEntry(runId);
36
- if (!options.json) displayAuthInfo(await loadGlobalConfig());
37
- const config = await loadGlobalConfig();
38
- const endpoint = config.endpoint ?? config.platformEndpoint;
39
- if (!config.token || !endpoint) {
40
- if (localEntry) {
41
- if (options.json) console.log(JSON.stringify(localEntry, null, 2));
42
- else displayLocalEntry(localEntry);
43
- return true;
44
- }
45
- logger.error(pc.red("Not authenticated and no local history for this run. Run `kici login` to authenticate."));
46
- return false;
47
- }
48
- const client = new OrchestratorClient({
49
- endpoint,
50
- token: config.token
51
- });
52
- try {
53
- const remoteStatus = await client.getRunStatus(runId);
54
- if (options.json) {
55
- console.log(JSON.stringify(remoteStatus, null, 2));
56
- return true;
57
- }
58
- if (options.logs) return await displayLogs(client, config.token, runId, options.job);
59
- displayRunSummary(remoteStatus, localEntry);
60
- return true;
61
- } catch (error) {
62
- if (error instanceof NotFoundError) {
63
- if (localEntry) {
64
- if (options.json) console.log(JSON.stringify(localEntry, null, 2));
65
- else {
66
- logger.info(pc.yellow("Run not found on orchestrator. Showing local history:\n"));
67
- displayLocalEntry(localEntry);
68
- }
69
- return true;
70
- }
71
- logger.error(pc.red(`Run not found: ${runId}`));
72
- return false;
73
- }
74
- if (error instanceof AuthenticationError) {
75
- logger.error(pc.red("Authentication failed. Run `kici login` to re-authenticate."));
76
- return false;
77
- }
78
- if (error instanceof ConnectionError) {
79
- if (localEntry) {
80
- logger.info(pc.yellow("Cannot reach orchestrator. Showing local history (may be stale):\n"));
81
- if (options.json) console.log(JSON.stringify(localEntry, null, 2));
82
- else displayLocalEntry(localEntry);
83
- return true;
84
- }
85
- logger.error(pc.red(`Connection failed: ${error.message}`));
86
- return false;
87
- }
88
- throw error;
89
- }
90
- } catch (error) {
91
- const message = toErrorMessage(error);
92
- logger.error(pc.red(`Error: ${message}`));
93
- return false;
94
- }
95
- }
96
- /**
97
- * Display a run summary from remote status (+ local context).
98
- */
99
- function displayRunSummary(remote, local) {
100
- const statusColor = remote.status === "success" ? pc.green : remote.status === "failed" ? pc.red : remote.status === "cancelled" ? pc.yellow : pc.blue;
101
- logger.info(pc.bold(`\nRun: ${remote.runId}`));
102
- logger.info(`Status: ${statusColor(remote.status)}`);
103
- if (remote.status === "failed" && remote.failureReason) logger.info(`Reason: ${pc.red(remote.failureReason)}`);
104
- if (local?.fixtureId) logger.info(`Fixture: ${pc.cyan(local.fixtureId)}`);
105
- if (local?.endpoint) logger.info(`Endpoint: ${pc.gray(local.endpoint)}`);
106
- if (local?.startedAt) logger.info(`Started: ${pc.gray(local.startedAt)}`);
107
- if (local?.completedAt) logger.info(`Completed: ${pc.gray(local.completedAt)}`);
108
- if (remote.summary) {
109
- const totalDuration = remote.summary.totalDurationMs;
110
- logger.info(`Duration: ${pc.gray(formatDuration(totalDuration))}`);
111
- if (remote.summary.jobs.length > 0) {
112
- logger.info(pc.bold("\nJobs:"));
113
- const nameWidth = Math.max(10, ...remote.summary.jobs.map((j) => j.name.length)) + 2;
114
- for (const job of remote.summary.jobs) {
115
- const jobColor = job.status === "success" ? pc.green : job.status === "failed" ? pc.red : job.status === "cancelled" ? pc.yellow : pc.blue;
116
- const duration = job.durationMs ? formatDuration(job.durationMs) : "-";
117
- logger.info(` ${jobColor(job.status.padEnd(12))} ${job.name.padEnd(nameWidth)} ${pc.gray(duration)}`);
118
- if (job.status === "failed" && job.errorMessage) logger.info(` ${pc.red("↳")} ${pc.gray(job.errorMessage)}`);
119
- }
120
- }
121
- }
122
- logger.info("");
123
- }
124
- /**
125
- * Display a local-only history entry.
126
- */
127
- function displayLocalEntry(entry) {
128
- const statusColor = entry.status === "success" ? pc.green : entry.status === "failed" ? pc.red : entry.status === "cancelled" ? pc.yellow : pc.blue;
129
- logger.info(pc.bold(`\nRun: ${entry.runId}`));
130
- logger.info(`Status: ${statusColor(entry.status)}`);
131
- logger.info(`Fixture: ${pc.cyan(entry.fixtureId)}`);
132
- logger.info(`Endpoint: ${pc.gray(entry.endpoint)}`);
133
- logger.info(`Started: ${pc.gray(entry.startedAt)}`);
134
- if (entry.completedAt) logger.info(`Completed: ${pc.gray(entry.completedAt)}`);
135
- if (entry.durationMs) logger.info(`Duration: ${pc.gray(formatDuration(entry.durationMs))}`);
136
- if (entry.jobs && entry.jobs.length > 0) {
137
- logger.info(pc.bold("\nJobs:"));
138
- for (const job of entry.jobs) {
139
- const jobColor = job.status === "success" ? pc.green : job.status === "failed" ? pc.red : job.status === "cancelled" ? pc.yellow : pc.blue;
140
- const duration = job.durationMs ? formatDuration(job.durationMs) : "-";
141
- logger.info(` ${jobColor(job.status.padEnd(12))} ${job.name} ${pc.gray(duration)}`);
142
- }
143
- }
144
- logger.info(pc.gray("\n(Local history only -- run may have updated on orchestrator)"));
145
- logger.info("");
146
- }
147
- /**
148
- * Stream logs for a run from the orchestrator.
149
- *
150
- * For active runs, connects via WebSocket for live streaming.
151
- * For completed runs, fetches historical logs from storage.
152
- */
153
- async function displayLogs(client, token, runId, jobFilter) {
154
- let logsResponse;
155
- try {
156
- logsResponse = await client.getRunLogs(runId, jobFilter);
157
- } catch (error) {
158
- if (error instanceof NotFoundError) {
159
- const caps = await client.getCapabilities();
160
- logger.error(formatCapabilityGapError({
161
- feature: "log-streaming",
162
- cliVersion: CLI_VERSION,
163
- orchestratorVersion: caps.orchestratorVersion
164
- }));
165
- return false;
166
- }
167
- throw error;
168
- }
169
- if (logsResponse.observeUrl) {
170
- logger.info(pc.bold(`\nStreaming live logs for run: ${runId}\n`));
171
- return (await observeCompletion("status", runId, logsResponse.observeUrl, token, client, {})).status === "success";
172
- }
173
- logger.info(pc.bold(`\nLogs for run: ${runId}\n`));
174
- if (!logsResponse.logs || logsResponse.logs.length === 0) {
175
- logger.info(pc.gray("No logs available for this run."));
176
- return true;
177
- }
178
- const formatter = new StreamingFormatter();
179
- for (const entry of logsResponse.logs) for (const line of entry.lines) {
180
- const output = formatter.formatLogLine(entry.jobName, entry.stepName, line);
181
- if (output) process.stdout.write(output);
182
- }
183
- logger.info("");
184
- return true;
185
- }
186
- /**
187
- * Display authentication information section.
188
- *
189
- * Shows logged-in user, active org, and PAT expiry with warnings.
190
- */
191
- function displayAuthInfo(config) {
192
- logger.info(pc.bold("\nAuth:"));
193
- if (config.pat) {
194
- const email = config.userEmail || "unknown";
195
- logger.info(` Logged in as: ${pc.cyan(email)}`);
196
- logger.info(` Active org: ${config.activeOrgId || pc.gray("none")}`);
197
- if (config.patExpiresAt) {
198
- const expiryDate = new Date(config.patExpiresAt);
199
- const now = /* @__PURE__ */ new Date();
200
- const daysRemaining = Math.ceil((expiryDate.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
201
- if (daysRemaining <= 0) logger.info(pc.red(` PAT expired. Run 'kici login' to re-authenticate.`));
202
- else if (daysRemaining <= 7) logger.info(pc.yellow(` PAT expires in ${daysRemaining} day(s). Run 'kici login' to refresh.`));
203
- else logger.info(` PAT expires: ${expiryDate.toLocaleDateString()} (${daysRemaining} days remaining)`);
204
- }
205
- } else if (config.token) logger.info(` Using API key authentication.`);
206
- else logger.info(pc.gray(` Not authenticated. Run 'kici login' to get started.`));
207
- logger.info("");
208
- }
209
- //#endregion
210
- export { displayRunSummary, statusCommand };
211
-
212
- //# sourceMappingURL=status.js.map
@@ -1,203 +0,0 @@
1
- import "../chunk-gOLHoazu.js";
2
- import { toErrorMessage } from "@kici-dev/core";
3
- //#region src/remote/client.ts
4
- /**
5
- * REST client for communicating with the KiCI orchestrator.
6
- *
7
- * Provides typed methods for triggering test runs, cancelling runs,
8
- * managing uploads, and checking run status.
9
- */
10
- var AuthenticationError = class extends Error {
11
- constructor(message = "Invalid API key. Run `kici login` to authenticate.") {
12
- super(message);
13
- this.name = "AuthenticationError";
14
- }
15
- };
16
- var AccessDeniedError = class extends Error {
17
- constructor(message = "Access denied") {
18
- super(message);
19
- this.name = "AccessDeniedError";
20
- }
21
- };
22
- var NotFoundError = class extends Error {
23
- constructor(message = "Resource not found") {
24
- super(message);
25
- this.name = "NotFoundError";
26
- }
27
- };
28
- var ServerError = class extends Error {
29
- constructor(message = "Server error", statusCode) {
30
- super(message);
31
- this.statusCode = statusCode;
32
- this.name = "ServerError";
33
- }
34
- };
35
- var ConnectionError = class extends Error {
36
- constructor(message, endpoint) {
37
- super(message);
38
- this.endpoint = endpoint;
39
- this.name = "ConnectionError";
40
- }
41
- };
42
- /**
43
- * REST client for the KiCI orchestrator API.
44
- *
45
- * Handles authentication, request formatting, and typed response parsing
46
- * for all test-trigger and upload operations.
47
- */
48
- var OrchestratorClient = class {
49
- baseUrl;
50
- token;
51
- cachedCapabilities;
52
- constructor(config) {
53
- this.baseUrl = config.endpoint.replace(/\/+$/, "");
54
- this.token = config.token;
55
- }
56
- /**
57
- * Fetch the orchestrator's capability manifest.
58
- *
59
- * Never throws — on any failure (old orchestrator returning 404, network
60
- * error, malformed JSON) it returns an empty manifest. Callers use the
61
- * returned fields to format actionable capability-gap errors and treat
62
- * missing fields as "unknown".
63
- *
64
- * Memoised per client instance so repeated calls in a single CLI session
65
- * hit the orchestrator once.
66
- */
67
- async getCapabilities() {
68
- if (!this.cachedCapabilities) this.cachedCapabilities = this.fetchCapabilities();
69
- return this.cachedCapabilities;
70
- }
71
- async fetchCapabilities() {
72
- const url = `${this.baseUrl}/api/v1/capabilities`;
73
- try {
74
- const response = await fetch(url);
75
- if (!response.ok) return {};
76
- const body = await response.json();
77
- return {
78
- orchestratorVersion: typeof body.orchestratorVersion === "string" ? body.orchestratorVersion : void 0,
79
- protocolVersion: typeof body.protocolVersion === "number" ? body.protocolVersion : void 0,
80
- minProtocolVersion: typeof body.minProtocolVersion === "number" ? body.minProtocolVersion : void 0
81
- };
82
- } catch {
83
- return {};
84
- }
85
- }
86
- /**
87
- * Trigger a test run on the orchestrator.
88
- *
89
- * POST /api/v1/test/trigger
90
- */
91
- async triggerTest(input) {
92
- return await (await this.request("/api/v1/test/trigger", {
93
- method: "POST",
94
- body: JSON.stringify(input)
95
- })).json();
96
- }
97
- /**
98
- * Cancel a running test run.
99
- *
100
- * POST /api/v1/test/cancel
101
- */
102
- async cancelTest(runId) {
103
- return await (await this.request("/api/v1/test/cancel", {
104
- method: "POST",
105
- body: JSON.stringify({ runId })
106
- })).json();
107
- }
108
- /**
109
- * Initialize an upload and get a pre-signed URL.
110
- *
111
- * POST /api/v1/uploads/init
112
- */
113
- async initUpload(opts) {
114
- return await (await this.request("/api/v1/uploads/init", {
115
- method: "POST",
116
- body: JSON.stringify(opts)
117
- })).json();
118
- }
119
- /**
120
- * Get the status of an upload.
121
- *
122
- * GET /api/v1/uploads/:uploadId/status
123
- */
124
- async getUploadStatus(uploadId) {
125
- return await (await this.request(`/api/v1/uploads/${uploadId}/status`, { method: "GET" })).json();
126
- }
127
- /**
128
- * List workflow registrations for an organization.
129
- *
130
- * GET /api/v1/orgs/:orgId/registrations
131
- */
132
- async getRegistrations(orgId, filters) {
133
- const query = new URLSearchParams(filters).toString();
134
- const path = `/api/v1/orgs/${orgId}/registrations${query ? `?${query}` : ""}`;
135
- return await (await this.request(path, { method: "GET" })).json();
136
- }
137
- /**
138
- * Get the status of a test run (polling fallback).
139
- *
140
- * GET /api/v1/test/runs/:runId
141
- */
142
- async getRunStatus(runId) {
143
- return await (await this.request(`/api/v1/test/runs/${runId}`, { method: "GET" })).json();
144
- }
145
- /**
146
- * Get logs for a test run.
147
- *
148
- * GET /api/v1/test/runs/:runId/logs
149
- */
150
- async getRunLogs(runId, jobFilter) {
151
- const query = jobFilter ? `?job=${encodeURIComponent(jobFilter)}` : "";
152
- return await (await this.request(`/api/v1/test/runs/${runId}/logs${query}`, { method: "GET" })).json();
153
- }
154
- /**
155
- * Make an authenticated request to the orchestrator.
156
- * Handles error classification and connection errors.
157
- */
158
- async request(path, init) {
159
- const url = `${this.baseUrl}${path}`;
160
- let response;
161
- try {
162
- response = await fetch(url, {
163
- ...init,
164
- headers: {
165
- "Content-Type": "application/json",
166
- Authorization: `Bearer ${this.token}`,
167
- ...init.headers
168
- }
169
- });
170
- } catch (err) {
171
- const message = toErrorMessage(err);
172
- throw new ConnectionError(`Failed to connect to orchestrator at ${this.baseUrl}: ${message}`, this.baseUrl);
173
- }
174
- if (response.ok) return response;
175
- if (response.status === 401) throw new AuthenticationError();
176
- if (response.status === 403) {
177
- let detail = "Access denied";
178
- try {
179
- const body = await response.json();
180
- if (body.error) detail = body.error;
181
- } catch {}
182
- throw new AccessDeniedError(detail);
183
- }
184
- if (response.status === 404) throw new NotFoundError();
185
- if (response.status >= 500) {
186
- let detail = `Server error (${response.status})`;
187
- try {
188
- const body = await response.json();
189
- if (body.error) detail = `${body.error} (${response.status})`;
190
- } catch {}
191
- throw new ServerError(`${detail}. The orchestrator may be temporarily unavailable -- try again in a moment.`, response.status);
192
- }
193
- let bodyText = "";
194
- try {
195
- bodyText = await response.text();
196
- } catch {}
197
- throw new Error(`Request failed with status ${response.status}: ${bodyText}`);
198
- }
199
- };
200
- //#endregion
201
- export { AuthenticationError, ConnectionError, NotFoundError, OrchestratorClient, ServerError };
202
-
203
- //# sourceMappingURL=client.js.map