@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.
- package/dist/auth/headless-detect.js +1 -1
- package/dist/cli-banner.js +1 -1
- package/dist/cli.js +56 -19
- package/dist/commands/approve.js +1 -1
- package/dist/commands/compile.js +19 -17
- package/dist/commands/diagnostics.d.ts +7 -0
- package/dist/commands/diagnostics.js +58 -0
- package/dist/commands/docs.js +1 -1
- package/dist/commands/drain-worker.js +1 -1
- package/dist/commands/endpoints.js +1 -1
- package/dist/commands/fixture.js +1 -1
- package/dist/commands/held-run-client.js +1 -1
- package/dist/commands/held-run-resolve.js +1 -1
- package/dist/commands/hook.js +1 -1
- package/dist/commands/index.d.ts +16 -4
- package/dist/commands/index.js +10 -4
- package/dist/commands/init.js +2 -2
- package/dist/commands/login.d.ts +0 -2
- package/dist/commands/login.js +1 -3
- package/dist/commands/logout.js +1 -1
- package/dist/commands/orchestrators.d.ts +25 -0
- package/dist/commands/orchestrators.js +115 -0
- package/dist/commands/org.js +1 -1
- package/dist/commands/reject.js +1 -1
- package/dist/commands/run.d.ts +2 -9
- package/dist/commands/run.js +256 -315
- package/dist/commands/runs/cancel.d.ts +6 -0
- package/dist/commands/runs/cancel.js +32 -0
- package/dist/commands/runs/list.d.ts +6 -0
- package/dist/commands/runs/list.js +49 -0
- package/dist/commands/runs/logs.d.ts +7 -0
- package/dist/commands/runs/logs.js +67 -0
- package/dist/commands/runs/rerun.d.ts +5 -0
- package/dist/commands/runs/rerun.js +21 -0
- package/dist/commands/runs/show.d.ts +5 -0
- package/dist/commands/runs/show.js +65 -0
- package/dist/commands/secrets-list.d.ts +7 -9
- package/dist/commands/secrets-list.js +40 -64
- package/dist/commands/test.d.ts +4 -0
- package/dist/commands/test.js +4 -6
- package/dist/commands/types.d.ts +3 -5
- package/dist/commands/types.js +13 -37
- package/dist/commands/verify-attestation.d.ts +12 -0
- package/dist/commands/verify-attestation.js +69 -0
- package/dist/commands/watch.js +1 -1
- package/dist/commands/workflows.js +14 -34
- package/dist/errors/capability-gap.js +1 -1
- package/dist/errors/formatter.js +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/execution/executor.js +1 -1
- package/dist/execution/index.js +1 -1
- package/dist/execution/sdk-alias.js +1 -1
- package/dist/execution/ts-loader.js +1 -1
- package/dist/fixtures/compiler.js +1 -1
- package/dist/fixtures/defaults/index.js +1 -1
- package/dist/format.js +1 -1
- package/dist/generators/secrets-dts.js +2 -2
- package/dist/hooks/detector.js +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/installer.js +1 -1
- package/dist/hooks/templates.js +1 -1
- package/dist/index.js +1 -1
- package/dist/llm-context/llms-full.txt +1549 -1282
- package/dist/llm-context/llms.txt +6 -2
- package/dist/local-executor/dag-scheduler.js +1 -1
- package/dist/local-executor/index.js +1 -1
- package/dist/local-executor/job-runner.js +40 -18
- package/dist/local-executor/materializer.js +1 -1
- package/dist/local-executor/output-streamer.js +1 -1
- package/dist/local-executor/payload-generator.js +1 -1
- package/dist/local-executor/picker.js +1 -1
- package/dist/local-executor/runs-on-display.d.ts +9 -0
- package/dist/local-executor/runs-on-display.js +23 -0
- package/dist/local-executor/secret-loader.js +1 -1
- package/dist/local-executor/to-event-payload.js +1 -1
- package/dist/local-executor/types.js +1 -1
- package/dist/local-executor/workflow-lock.js +0 -0
- package/dist/lockfile/generator.d.ts +9 -5
- package/dist/lockfile/generator.js +58 -38
- package/dist/lockfile/hash-files.js +1 -1
- package/dist/lockfile/hasher.js +1 -1
- package/dist/lockfile/index.js +1 -1
- package/dist/lockfile/purity-analyzer.js +1 -1
- package/dist/postinstall.js +1 -1
- package/dist/provenance-trust-root.d.ts +14 -0
- package/dist/provenance-trust-root.js +49 -0
- package/dist/remote/config.d.ts +6 -2
- package/dist/remote/config.js +7 -4
- package/dist/remote/dashboard-client.d.ts +92 -0
- package/dist/remote/dashboard-client.js +168 -0
- package/dist/remote/encryption.js +3 -4
- package/dist/remote/history.js +1 -1
- package/dist/remote/oauth.js +1 -1
- package/dist/remote/oidc-discovery.js +1 -1
- package/dist/remote/output/json.js +1 -1
- package/dist/remote/output/junit.js +1 -1
- package/dist/remote/output/streaming.js +1 -1
- package/dist/remote/output/summary.js +1 -1
- package/dist/remote/platform-client.d.ts +142 -0
- package/dist/remote/platform-client.js +187 -0
- package/dist/remote/prod-defaults.js +1 -1
- package/dist/remote/render.d.ts +11 -0
- package/dist/remote/render.js +48 -0
- package/dist/remote/secret-upload.js +1 -1
- package/dist/remote/uploader.d.ts +9 -0
- package/dist/remote/uploader.js +51 -4
- package/dist/templates/agents-md.d.ts +1 -1
- package/dist/templates/agents-md.js +8 -3
- package/dist/templates/index.js +1 -1
- package/dist/templates/package-json.js +4 -5
- package/dist/templates/tsconfig-json.js +1 -1
- package/dist/templates/workflows/hello-world.js +2 -2
- package/dist/templates/workflows/hello-world.ts +1 -1
- package/dist/templates/workflows/pr-checks.js +3 -3
- package/dist/templates/workflows/pr-checks.ts +2 -2
- package/dist/test-runner/dry-run.js +1 -1
- package/dist/test-runner/event-types.js +1 -1
- package/dist/test-runner/git-detector.js +1 -1
- package/dist/test-runner/index.js +1 -1
- package/dist/test-runner/job-executor.js +3 -2
- package/dist/test-runner/output-formatter.js +1 -1
- package/dist/test-runner/payload-builder.js +1 -1
- package/dist/test-runner/rule-evaluator.js +1 -1
- package/dist/test-runner/secrets-file.js +1 -1
- package/dist/test-runner/step-context.js +10 -6
- package/dist/types.d.ts +29 -8
- package/dist/types.js +2 -1
- package/dist/validation/index.js +1 -1
- package/dist/validation/validator.js +1 -1
- package/dist/workflows/hello-world.ts +1 -1
- package/dist/workflows/pr-checks.ts +2 -2
- package/package.json +10 -9
- package/sbom.spdx.json +465 -410
- package/dist/commands/cancel.js +0 -124
- package/dist/commands/status.js +0 -212
- package/dist/remote/client.js +0 -203
- package/dist/remote/observer.js +0 -174
- /package/dist/{chunk-gOLHoazu.js → chunk-BTugEXQM.js} +0 -0
package/dist/commands/cancel.js
DELETED
|
@@ -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
|
package/dist/commands/status.js
DELETED
|
@@ -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
|
package/dist/remote/client.js
DELETED
|
@@ -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
|