@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
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Typed client for the Platform org-scoped dashboard API (the endpoints the
3
+ * web UI uses). Authenticated with the stored PAT + active org. This is the
4
+ * only place in the CLI that knows these routes.
5
+ */
6
+ import { z } from 'zod';
7
+ import { type RunListResponse, type RunListItem, type DiagnosticsInfrastructureResponse, type DiagnosticsSummaryResponse, type DashboardRunDetailApiResponse, type DashboardStepLogsApiResponse, type RegistrationItem } from '@kici-dev/engine';
8
+ import { type GlobalConfig } from './config.js';
9
+ export type DashboardErrorKind = 'not_logged_in' | 'no_active_org' | 'unauthorized' | 'forbidden' | 'not_found' | 'conflict' | 'cooldown' | 'orchestrator_offline' | 'http';
10
+ /** Typed error raised by every DashboardClient method on a non-2xx response. */
11
+ export declare class DashboardClientError extends Error {
12
+ readonly kind: DashboardErrorKind;
13
+ readonly status?: number | undefined;
14
+ constructor(kind: DashboardErrorKind, message: string, status?: number | undefined);
15
+ }
16
+ /** Filters accepted by the runs-list endpoint. */
17
+ export interface RunsListFilters {
18
+ status?: string;
19
+ workflow?: string;
20
+ branch?: string;
21
+ repo?: string;
22
+ trigger?: string;
23
+ source?: string;
24
+ since?: string;
25
+ page?: number;
26
+ }
27
+ /** Result of {@link DashboardClient.listRegistrations}. */
28
+ export interface RegistrationsListResult {
29
+ registrations: RegistrationItem[];
30
+ registryVersion: number;
31
+ registryUpdatedAt: string;
32
+ }
33
+ /** Filters accepted by the registrations-list endpoint. */
34
+ export interface RegistrationsListFilters {
35
+ triggerType?: string;
36
+ repoIdentifier?: string;
37
+ }
38
+ /**
39
+ * A secret context (environment) as surfaced to the developer CLI's
40
+ * `secrets list` / `types` commands. The orchestrator returns the per-env
41
+ * secret key names (never values) when `includeSecrets` is requested.
42
+ */
43
+ declare const environmentContextSchema: z.ZodObject<{
44
+ name: z.ZodString;
45
+ enabled: z.ZodBoolean;
46
+ allowLocalExecution: z.ZodBoolean;
47
+ secretKeys: z.ZodDefault<z.ZodArray<z.ZodString>>;
48
+ }, z.core.$strip>;
49
+ /** A secret context (environment) returned by {@link DashboardClient.listEnvironments}. */
50
+ export type EnvironmentContext = z.infer<typeof environmentContextSchema>;
51
+ export declare class DashboardClient {
52
+ private readonly endpoint;
53
+ private readonly token;
54
+ private readonly orgId;
55
+ private constructor();
56
+ static fromConfig(config: GlobalConfig): DashboardClient;
57
+ static load(): Promise<DashboardClient>;
58
+ private orgUrl;
59
+ private request;
60
+ private throwForStatus;
61
+ /** Generic GET helper used by typed methods (and tests). */
62
+ getJson(path: string): Promise<unknown>;
63
+ /** Generic POST helper used by typed methods (and tests). */
64
+ postJson(path: string, body?: unknown): Promise<unknown>;
65
+ getDiagnosticsSummary(): Promise<DiagnosticsSummaryResponse>;
66
+ getInfrastructure(): Promise<DiagnosticsInfrastructureResponse>;
67
+ listRuns(filters?: RunsListFilters): Promise<RunListResponse>;
68
+ getRun(runId: string): Promise<RunListItem>;
69
+ getRunDetail(runId: string): Promise<DashboardRunDetailApiResponse>;
70
+ getStepLogs(runId: string, jobId: string, stepIndex: number): Promise<DashboardStepLogsApiResponse>;
71
+ rerunRun(runId: string): Promise<{
72
+ newRunId: string;
73
+ }>;
74
+ cancelRun(runId: string, force: boolean): Promise<{
75
+ cancelledJobs?: number;
76
+ }>;
77
+ cancelByBranch(branch: string): Promise<{
78
+ cancelledRuns?: number;
79
+ }>;
80
+ /** List the org's permanently registered workflows (GET /registrations). */
81
+ listRegistrations(filters?: RegistrationsListFilters): Promise<RegistrationsListResult>;
82
+ /**
83
+ * List the org's environments as secret contexts (GET /environments).
84
+ *
85
+ * Pass `includeSecrets` to have the orchestrator attach each environment's
86
+ * reachable secret key names (never values). Used by `kici secrets list`
87
+ * and `kici types`.
88
+ */
89
+ listEnvironments(includeSecrets?: boolean): Promise<EnvironmentContext[]>;
90
+ }
91
+ export {};
92
+ //# sourceMappingURL=dashboard-client.d.ts.map
@@ -0,0 +1,168 @@
1
+ import "../chunk-BTugEXQM.js";
2
+ import { loadGlobalConfig } from "./config.js";
3
+ import { dashboardRunDetailApiResponseSchema, dashboardStepLogsApiResponseSchema, diagnosticsInfrastructureResponseSchema, diagnosticsSummaryResponseSchema, registrationItemSchema, runListItemSchema, runListResponseSchema } from "@kici-dev/engine";
4
+ import { z } from "zod";
5
+ //#region src/remote/dashboard-client.ts
6
+ /**
7
+ * Typed client for the Platform org-scoped dashboard API (the endpoints the
8
+ * web UI uses). Authenticated with the stored PAT + active org. This is the
9
+ * only place in the CLI that knows these routes.
10
+ */
11
+ /** Typed error raised by every DashboardClient method on a non-2xx response. */
12
+ var DashboardClientError = class extends Error {
13
+ kind;
14
+ status;
15
+ constructor(kind, message, status) {
16
+ super(message);
17
+ this.kind = kind;
18
+ this.status = status;
19
+ this.name = "DashboardClientError";
20
+ }
21
+ };
22
+ const singleRunSchema = z.object({ run: runListItemSchema });
23
+ const rerunResponseSchema = z.object({ newRunId: z.string() });
24
+ const cancelResponseSchema = z.object({ cancelledJobs: z.number().optional() });
25
+ const cancelByBranchResponseSchema = z.object({ cancelledRuns: z.number().optional() });
26
+ const registrationsListSchema = z.object({
27
+ registrations: z.array(registrationItemSchema).default([]),
28
+ registryVersion: z.number(),
29
+ registryUpdatedAt: z.string()
30
+ });
31
+ /**
32
+ * A secret context (environment) as surfaced to the developer CLI's
33
+ * `secrets list` / `types` commands. The orchestrator returns the per-env
34
+ * secret key names (never values) when `includeSecrets` is requested.
35
+ */
36
+ const environmentContextSchema = z.object({
37
+ name: z.string(),
38
+ enabled: z.boolean(),
39
+ allowLocalExecution: z.boolean(),
40
+ secretKeys: z.array(z.string()).default([])
41
+ });
42
+ const environmentsListSchema = z.object({ environments: z.array(environmentContextSchema).default([]) });
43
+ const STATUS_ERROR_MAP = {
44
+ 401: ["unauthorized", "Authentication failed. Run `kici login` to re-authenticate."],
45
+ 403: ["forbidden", "Access denied."],
46
+ 404: ["not_found", "Not found."],
47
+ 409: ["conflict", "Already in a terminal state."],
48
+ 429: ["cooldown", "Rate limited — wait and retry."],
49
+ 503: ["orchestrator_offline", "Orchestrator offline — try again shortly."],
50
+ 504: ["orchestrator_offline", "Orchestrator timed out — try again shortly."]
51
+ };
52
+ var DashboardClient = class DashboardClient {
53
+ endpoint;
54
+ token;
55
+ orgId;
56
+ constructor(endpoint, token, orgId) {
57
+ this.endpoint = endpoint;
58
+ this.token = token;
59
+ this.orgId = orgId;
60
+ }
61
+ static fromConfig(config) {
62
+ const token = config.pat ?? config.token;
63
+ const endpoint = config.platformEndpoint ?? config.endpoint;
64
+ if (!token) throw new DashboardClientError("not_logged_in", "Not logged in. Run `kici login` first.");
65
+ if (!endpoint) throw new DashboardClientError("not_logged_in", "No endpoint configured. Run `kici login` first.");
66
+ if (!config.activeOrgId) throw new DashboardClientError("no_active_org", "No active organization. Run `kici org use <name>` to set one.");
67
+ return new DashboardClient(endpoint.replace(/\/$/, ""), token, config.activeOrgId);
68
+ }
69
+ static async load() {
70
+ return DashboardClient.fromConfig(await loadGlobalConfig());
71
+ }
72
+ orgUrl(path) {
73
+ return `${this.endpoint}/api/v1/orgs/${this.orgId}/${path.replace(/^\//, "")}`;
74
+ }
75
+ async request(method, path, body) {
76
+ const res = await fetch(this.orgUrl(path), {
77
+ method,
78
+ headers: {
79
+ "Content-Type": "application/json",
80
+ Authorization: `Bearer ${this.token}`
81
+ },
82
+ body: body === void 0 ? void 0 : JSON.stringify(body)
83
+ }).catch((err) => {
84
+ throw new DashboardClientError("http", `Network error: ${String(err)}`);
85
+ });
86
+ if (res.ok) {
87
+ const text = await res.text();
88
+ return text ? JSON.parse(text) : {};
89
+ }
90
+ return this.throwForStatus(res);
91
+ }
92
+ async throwForStatus(res) {
93
+ let detail;
94
+ try {
95
+ detail = (await res.json()).error;
96
+ } catch {}
97
+ const [kind, fallback] = STATUS_ERROR_MAP[res.status] ?? ["http", `Request failed (${res.status}).`];
98
+ throw new DashboardClientError(kind, detail ?? fallback, res.status);
99
+ }
100
+ /** Generic GET helper used by typed methods (and tests). */
101
+ async getJson(path) {
102
+ return this.request("GET", path);
103
+ }
104
+ /** Generic POST helper used by typed methods (and tests). */
105
+ async postJson(path, body) {
106
+ return this.request("POST", path, body);
107
+ }
108
+ async getDiagnosticsSummary() {
109
+ return diagnosticsSummaryResponseSchema.parse(await this.getJson("/diagnostics"));
110
+ }
111
+ async getInfrastructure() {
112
+ return diagnosticsInfrastructureResponseSchema.parse(await this.getJson("/diagnostics/infrastructure"));
113
+ }
114
+ async listRuns(filters = {}) {
115
+ const qs = new URLSearchParams();
116
+ if (filters.status) qs.set("status", filters.status);
117
+ if (filters.workflow) qs.set("workflow", filters.workflow);
118
+ if (filters.branch) qs.set("branch", filters.branch);
119
+ if (filters.repo) qs.set("repository", filters.repo);
120
+ if (filters.trigger) qs.set("triggerType", filters.trigger);
121
+ if (filters.source) qs.set("source", filters.source);
122
+ if (filters.since) qs.set("since", filters.since);
123
+ if (filters.page) qs.set("page", String(filters.page));
124
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
125
+ return runListResponseSchema.parse(await this.getJson(`/runs${suffix}`));
126
+ }
127
+ async getRun(runId) {
128
+ return singleRunSchema.parse(await this.getJson(`/runs/${runId}`)).run;
129
+ }
130
+ async getRunDetail(runId) {
131
+ return dashboardRunDetailApiResponseSchema.parse(await this.getJson(`/runs/${runId}/detail`));
132
+ }
133
+ async getStepLogs(runId, jobId, stepIndex) {
134
+ return dashboardStepLogsApiResponseSchema.parse(await this.getJson(`/runs/${runId}/jobs/${jobId}/steps/${stepIndex}/logs`));
135
+ }
136
+ async rerunRun(runId) {
137
+ return rerunResponseSchema.parse(await this.postJson(`/runs/${runId}/rerun`));
138
+ }
139
+ async cancelRun(runId, force) {
140
+ return cancelResponseSchema.parse(await this.postJson(`/runs/${runId}/cancel`, { force }));
141
+ }
142
+ async cancelByBranch(branch) {
143
+ return cancelByBranchResponseSchema.parse(await this.postJson("/runs/cancel-by-branch", { branch }));
144
+ }
145
+ /** List the org's permanently registered workflows (GET /registrations). */
146
+ async listRegistrations(filters = {}) {
147
+ const qs = new URLSearchParams();
148
+ if (filters.triggerType) qs.set("triggerType", filters.triggerType);
149
+ if (filters.repoIdentifier) qs.set("repoIdentifier", filters.repoIdentifier);
150
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
151
+ return registrationsListSchema.parse(await this.getJson(`/registrations${suffix}`));
152
+ }
153
+ /**
154
+ * List the org's environments as secret contexts (GET /environments).
155
+ *
156
+ * Pass `includeSecrets` to have the orchestrator attach each environment's
157
+ * reachable secret key names (never values). Used by `kici secrets list`
158
+ * and `kici types`.
159
+ */
160
+ async listEnvironments(includeSecrets = false) {
161
+ const suffix = includeSecrets ? "?includeSecrets=true" : "";
162
+ return environmentsListSchema.parse(await this.getJson(`/environments${suffix}`)).environments;
163
+ }
164
+ };
165
+ //#endregion
166
+ export { DashboardClient, DashboardClientError };
167
+
168
+ //# sourceMappingURL=dashboard-client.js.map
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import fs from "node:fs/promises";
3
3
  import { deriveSharedSecret } from "@kici-dev/core";
4
4
  import crypto from "node:crypto";
@@ -11,7 +11,6 @@ import crypto from "node:crypto";
11
11
  * Same pattern as engine/src/secrets/crypto.ts.
12
12
  */
13
13
  const IV_LENGTH = 12;
14
- const AUTH_TAG_LENGTH = 16;
15
14
  /**
16
15
  * Generate an ephemeral X25519 keypair.
17
16
  * Keys are exported as DER buffers for compact wire format.
@@ -72,8 +71,8 @@ async function decryptTarball(encryptedPath, cliPublicKey, orchestratorPrivateKe
72
71
  const aesKey = deriveSharedSecret(orchestratorPrivateKey, cliPublicKey);
73
72
  const encrypted = await fs.readFile(encryptedPath);
74
73
  const iv = encrypted.subarray(0, IV_LENGTH);
75
- const authTag = encrypted.subarray(IV_LENGTH, IV_LENGTH + AUTH_TAG_LENGTH);
76
- const ciphertext = encrypted.subarray(IV_LENGTH + AUTH_TAG_LENGTH);
74
+ const authTag = encrypted.subarray(IV_LENGTH, 28);
75
+ const ciphertext = encrypted.subarray(28);
77
76
  const decipher = crypto.createDecipheriv("aes-256-gcm", aesKey, iv);
78
77
  decipher.setAuthTag(authTag);
79
78
  const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { formatRelativeTime } from "../format.js";
3
3
  import { getConfigDir } from "./config.js";
4
4
  import path from "node:path";
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { discoverOidcEndpoints } from "./oidc-discovery.js";
3
3
  import pc from "picocolors";
4
4
  import { toErrorMessage } from "@kici-dev/core";
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { toErrorMessage } from "@kici-dev/core";
3
3
  //#region src/remote/oidc-discovery.ts
4
4
  const cache = /* @__PURE__ */ new Map();
@@ -1,4 +1,4 @@
1
- import "../../chunk-gOLHoazu.js";
1
+ import "../../chunk-BTugEXQM.js";
2
2
  //#region src/remote/output/json.ts
3
3
  /**
4
4
  * Format run results as structured JSON with 2-space indentation.
@@ -1,4 +1,4 @@
1
- import "../../chunk-gOLHoazu.js";
1
+ import "../../chunk-BTugEXQM.js";
2
2
  //#region src/remote/output/junit.ts
3
3
  /**
4
4
  * Format run results as JUnit XML following the standard schema.
@@ -1,4 +1,4 @@
1
- import "../../chunk-gOLHoazu.js";
1
+ import "../../chunk-BTugEXQM.js";
2
2
  import pc from "picocolors";
3
3
  import { formatDuration } from "@kici-dev/core";
4
4
  //#region src/remote/output/streaming.ts
@@ -1,4 +1,4 @@
1
- import "../../chunk-gOLHoazu.js";
1
+ import "../../chunk-BTugEXQM.js";
2
2
  import pc from "picocolors";
3
3
  import { formatDuration } from "@kici-dev/core";
4
4
  //#region src/remote/output/summary.ts
@@ -0,0 +1,142 @@
1
+ /**
2
+ * PAT-authenticated client for the Platform's dev-facing run-remote routes.
3
+ *
4
+ * This is the developer CLI's contact point for `kici run remote` and its
5
+ * companion commands. It targets the Platform (`config.platformEndpoint`), which
6
+ * relays each control request over the WS dashboard-proxy to the org's
7
+ * orchestrator cluster — the orchestrator's own HTTP API is never reached
8
+ * directly (it may live on a hidden network).
9
+ *
10
+ * The overlay tarball does NOT flow through here: `initUpload` returns an
11
+ * external presigned URL the CLI PUTs to directly (data plane).
12
+ */
13
+ export declare class AuthenticationError extends Error {
14
+ constructor(message?: string);
15
+ }
16
+ export declare class AccessDeniedError extends Error {
17
+ constructor(message?: string);
18
+ }
19
+ export declare class NotFoundError extends Error {
20
+ constructor(message?: string);
21
+ }
22
+ export declare class ConnectionError extends Error {
23
+ endpoint?: string | undefined;
24
+ constructor(message: string, endpoint?: string | undefined);
25
+ }
26
+ /**
27
+ * Thrown when the org has more than one connected orchestrator cluster and the
28
+ * developer did not pick one (no `--orchestrator` flag, no per-org default).
29
+ * Carries the list of connected cluster names so the CLI can print the choice.
30
+ */
31
+ export declare class AmbiguousClusterError extends Error {
32
+ clusters: string[];
33
+ constructor(clusters: string[], message?: string);
34
+ }
35
+ /** Thrown when the org has no connected orchestrator cluster. */
36
+ export declare class NoClusterError extends Error {
37
+ constructor(message?: string);
38
+ }
39
+ export interface PlatformUploadInitInput {
40
+ sha?: string;
41
+ fileCount?: number;
42
+ compressedSize?: number;
43
+ }
44
+ export interface PlatformUploadInitResponse {
45
+ uploadId: string;
46
+ signedUrl: string;
47
+ publicKey: string;
48
+ expiresIn: number;
49
+ }
50
+ export interface PlatformTriggerInput {
51
+ fixtureId: string;
52
+ event: {
53
+ type: string;
54
+ action?: string;
55
+ targetBranch: string;
56
+ sourceBranch?: string;
57
+ payload: Record<string, unknown>;
58
+ changedFiles?: string[];
59
+ };
60
+ workflowName?: string;
61
+ uploadId?: string;
62
+ /**
63
+ * Ephemeral X25519 public key the CLI used to encrypt the overlay tarball.
64
+ * The orchestrator pairs it with the upload's stored private key to decrypt
65
+ * the overlay. Distinct from `encryptedSecretsKey` (the optional secrets key).
66
+ */
67
+ cliPublicKey?: string;
68
+ inlineLockFile?: string;
69
+ fullRepo?: boolean;
70
+ secrets?: Record<string, string>;
71
+ encryptedSecrets?: string;
72
+ encryptedSecretsKey?: string;
73
+ }
74
+ export interface PlatformTriggerResponse {
75
+ runId: string;
76
+ status: 'accepted' | 'rejected';
77
+ reason?: string;
78
+ jobIds?: string[];
79
+ }
80
+ export interface PlatformRunStatusResponse {
81
+ runId: string;
82
+ status: string;
83
+ jobs: Array<{
84
+ jobId: string;
85
+ jobName: string;
86
+ status: string;
87
+ exitCode?: number | null;
88
+ errorMessage?: string | null;
89
+ }>;
90
+ done: boolean;
91
+ }
92
+ export interface PlatformRunLogsResponse {
93
+ lines: string[];
94
+ nextCursor: number;
95
+ done: boolean;
96
+ }
97
+ export interface PlatformCancelResponse {
98
+ cancelled: boolean;
99
+ }
100
+ interface PlatformRunClientConfig {
101
+ /** Platform base URL, e.g. `https://api.kici.dev`. */
102
+ platformEndpoint: string;
103
+ /** Personal access token (PAT) used as the bearer credential. */
104
+ token: string;
105
+ }
106
+ /** Cluster targeting for a run-remote request. */
107
+ export interface ClusterTarget {
108
+ /** Explicit `--orchestrator <name>` pick. */
109
+ orchestrator?: string;
110
+ /** Per-org default cluster (`config.defaultClusters[orgId]`). */
111
+ defaultCluster?: string;
112
+ }
113
+ /**
114
+ * Client for the Platform's `/api/v1/orgs/:orgId/test/*` relay routes.
115
+ */
116
+ export declare class PlatformRunClient {
117
+ private readonly baseUrl;
118
+ private readonly token;
119
+ constructor(config: PlatformRunClientConfig);
120
+ /** POST /test/uploads/init — mint an external presigned upload URL. */
121
+ initUpload(orgId: string, target: ClusterTarget, body: PlatformUploadInitInput): Promise<PlatformUploadInitResponse>;
122
+ /** POST /test/trigger — trigger a remote run. */
123
+ trigger(orgId: string, target: ClusterTarget, body: PlatformTriggerInput): Promise<PlatformTriggerResponse>;
124
+ /** GET /test/runs/:runId — run-status snapshot. */
125
+ runStatus(orgId: string, runId: string, target?: ClusterTarget): Promise<PlatformRunStatusResponse>;
126
+ /** GET /test/runs/:runId/logs?cursor=<n> — next log chunk from a cursor. */
127
+ runLogs(orgId: string, runId: string, cursor: number, target?: ClusterTarget): Promise<PlatformRunLogsResponse>;
128
+ /** POST /test/runs/:runId/cancel — cancel a run. */
129
+ cancel(orgId: string, runId: string, target?: ClusterTarget): Promise<PlatformCancelResponse>;
130
+ /**
131
+ * Make a PAT-authenticated request to the Platform.
132
+ *
133
+ * Classifies errors: 401 → AuthenticationError, 403 → AccessDeniedError,
134
+ * 404 → NotFoundError, 422 ambiguous_cluster → AmbiguousClusterError,
135
+ * 422 no_cluster → NoClusterError. Network failures → ConnectionError.
136
+ */
137
+ private request;
138
+ /** Map a non-OK Platform response to a typed error. Always throws. */
139
+ private throwForStatus;
140
+ }
141
+ export {};
142
+ //# sourceMappingURL=platform-client.d.ts.map
@@ -0,0 +1,187 @@
1
+ import "../chunk-BTugEXQM.js";
2
+ import { toErrorMessage } from "@kici-dev/core";
3
+ //#region src/remote/platform-client.ts
4
+ /**
5
+ * PAT-authenticated client for the Platform's dev-facing run-remote routes.
6
+ *
7
+ * This is the developer CLI's contact point for `kici run remote` and its
8
+ * companion commands. It targets the Platform (`config.platformEndpoint`), which
9
+ * relays each control request over the WS dashboard-proxy to the org's
10
+ * orchestrator cluster — the orchestrator's own HTTP API is never reached
11
+ * directly (it may live on a hidden network).
12
+ *
13
+ * The overlay tarball does NOT flow through here: `initUpload` returns an
14
+ * external presigned URL the CLI PUTs to directly (data plane).
15
+ */
16
+ var AuthenticationError = class extends Error {
17
+ constructor(message = "Invalid or expired token. Run `kici login` to authenticate.") {
18
+ super(message);
19
+ this.name = "AuthenticationError";
20
+ }
21
+ };
22
+ var AccessDeniedError = class extends Error {
23
+ constructor(message = "Access denied") {
24
+ super(message);
25
+ this.name = "AccessDeniedError";
26
+ }
27
+ };
28
+ var NotFoundError = class extends Error {
29
+ constructor(message = "Resource not found") {
30
+ super(message);
31
+ this.name = "NotFoundError";
32
+ }
33
+ };
34
+ var ConnectionError = class extends Error {
35
+ endpoint;
36
+ constructor(message, endpoint) {
37
+ super(message);
38
+ this.endpoint = endpoint;
39
+ this.name = "ConnectionError";
40
+ }
41
+ };
42
+ /**
43
+ * Thrown when the org has more than one connected orchestrator cluster and the
44
+ * developer did not pick one (no `--orchestrator` flag, no per-org default).
45
+ * Carries the list of connected cluster names so the CLI can print the choice.
46
+ */
47
+ var AmbiguousClusterError = class extends Error {
48
+ clusters;
49
+ constructor(clusters, message = "Multiple orchestrator clusters are connected — pass --orchestrator <name>") {
50
+ super(message);
51
+ this.clusters = clusters;
52
+ this.name = "AmbiguousClusterError";
53
+ }
54
+ };
55
+ /** Thrown when the org has no connected orchestrator cluster. */
56
+ var NoClusterError = class extends Error {
57
+ constructor(message = "No orchestrator is connected for this organization.") {
58
+ super(message);
59
+ this.name = "NoClusterError";
60
+ }
61
+ };
62
+ /**
63
+ * Append the cluster-targeting query params the Platform routes understand:
64
+ * `?orchestrator=<cluster>` (explicit pick) and `?defaultCluster=<cluster>`
65
+ * (the CLI's per-org default). Either may be omitted to let the Platform
66
+ * sole-select or return a 422 with the cluster list.
67
+ */
68
+ function clusterQuery(orchestrator, defaultCluster) {
69
+ const params = new URLSearchParams();
70
+ if (orchestrator) params.set("orchestrator", orchestrator);
71
+ if (defaultCluster) params.set("defaultCluster", defaultCluster);
72
+ const q = params.toString();
73
+ return q ? `?${q}` : "";
74
+ }
75
+ /**
76
+ * Client for the Platform's `/api/v1/orgs/:orgId/test/*` relay routes.
77
+ */
78
+ var PlatformRunClient = class {
79
+ baseUrl;
80
+ token;
81
+ constructor(config) {
82
+ this.baseUrl = config.platformEndpoint.replace(/\/+$/, "");
83
+ this.token = config.token;
84
+ }
85
+ /** POST /test/uploads/init — mint an external presigned upload URL. */
86
+ async initUpload(orgId, target, body) {
87
+ const path = `/api/v1/orgs/${orgId}/test/uploads/init${clusterQuery(target.orchestrator, target.defaultCluster)}`;
88
+ return await (await this.request(path, {
89
+ method: "POST",
90
+ body: JSON.stringify(body)
91
+ })).json();
92
+ }
93
+ /** POST /test/trigger — trigger a remote run. */
94
+ async trigger(orgId, target, body) {
95
+ const path = `/api/v1/orgs/${orgId}/test/trigger${clusterQuery(target.orchestrator, target.defaultCluster)}`;
96
+ return await (await this.request(path, {
97
+ method: "POST",
98
+ body: JSON.stringify(body)
99
+ })).json();
100
+ }
101
+ /** GET /test/runs/:runId — run-status snapshot. */
102
+ async runStatus(orgId, runId, target = {}) {
103
+ const path = `/api/v1/orgs/${orgId}/test/runs/${runId}${clusterQuery(target.orchestrator, target.defaultCluster)}`;
104
+ return await (await this.request(path, { method: "GET" })).json();
105
+ }
106
+ /** GET /test/runs/:runId/logs?cursor=<n> — next log chunk from a cursor. */
107
+ async runLogs(orgId, runId, cursor, target = {}) {
108
+ const params = new URLSearchParams();
109
+ params.set("cursor", String(cursor));
110
+ if (target.orchestrator) params.set("orchestrator", target.orchestrator);
111
+ if (target.defaultCluster) params.set("defaultCluster", target.defaultCluster);
112
+ const path = `/api/v1/orgs/${orgId}/test/runs/${runId}/logs?${params.toString()}`;
113
+ return await (await this.request(path, { method: "GET" })).json();
114
+ }
115
+ /** POST /test/runs/:runId/cancel — cancel a run. */
116
+ async cancel(orgId, runId, target = {}) {
117
+ const path = `/api/v1/orgs/${orgId}/test/runs/${runId}/cancel${clusterQuery(target.orchestrator, target.defaultCluster)}`;
118
+ return await (await this.request(path, {
119
+ method: "POST",
120
+ body: JSON.stringify({})
121
+ })).json();
122
+ }
123
+ /**
124
+ * Make a PAT-authenticated request to the Platform.
125
+ *
126
+ * Classifies errors: 401 → AuthenticationError, 403 → AccessDeniedError,
127
+ * 404 → NotFoundError, 422 ambiguous_cluster → AmbiguousClusterError,
128
+ * 422 no_cluster → NoClusterError. Network failures → ConnectionError.
129
+ */
130
+ async request(path, init) {
131
+ const url = `${this.baseUrl}${path}`;
132
+ let response;
133
+ try {
134
+ response = await fetch(url, {
135
+ ...init,
136
+ headers: {
137
+ "Content-Type": "application/json",
138
+ Authorization: `Bearer ${this.token}`,
139
+ ...init.headers
140
+ }
141
+ });
142
+ } catch (err) {
143
+ throw new ConnectionError(`Failed to connect to the Platform at ${this.baseUrl}: ${toErrorMessage(err)}`, this.baseUrl);
144
+ }
145
+ if (response.ok) return response;
146
+ await this.throwForStatus(response);
147
+ return response;
148
+ }
149
+ /** Map a non-OK Platform response to a typed error. Always throws. */
150
+ async throwForStatus(response) {
151
+ if (response.status === 401) throw new AuthenticationError();
152
+ if (response.status === 403) throw new AccessDeniedError(await readError(response, "Access denied"));
153
+ if (response.status === 404) throw new NotFoundError(await readError(response, "Resource not found"));
154
+ if (response.status === 422) {
155
+ const body = await readJson(response);
156
+ if (body.error === "ambiguous_cluster") throw new AmbiguousClusterError(body.clusters ?? [], body.message);
157
+ if (body.error === "no_cluster") throw new NoClusterError(body.message);
158
+ throw new Error(body.reason ?? body.message ?? body.error ?? "Request rejected (422)");
159
+ }
160
+ throw new Error(`Request failed with status ${response.status}: ${await readError(response, "")}`);
161
+ }
162
+ };
163
+ /** Read a JSON body, returning `{}` on any parse failure. */
164
+ async function readJson(response) {
165
+ try {
166
+ return await response.json();
167
+ } catch {
168
+ return {};
169
+ }
170
+ }
171
+ /** Read the `error` field of a JSON body, falling back to text then a default. */
172
+ async function readError(response, fallback) {
173
+ try {
174
+ const body = await response.clone().json();
175
+ if (body.error) return body.error;
176
+ if (body.message) return body.message;
177
+ } catch {}
178
+ try {
179
+ const text = await response.text();
180
+ if (text) return text;
181
+ } catch {}
182
+ return fallback;
183
+ }
184
+ //#endregion
185
+ export { AccessDeniedError, AmbiguousClusterError, AuthenticationError, ConnectionError, NoClusterError, NotFoundError, PlatformRunClient };
186
+
187
+ //# sourceMappingURL=platform-client.js.map
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  //#region src/remote/prod-defaults.ts
3
3
  /**
4
4
  * Production defaults for the `kici login` OAuth flow. When the matching