@kici-dev/compiler 0.4.0 → 0.6.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.
- package/dist/cli.js +37 -7
- package/dist/commands/approve.d.ts +12 -0
- package/dist/commands/approve.js +5 -2
- package/dist/commands/compile.js +5 -15
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/endpoints.js +4 -6
- package/dist/commands/held-run-client.d.ts +21 -1
- package/dist/commands/held-run-client.js +34 -15
- package/dist/commands/hook.js +22 -20
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +2 -1
- package/dist/commands/init.d.ts +9 -2
- package/dist/commands/init.js +43 -16
- package/dist/commands/login.js +1 -1
- package/dist/commands/orchestrators.js +3 -2
- package/dist/commands/preview.js +1 -8
- package/dist/commands/reject.d.ts +12 -0
- package/dist/commands/reject.js +5 -2
- package/dist/commands/report/collect.d.ts +82 -0
- package/dist/commands/report/collect.js +234 -0
- package/dist/commands/report/identity.d.ts +48 -0
- package/dist/commands/report/identity.js +49 -0
- package/dist/commands/report/index.d.ts +63 -0
- package/dist/commands/report/index.js +119 -0
- package/dist/commands/report/upload.d.ts +38 -0
- package/dist/commands/report/upload.js +64 -0
- package/dist/commands/run-hold-watch.js +2 -2
- package/dist/commands/run.js +6 -3
- package/dist/commands/runs/show.js +80 -1
- package/dist/commands/types.js +51 -9
- package/dist/errors/formatter.d.ts +2 -4
- package/dist/errors/formatter.js +1 -3
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +2 -2
- package/dist/execution/sdk-alias.js +4 -2
- package/dist/fixtures/compiler.js +2 -1
- package/dist/format.js +3 -3
- package/dist/generators/secrets-dts.d.ts +8 -3
- package/dist/generators/secrets-dts.js +3 -3
- package/dist/hooks/installer.js +2 -1
- package/dist/llm-context/llms-architecture.txt +59 -23
- package/dist/llm-context/llms-cli.txt +168 -34
- package/dist/llm-context/llms-features-execution.txt +2017 -0
- package/dist/llm-context/llms-features.txt +96 -1100
- package/dist/llm-context/llms-full.txt +3131 -1407
- package/dist/llm-context/llms-getting-started.txt +164 -31
- package/dist/llm-context/llms-patterns.txt +186 -7
- package/dist/llm-context/llms-providers.txt +15 -33
- package/dist/llm-context/llms-sdk-runtime.txt +62 -40
- package/dist/llm-context/llms-sdk.txt +284 -58
- package/dist/llm-context/llms.txt +23 -15
- package/dist/local-plane/paths.d.ts +15 -0
- package/dist/local-plane/paths.js +22 -1
- package/dist/local-plane/plane-manager.js +2 -2
- package/dist/local-plane/port-holder.js +1 -1
- package/dist/local-plane/postgres.d.ts +3 -16
- package/dist/local-plane/postgres.js +10 -15
- package/dist/lockfile/generator.d.ts +12 -0
- package/dist/lockfile/generator.js +182 -54
- package/dist/lockfile/index.d.ts +0 -2
- package/dist/lockfile/index.js +1 -2
- package/dist/postinstall.js +2 -1
- package/dist/remote/config.d.ts +2 -15
- package/dist/remote/config.js +2 -16
- package/dist/remote/dashboard-client.d.ts +39 -0
- package/dist/remote/dashboard-client.js +41 -0
- package/dist/remote/oauth.js +7 -5
- package/dist/remote/uploader.js +2 -2
- package/dist/templates/package-json.js +1 -1
- package/dist/test-runner/dry-run.d.ts +1 -2
- package/dist/test-runner/dry-run.js +5 -20
- package/dist/test-runner/git-detector.js +2 -1
- package/dist/test-runner/job-executor.js +2 -1
- package/dist/test-runner/payload-builder.js +11 -17
- package/dist/types.d.ts +64 -10
- package/dist/types.js +7 -1
- package/dist/validation/validator.js +63 -6
- package/package.json +16 -11
- package/sbom.spdx.json +957 -900
- package/dist/lockfile/purity-analyzer.d.ts +0 -25
- package/dist/lockfile/purity-analyzer.js +0 -204
- package/dist/lockfile/purity-diagnostics.d.ts +0 -31
- package/dist/lockfile/purity-diagnostics.js +0 -52
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import "../../rolldown-runtime-ClRpJifh.js";
|
|
2
|
+
import { DashboardClient } from "../../remote/dashboard-client.js";
|
|
3
|
+
import * as fs$1 from "node:fs";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
//#region src/commands/report/upload.ts
|
|
6
|
+
/**
|
|
7
|
+
* Upload a report bundle privately to KiCI.
|
|
8
|
+
*
|
|
9
|
+
* Three steps, and the split is the point: the Platform mints a presigned PUT,
|
|
10
|
+
* the bytes go straight from this machine to object storage, and a confirm call
|
|
11
|
+
* lets the Platform verify what actually landed. The bundle never transits the
|
|
12
|
+
* control plane, and the Platform never takes the client's word for the size.
|
|
13
|
+
*
|
|
14
|
+
* Upload is always opt-in (`--upload`). A bundle contains diagnostic data from
|
|
15
|
+
* the customer's own machine, so sending it is a separate, explicit act from
|
|
16
|
+
* producing it.
|
|
17
|
+
*/
|
|
18
|
+
/** sha256 of the file, which the Platform records alongside the report. */
|
|
19
|
+
function sha256Of(body) {
|
|
20
|
+
return createHash("sha256").update(body).digest("hex");
|
|
21
|
+
}
|
|
22
|
+
async function defaultPutBytes(url, body) {
|
|
23
|
+
const res = await fetch(url, {
|
|
24
|
+
method: "PUT",
|
|
25
|
+
body: new Uint8Array(body),
|
|
26
|
+
headers: { "Content-Length": String(body.byteLength) }
|
|
27
|
+
});
|
|
28
|
+
if (!res.ok) throw new Error(`Bundle upload failed (${res.status} ${res.statusText}).`);
|
|
29
|
+
}
|
|
30
|
+
async function defaultDeps() {
|
|
31
|
+
const client = await DashboardClient.load();
|
|
32
|
+
return {
|
|
33
|
+
createIssueReport: client.createIssueReport.bind(client),
|
|
34
|
+
confirmIssueReport: client.confirmIssueReport.bind(client),
|
|
35
|
+
putBytes: defaultPutBytes
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Upload one bundle and return the reference id to quote to support.
|
|
40
|
+
*
|
|
41
|
+
* Reads the file once and derives both the size and the digest from those same
|
|
42
|
+
* bytes, so what is promised at presign time is necessarily what is uploaded —
|
|
43
|
+
* a stat-then-read would race a file still being written.
|
|
44
|
+
*/
|
|
45
|
+
async function uploadReportBundle(zipPath, meta, deps) {
|
|
46
|
+
const resolved = deps ?? await defaultDeps();
|
|
47
|
+
const body = fs$1.readFileSync(zipPath);
|
|
48
|
+
const { ref, uploadUrl } = await resolved.createIssueReport({
|
|
49
|
+
bundleId: meta.bundleId,
|
|
50
|
+
byteSize: body.byteLength,
|
|
51
|
+
sha256: sha256Of(body),
|
|
52
|
+
message: meta.message,
|
|
53
|
+
email: meta.email
|
|
54
|
+
});
|
|
55
|
+
await resolved.putBytes(uploadUrl, body);
|
|
56
|
+
return {
|
|
57
|
+
ref,
|
|
58
|
+
status: (await resolved.confirmIssueReport(ref)).status
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { sha256Of, uploadReportBundle };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=upload.js.map
|
|
@@ -66,7 +66,7 @@ async function handleNewHolds(args) {
|
|
|
66
66
|
printHold(action.hold, out);
|
|
67
67
|
ctx = ctx ?? await resolveCtx();
|
|
68
68
|
if (!ctx) {
|
|
69
|
-
out(pc.dim(`Run held; approve via \`kici approve ${action.hold.runId}\`.`));
|
|
69
|
+
out(pc.dim(`Run held; approve via \`kici approve ${action.hold.runId} --hold ${action.hold.id}\`.`));
|
|
70
70
|
continue;
|
|
71
71
|
}
|
|
72
72
|
if (args.approveAll) {
|
|
@@ -74,7 +74,7 @@ async function handleNewHolds(args) {
|
|
|
74
74
|
continue;
|
|
75
75
|
}
|
|
76
76
|
if (action.kind === "notify") {
|
|
77
|
-
out(pc.dim(`Run held; approve via the dashboard or \`kici approve ${action.hold.runId}\`.`));
|
|
77
|
+
out(pc.dim(`Run held; approve via the dashboard or \`kici approve ${action.hold.runId} --hold ${action.hold.id}\`.`));
|
|
78
78
|
continue;
|
|
79
79
|
}
|
|
80
80
|
const approved = await args.confirm("Approve this gate?");
|
package/dist/commands/run.js
CHANGED
|
@@ -303,8 +303,10 @@ async function renderResults(results, options) {
|
|
|
303
303
|
const junitXml = formatJunitResult(runResults);
|
|
304
304
|
await writeFile(options.junit, junitXml);
|
|
305
305
|
if (!options.quiet) logger.info(pc.green(`JUnit XML written to ${options.junit}`));
|
|
306
|
-
} else if (!options.quiet || results.some((r) => r.status !== "success" && r.status !== "accepted"))
|
|
307
|
-
|
|
306
|
+
} else if (!options.quiet || results.some((r) => r.status !== "success" && r.status !== "accepted")) {
|
|
307
|
+
if (runResults.length > 1) logger.info(formatMultiFixtureSummary(runResults));
|
|
308
|
+
else displayRemoteResults(results);
|
|
309
|
+
}
|
|
308
310
|
return results.every((r) => r.status === "accepted" || r.status === "success");
|
|
309
311
|
}
|
|
310
312
|
/**
|
|
@@ -537,10 +539,11 @@ async function watchRunHolds(runId, seenHolds, getCtx, setCtx, options) {
|
|
|
537
539
|
const holds = await listHeldRunsForRun(ctx, runId);
|
|
538
540
|
if (holds.length === 0) return;
|
|
539
541
|
const quiet = Boolean(options.quiet);
|
|
542
|
+
const isTty = quiet ? false : Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
540
543
|
await handleNewHolds({
|
|
541
544
|
holds,
|
|
542
545
|
seen: seenHolds,
|
|
543
|
-
isTty
|
|
546
|
+
isTty,
|
|
544
547
|
output: quiet ? (line) => void process.stderr.write(line + "\n") : (line) => logger.info(line),
|
|
545
548
|
approveAll: Boolean(options.approveAll),
|
|
546
549
|
confirm: (message) => confirm({
|
|
@@ -2,6 +2,7 @@ import "../../rolldown-runtime-ClRpJifh.js";
|
|
|
2
2
|
import { DashboardClient, DashboardClientError } from "../../remote/dashboard-client.js";
|
|
3
3
|
import { RunHistory } from "../../remote/history.js";
|
|
4
4
|
import { colorStatus, formatDuration as formatDuration$1, relativeTime } from "../../remote/render.js";
|
|
5
|
+
import { HeldRunRequestError, listHeldRunsForRun, resolveHeldRunContext } from "../held-run-client.js";
|
|
5
6
|
import pc from "picocolors";
|
|
6
7
|
import { logger, toErrorMessage } from "@kici-dev/core";
|
|
7
8
|
//#region src/commands/runs/show.ts
|
|
@@ -17,33 +18,111 @@ async function runsShowCommand(runId, options = {}) {
|
|
|
17
18
|
throw err;
|
|
18
19
|
}
|
|
19
20
|
const detail = await client.getRunDetail(runId);
|
|
21
|
+
const holds = await loadHolds(runId);
|
|
20
22
|
if (options.json) {
|
|
21
23
|
console.log(JSON.stringify({
|
|
22
24
|
run,
|
|
23
|
-
detail
|
|
25
|
+
detail,
|
|
26
|
+
heldRuns: holds.holds,
|
|
27
|
+
...holds.unavailable && { heldRunsUnavailable: holds.unavailable }
|
|
24
28
|
}, null, 2));
|
|
25
29
|
return true;
|
|
26
30
|
}
|
|
27
31
|
printHeader(run);
|
|
32
|
+
printInitFailure(detail.initFailure);
|
|
28
33
|
printJobs(detail.jobs);
|
|
34
|
+
printHolds(holds);
|
|
29
35
|
return true;
|
|
30
36
|
} catch (err) {
|
|
31
37
|
logger.error(pc.red(err instanceof DashboardClientError ? err.message : toErrorMessage(err)));
|
|
32
38
|
return false;
|
|
33
39
|
}
|
|
34
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Read the approval holds recorded for a run.
|
|
43
|
+
*
|
|
44
|
+
* The holds are extra detail on a run this command can already display, so a
|
|
45
|
+
* failure here degrades to a note rather than failing the command: an operator
|
|
46
|
+
* asking why a job did not run still gets the run, its jobs and its init
|
|
47
|
+
* failure. The auth context is resolved quietly for the same reason — a config
|
|
48
|
+
* that cannot reach the held-runs API is not an error for `runs show`.
|
|
49
|
+
*/
|
|
50
|
+
async function loadHolds(runId) {
|
|
51
|
+
try {
|
|
52
|
+
const ctx = await resolveHeldRunContext({ quiet: true });
|
|
53
|
+
if (!ctx) return {
|
|
54
|
+
holds: [],
|
|
55
|
+
unavailable: "not authenticated for held-run lookup",
|
|
56
|
+
unavailableSilently: true
|
|
57
|
+
};
|
|
58
|
+
return { holds: await listHeldRunsForRun(ctx, runId) };
|
|
59
|
+
} catch (err) {
|
|
60
|
+
const denied = err instanceof HeldRunRequestError && err.isPermissionDenied;
|
|
61
|
+
return {
|
|
62
|
+
holds: [],
|
|
63
|
+
unavailable: toErrorMessage(err),
|
|
64
|
+
...denied && { unavailableSilently: true }
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
35
68
|
function printHeader(run) {
|
|
36
69
|
const f = (v) => v == null ? "—" : v;
|
|
37
70
|
console.log(pc.bold(`\nRun ${run.runId}`) + ` ${colorStatus(run.status)}`);
|
|
38
71
|
console.log(pc.gray(` workflow=${f(run.workflowName)} repo=${f(run.repoIdentifier)} branch=${f(run.ref)} sha=${f(run.sha)} trigger=${f(run.triggerEvent)} by=${f(run.triggeredBy)}`));
|
|
39
72
|
console.log(pc.gray(` started=${relativeTime(run.startedAt ?? void 0)}`));
|
|
40
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* The run-scoped init failure — why the run never started a step (an
|
|
76
|
+
* unresolvable lock file, a secret it could not read, a gate it never passed).
|
|
77
|
+
* Nothing is printed when the run started normally.
|
|
78
|
+
*/
|
|
79
|
+
function printInitFailure(initFailure) {
|
|
80
|
+
if (!initFailure) return;
|
|
81
|
+
console.log(`\n ${pc.yellow("Init failure")} ${pc.gray(`(${initFailure.category})`)}`);
|
|
82
|
+
console.log(` ${initFailure.message}`);
|
|
83
|
+
}
|
|
41
84
|
function printJobs(jobs) {
|
|
42
85
|
for (const j of jobs) {
|
|
43
86
|
console.log(`\n ${pc.bold(j.jobName)} ${colorStatus(j.status)} ` + pc.gray(j.durationMs ? formatDuration$1(j.durationMs) : ""));
|
|
87
|
+
printJobFailure(j);
|
|
44
88
|
for (const s of j.steps ?? []) console.log(pc.gray(" └─ ") + `${s.stepName} ${colorStatus(s.status)} ` + pc.gray(`${s.durationMs ? formatDuration$1(s.durationMs) : ""}${s.exitCode != null ? ` exit=${s.exitCode}` : ""}`));
|
|
45
89
|
}
|
|
46
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Why a single job failed: its job-scoped init failure (a job the context rules
|
|
93
|
+
* rejected carries `context_rules` plus the context and rule that rejected it),
|
|
94
|
+
* or its plain error message. The init failure wins when both are present —
|
|
95
|
+
* the two carry the same text on a rejected job, and the category is the part
|
|
96
|
+
* that tells the reader whether a gate or a step failed.
|
|
97
|
+
*/
|
|
98
|
+
function printJobFailure(job) {
|
|
99
|
+
if (job.initFailure) {
|
|
100
|
+
console.log(` ${pc.yellow("init failure")} ${pc.gray(`(${job.initFailure.category})`)}: ` + job.initFailure.message);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (job.errorMessage) console.log(` ${pc.red("error")}: ${job.errorMessage}`);
|
|
104
|
+
}
|
|
105
|
+
/** The approval holds recorded against the run, or a note when unreadable. */
|
|
106
|
+
function printHolds(result) {
|
|
107
|
+
if (result.unavailable) {
|
|
108
|
+
if (!result.unavailableSilently) console.log(pc.gray(`\n Approval-hold detail unavailable: ${result.unavailable}`));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (result.holds.length === 0) return;
|
|
112
|
+
console.log(`\n ${pc.bold(`Approval holds (${result.holds.length})`)}`);
|
|
113
|
+
for (const h of result.holds) {
|
|
114
|
+
const parts = [
|
|
115
|
+
h.jobId || "(workflow)",
|
|
116
|
+
h.holdType ?? "—",
|
|
117
|
+
h.contextName ? `context=${h.contextName}` : void 0,
|
|
118
|
+
h.queueType ? `queue=${h.queueType}` : void 0,
|
|
119
|
+
colorStatus(h.status)
|
|
120
|
+
].filter((p) => p != null);
|
|
121
|
+
console.log(` ${parts.join(" ")}`);
|
|
122
|
+
if (h.reason) console.log(pc.gray(` reason: ${h.reason}`));
|
|
123
|
+
if (h.expiresAt) console.log(pc.gray(` expires: ${relativeTime(h.expiresAt)}`));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
47
126
|
async function showLocalFallback(runId, json) {
|
|
48
127
|
const history = new RunHistory();
|
|
49
128
|
await history.load();
|
package/dist/commands/types.js
CHANGED
|
@@ -8,6 +8,32 @@ import fs from "node:fs/promises";
|
|
|
8
8
|
import { toErrorMessage } from "@kici-dev/core";
|
|
9
9
|
//#region src/commands/types.ts
|
|
10
10
|
/**
|
|
11
|
+
* Error kinds meaning the Platform is genuinely unreachable or the CLI is not
|
|
12
|
+
* configured to reach it — not authenticated, no active org, network down, or
|
|
13
|
+
* orchestrator offline. For these, `kici types` writes a valid empty stub so
|
|
14
|
+
* the declaration file always exists (typecheck degrades to "no known keys"
|
|
15
|
+
* rather than "module has no exported member") instead of failing.
|
|
16
|
+
*
|
|
17
|
+
* An authenticated-but-rejected response (`unauthorized`, `forbidden`, …) is
|
|
18
|
+
* deliberately excluded: that is a real credential/permission problem the user
|
|
19
|
+
* must see, and writing a stub would mask it.
|
|
20
|
+
*/
|
|
21
|
+
const UNREACHABLE_ERROR_KINDS = [
|
|
22
|
+
"not_logged_in",
|
|
23
|
+
"no_active_org",
|
|
24
|
+
"orchestrator_offline",
|
|
25
|
+
"http"
|
|
26
|
+
];
|
|
27
|
+
/** True if `p` exists (any type). Used to avoid clobbering a real snapshot. */
|
|
28
|
+
async function fileExists(p) {
|
|
29
|
+
try {
|
|
30
|
+
await fs.access(p);
|
|
31
|
+
return true;
|
|
32
|
+
} catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
11
37
|
* Generate TypeScript declarations for context secrets.
|
|
12
38
|
*
|
|
13
39
|
* Fetches context metadata (with secret key names) through the Platform
|
|
@@ -18,24 +44,40 @@ import { toErrorMessage } from "@kici-dev/core";
|
|
|
18
44
|
* @returns true on success, false on error
|
|
19
45
|
*/
|
|
20
46
|
async function typesCommand(options = {}) {
|
|
47
|
+
const kiciDir = options.kiciDir ?? ".kici";
|
|
48
|
+
const typesDir = path.join(kiciDir, "types");
|
|
49
|
+
const outputPath = path.join(typesDir, "secrets.d.ts");
|
|
21
50
|
try {
|
|
22
51
|
const config = await loadGlobalConfig();
|
|
52
|
+
const metadata = (await DashboardClient.fromConfig(config).listContexts(true)).map((e) => ({
|
|
53
|
+
name: e.name,
|
|
54
|
+
keys: e.secretKeys ?? []
|
|
55
|
+
}));
|
|
56
|
+
const source = config.platformEndpoint ?? config.endpoint ?? "kici Platform";
|
|
23
57
|
const dtsContent = generateSecretsDts({
|
|
24
|
-
contexts:
|
|
25
|
-
|
|
26
|
-
keys: e.secretKeys ?? []
|
|
27
|
-
})),
|
|
28
|
-
endpoint: (config.platformEndpoint ?? config.endpoint ?? "kici Platform").replace(/\/+$/, ""),
|
|
29
|
-
generatedAt: /* @__PURE__ */ new Date()
|
|
58
|
+
contexts: metadata,
|
|
59
|
+
endpoint: source.replace(/\/+$/, "")
|
|
30
60
|
});
|
|
31
|
-
const kiciDir = options.kiciDir ?? ".kici";
|
|
32
|
-
const typesDir = path.join(kiciDir, "types");
|
|
33
61
|
await fs.mkdir(typesDir, { recursive: true });
|
|
34
|
-
const outputPath = path.join(typesDir, "secrets.d.ts");
|
|
35
62
|
await fs.writeFile(outputPath, dtsContent, "utf-8");
|
|
36
63
|
if (!options.quiet) console.log(pc.green("Types generated") + pc.dim(` ${outputPath}`));
|
|
37
64
|
return true;
|
|
38
65
|
} catch (err) {
|
|
66
|
+
if (err instanceof DashboardClientError && UNREACHABLE_ERROR_KINDS.includes(err.kind)) {
|
|
67
|
+
if (await fileExists(outputPath)) {
|
|
68
|
+
console.error(pc.yellow(`${err.message} Keeping the existing ${outputPath}; run \`kici types\` when authenticated to refresh it.`));
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
const stub = generateSecretsDts({
|
|
72
|
+
contexts: [],
|
|
73
|
+
endpoint: "",
|
|
74
|
+
offline: true
|
|
75
|
+
});
|
|
76
|
+
await fs.mkdir(typesDir, { recursive: true });
|
|
77
|
+
await fs.writeFile(outputPath, stub, "utf-8");
|
|
78
|
+
console.error(pc.yellow(`${err.message} Wrote an offline type stub to ${outputPath}; run \`kici types\` when authenticated to populate it.`));
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
39
81
|
if (err instanceof DashboardClientError) {
|
|
40
82
|
console.error(pc.red(err.message));
|
|
41
83
|
return false;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Error code string. Thrown compile errors use `E<digits>` (e.g. 'E001', 'E102');
|
|
3
|
-
* advisory, render-only diagnostics use `W<digits
|
|
4
|
-
*
|
|
3
|
+
* advisory, render-only diagnostics use `W<digits>`. `isCompilerError` only
|
|
4
|
+
* matches the `E<digits>` family — warning codes are never thrown, only rendered.
|
|
5
5
|
*/
|
|
6
6
|
type ErrorCode = string;
|
|
7
7
|
/** Diagnostic severity. Errors abort compilation; warnings are advisory (compile still succeeds). */
|
|
@@ -9,8 +9,6 @@ export declare enum DiagnosticSeverity {
|
|
|
9
9
|
Error = "error",
|
|
10
10
|
Warning = "warning"
|
|
11
11
|
}
|
|
12
|
-
/** Warning code for the impure dynamic-value → init-job fallback. */
|
|
13
|
-
export declare const PURITY_FALLBACK_CODE = "W101";
|
|
14
12
|
/** Source location for error reporting */
|
|
15
13
|
export interface SourceLocation {
|
|
16
14
|
readonly file: string;
|
package/dist/errors/formatter.js
CHANGED
|
@@ -7,8 +7,6 @@ let DiagnosticSeverity = /* @__PURE__ */ function(DiagnosticSeverity) {
|
|
|
7
7
|
DiagnosticSeverity["Warning"] = "warning";
|
|
8
8
|
return DiagnosticSeverity;
|
|
9
9
|
}({});
|
|
10
|
-
/** Warning code for the impure dynamic-value → init-job fallback. */
|
|
11
|
-
const PURITY_FALLBACK_CODE = "W101";
|
|
12
10
|
/**
|
|
13
11
|
* Format error in GNU standard format: file:line:column: error [CODE]: message
|
|
14
12
|
*
|
|
@@ -40,6 +38,6 @@ function isCompilerError(error) {
|
|
|
40
38
|
return typeof error === "object" && error !== null && "code" in error && "message" in error && typeof error.code === "string" && /^E\d+$/.test(error.code);
|
|
41
39
|
}
|
|
42
40
|
//#endregion
|
|
43
|
-
export { DiagnosticSeverity,
|
|
41
|
+
export { DiagnosticSeverity, compilerError, formatError, isCompilerError };
|
|
44
42
|
|
|
45
43
|
//# sourceMappingURL=formatter.js.map
|
package/dist/errors/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { formatError, compilerError, isCompilerError, DiagnosticSeverity
|
|
1
|
+
export { formatError, compilerError, isCompilerError, DiagnosticSeverity } from './formatter.js';
|
|
2
2
|
export type { SourceLocation, CompilerError } from './formatter.js';
|
|
3
3
|
export { CapabilityGapError, formatCapabilityGapError } from './capability-gap.js';
|
|
4
4
|
export type { CapabilityGapInfo } from './capability-gap.js';
|
package/dist/errors/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../rolldown-runtime-ClRpJifh.js";
|
|
2
|
-
import { DiagnosticSeverity,
|
|
2
|
+
import { DiagnosticSeverity, compilerError, formatError, isCompilerError } from "./formatter.js";
|
|
3
3
|
import { CapabilityGapError, formatCapabilityGapError } from "./capability-gap.js";
|
|
4
4
|
import { firstStepLocation, locationForJob, locationForWorkflow } from "./source-location.js";
|
|
5
|
-
export { CapabilityGapError, DiagnosticSeverity,
|
|
5
|
+
export { CapabilityGapError, DiagnosticSeverity, compilerError, firstStepLocation, formatCapabilityGapError, formatError, isCompilerError, locationForJob, locationForWorkflow };
|
|
@@ -19,7 +19,8 @@ import { readFile } from "node:fs/promises";
|
|
|
19
19
|
*/
|
|
20
20
|
async function getSdkPathFromPackageJson() {
|
|
21
21
|
try {
|
|
22
|
-
const
|
|
22
|
+
const pkgPath = path.resolve(process.cwd(), ".kici", "package.json");
|
|
23
|
+
const content = await readFile(pkgPath, "utf-8");
|
|
23
24
|
const sdkPath = JSON.parse(content).kici?.sdkPath;
|
|
24
25
|
if (!sdkPath) return null;
|
|
25
26
|
return path.resolve(sdkPath);
|
|
@@ -36,7 +37,8 @@ async function getSdkPathFromPackageJson() {
|
|
|
36
37
|
*/
|
|
37
38
|
async function isInKiciRepo() {
|
|
38
39
|
try {
|
|
39
|
-
const
|
|
40
|
+
const rootPkgPath = path.resolve(process.cwd(), "package.json");
|
|
41
|
+
const content = await readFile(rootPkgPath, "utf-8");
|
|
40
42
|
return JSON.parse(content).kici?.development === true;
|
|
41
43
|
} catch {
|
|
42
44
|
return false;
|
|
@@ -119,7 +119,8 @@ async function ensureRuntimeSymlinks(filePath) {
|
|
|
119
119
|
continue;
|
|
120
120
|
} catch {}
|
|
121
121
|
try {
|
|
122
|
-
const
|
|
122
|
+
const entry = import.meta.resolve(pkg);
|
|
123
|
+
const pkgDir = await findPackageRoot(fileURLToPath(entry));
|
|
123
124
|
const linkParent = path.dirname(linkPath);
|
|
124
125
|
if (linkParent !== nodeModulesDir) await fs.mkdir(linkParent, { recursive: true });
|
|
125
126
|
await fs.symlink(pkgDir, linkPath);
|
package/dist/format.js
CHANGED
|
@@ -6,12 +6,12 @@ import "./rolldown-runtime-ClRpJifh.js";
|
|
|
6
6
|
function formatRelativeTime(isoDate) {
|
|
7
7
|
const ms = Date.now() - new Date(isoDate).getTime();
|
|
8
8
|
if (ms < 0) return "just now";
|
|
9
|
-
const minutes = Math.floor(ms /
|
|
9
|
+
const minutes = Math.floor(ms / 6e4);
|
|
10
10
|
if (minutes < 1) return "just now";
|
|
11
11
|
if (minutes < 60) return `${minutes} minute${minutes === 1 ? "" : "s"} ago`;
|
|
12
|
-
const hours = Math.floor(ms /
|
|
12
|
+
const hours = Math.floor(ms / 36e5);
|
|
13
13
|
if (hours < 24) return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
|
14
|
-
const days = Math.floor(ms /
|
|
14
|
+
const days = Math.floor(ms / 864e5);
|
|
15
15
|
return `${days} day${days === 1 ? "" : "s"} ago`;
|
|
16
16
|
}
|
|
17
17
|
//#endregion
|
|
@@ -10,10 +10,16 @@ export interface ContextMetadata {
|
|
|
10
10
|
name: string;
|
|
11
11
|
keys: string[];
|
|
12
12
|
}
|
|
13
|
-
interface GenerateSecretsDtsOptions {
|
|
13
|
+
export interface GenerateSecretsDtsOptions {
|
|
14
14
|
contexts: ContextMetadata[];
|
|
15
15
|
endpoint: string;
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Mark the output as an offline stub written when the Platform could not be
|
|
18
|
+
* reached (unauthenticated, offline, or no active org). The header names it a
|
|
19
|
+
* stub instead of a source URL so a reader can tell it from a real snapshot,
|
|
20
|
+
* and the caller passes `contexts: []` so it augments no known keys.
|
|
21
|
+
*/
|
|
22
|
+
offline?: boolean;
|
|
17
23
|
}
|
|
18
24
|
/**
|
|
19
25
|
* Generate a .d.ts string from context metadata.
|
|
@@ -25,5 +31,4 @@ interface GenerateSecretsDtsOptions {
|
|
|
25
31
|
* @returns The .d.ts file content as a string
|
|
26
32
|
*/
|
|
27
33
|
export declare function generateSecretsDts(options: GenerateSecretsDtsOptions): string;
|
|
28
|
-
export {};
|
|
29
34
|
//# sourceMappingURL=secrets-dts.d.ts.map
|
|
@@ -34,11 +34,11 @@ function buildKeySourceMap(contexts) {
|
|
|
34
34
|
* @returns The .d.ts file content as a string
|
|
35
35
|
*/
|
|
36
36
|
function generateSecretsDts(options) {
|
|
37
|
-
const { contexts, endpoint,
|
|
37
|
+
const { contexts, endpoint, offline } = options;
|
|
38
38
|
const lines = [];
|
|
39
39
|
lines.push("// @generated by kici types -- DO NOT EDIT");
|
|
40
|
-
lines.push(
|
|
41
|
-
lines.push(`//
|
|
40
|
+
if (offline) lines.push("// Source: offline stub -- Platform unreachable, no known secret keys");
|
|
41
|
+
else lines.push(`// Source: ${endpoint}`);
|
|
42
42
|
lines.push("// Run `kici types` to refresh");
|
|
43
43
|
lines.push("");
|
|
44
44
|
lines.push("declare module '@kici-dev/sdk' {");
|
package/dist/hooks/installer.js
CHANGED
|
@@ -252,7 +252,8 @@ repos:
|
|
|
252
252
|
*/
|
|
253
253
|
async function resolveCommonGitDir(gitDir) {
|
|
254
254
|
try {
|
|
255
|
-
const
|
|
255
|
+
const commondirPath = path.join(gitDir, "commondir");
|
|
256
|
+
const commondir = (await readFile(commondirPath, "utf-8")).trim();
|
|
256
257
|
return path.resolve(gitDir, commondir);
|
|
257
258
|
} catch {
|
|
258
259
|
return gitDir;
|