@kici-dev/compiler 0.0.0 → 0.1.1

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 (221) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +1 -6
  3. package/dist/assets/api-TJJVHrjC.json +118 -0
  4. package/dist/assets/descriptor-BTtjzN9L.json +1382 -0
  5. package/dist/assets/package-BpQF9kR8.json +74 -0
  6. package/dist/assets/package-Ceo2h27X.json +89 -0
  7. package/dist/assets/source_context-D0atuL28.json +20 -0
  8. package/dist/assets/type-BFqO8SCZ.json +202 -0
  9. package/dist/auth/headless-detect.d.ts +14 -0
  10. package/dist/auth/headless-detect.js +25 -0
  11. package/dist/chunk-gOLHoazu.js +4 -0
  12. package/dist/cli.d.ts +3 -0
  13. package/dist/cli.js +193 -0
  14. package/dist/commands/cancel.d.ts +22 -0
  15. package/dist/commands/cancel.js +124 -0
  16. package/dist/commands/compile.d.ts +17 -0
  17. package/dist/commands/compile.js +99 -0
  18. package/dist/commands/docs.d.ts +26 -0
  19. package/dist/commands/docs.js +60 -0
  20. package/dist/commands/drain-worker.d.ts +19 -0
  21. package/dist/commands/drain-worker.js +45 -0
  22. package/dist/commands/endpoints.d.ts +53 -0
  23. package/dist/commands/endpoints.js +185 -0
  24. package/dist/commands/fixture.d.ts +14 -0
  25. package/dist/commands/fixture.js +104 -0
  26. package/dist/commands/hook.d.ts +20 -0
  27. package/dist/commands/hook.js +97 -0
  28. package/dist/commands/index.d.ts +33 -0
  29. package/dist/commands/index.js +20 -0
  30. package/dist/commands/init.d.ts +35 -0
  31. package/dist/commands/init.js +393 -0
  32. package/dist/commands/login.d.ts +23 -0
  33. package/dist/commands/login.js +144 -0
  34. package/dist/commands/logout.d.ts +18 -0
  35. package/dist/commands/logout.js +55 -0
  36. package/dist/commands/org.d.ts +27 -0
  37. package/dist/commands/org.js +126 -0
  38. package/dist/commands/run.d.ts +21 -0
  39. package/dist/commands/run.js +562 -0
  40. package/dist/commands/secrets-list.d.ts +16 -0
  41. package/dist/commands/secrets-list.js +85 -0
  42. package/dist/commands/status.d.ts +30 -0
  43. package/dist/commands/status.js +210 -0
  44. package/dist/commands/test.d.ts +61 -0
  45. package/dist/commands/test.js +220 -0
  46. package/dist/commands/types.d.ts +18 -0
  47. package/dist/commands/types.js +74 -0
  48. package/dist/commands/watch.d.ts +14 -0
  49. package/dist/commands/watch.js +97 -0
  50. package/dist/commands/workflows.d.ts +28 -0
  51. package/dist/commands/workflows.js +154 -0
  52. package/dist/comment-created.json +30 -0
  53. package/dist/create-branch.json +17 -0
  54. package/dist/delete-branch.json +15 -0
  55. package/dist/dispatch.json +15 -0
  56. package/dist/errors/capability-gap.d.ts +50 -0
  57. package/dist/errors/capability-gap.js +54 -0
  58. package/dist/errors/codes.d.ts +25 -0
  59. package/dist/errors/formatter.d.ts +32 -0
  60. package/dist/errors/formatter.js +35 -0
  61. package/dist/errors/index.d.ts +5 -0
  62. package/dist/errors/index.js +4 -0
  63. package/dist/execution/executor.d.ts +61 -0
  64. package/dist/execution/executor.js +230 -0
  65. package/dist/execution/index.d.ts +4 -0
  66. package/dist/execution/index.js +3 -0
  67. package/dist/execution/sdk-alias.d.ts +33 -0
  68. package/dist/execution/sdk-alias.js +102 -0
  69. package/dist/fixtures/compiler.d.ts +47 -0
  70. package/dist/fixtures/compiler.js +177 -0
  71. package/dist/fixtures/defaults/comment-created.json +30 -0
  72. package/dist/fixtures/defaults/create-branch.json +17 -0
  73. package/dist/fixtures/defaults/delete-branch.json +15 -0
  74. package/dist/fixtures/defaults/dispatch.json +15 -0
  75. package/dist/fixtures/defaults/fork.json +19 -0
  76. package/dist/fixtures/defaults/index.d.ts +16 -0
  77. package/dist/fixtures/defaults/index.js +105 -0
  78. package/dist/fixtures/defaults/index.ts +145 -0
  79. package/dist/fixtures/defaults/pr-closed.json +28 -0
  80. package/dist/fixtures/defaults/pr-opened.json +27 -0
  81. package/dist/fixtures/defaults/pr-reopened.json +27 -0
  82. package/dist/fixtures/defaults/pr-synchronize.json +27 -0
  83. package/dist/fixtures/defaults/push.json +16 -0
  84. package/dist/fixtures/defaults/release-published.json +23 -0
  85. package/dist/fixtures/defaults/review-comment-created.json +36 -0
  86. package/dist/fixtures/defaults/review-submitted.json +35 -0
  87. package/dist/fixtures/defaults/star-created.json +15 -0
  88. package/dist/fixtures/defaults/status.json +26 -0
  89. package/dist/fixtures/defaults/tag-push.json +20 -0
  90. package/dist/fixtures/defaults/watch-started.json +15 -0
  91. package/dist/fixtures/defaults/workflow-run-completed.json +23 -0
  92. package/dist/fork.json +19 -0
  93. package/dist/format.d.ts +5 -0
  94. package/dist/format.js +20 -0
  95. package/dist/generators/secrets-dts.d.ts +29 -0
  96. package/dist/generators/secrets-dts.js +67 -0
  97. package/dist/hooks/detector.d.ts +39 -0
  98. package/dist/hooks/detector.js +133 -0
  99. package/dist/hooks/index.d.ts +6 -0
  100. package/dist/hooks/index.js +5 -0
  101. package/dist/hooks/installer.d.ts +24 -0
  102. package/dist/hooks/installer.js +328 -0
  103. package/dist/hooks/templates.d.ts +26 -0
  104. package/dist/hooks/templates.js +63 -0
  105. package/dist/index.d.ts +12 -0
  106. package/dist/index.js +12 -0
  107. package/dist/llm-context/llms-full.txt +9974 -0
  108. package/dist/llm-context/llms.txt +61 -0
  109. package/dist/local-executor/dag-scheduler.d.ts +44 -0
  110. package/dist/local-executor/dag-scheduler.js +183 -0
  111. package/dist/local-executor/index.d.ts +23 -0
  112. package/dist/local-executor/index.js +309 -0
  113. package/dist/local-executor/job-runner.d.ts +40 -0
  114. package/dist/local-executor/job-runner.js +307 -0
  115. package/dist/local-executor/output-streamer.d.ts +31 -0
  116. package/dist/local-executor/output-streamer.js +166 -0
  117. package/dist/local-executor/payload-generator.d.ts +16 -0
  118. package/dist/local-executor/payload-generator.js +138 -0
  119. package/dist/local-executor/picker.d.ts +33 -0
  120. package/dist/local-executor/picker.js +109 -0
  121. package/dist/local-executor/secret-loader.d.ts +18 -0
  122. package/dist/local-executor/secret-loader.js +105 -0
  123. package/dist/local-executor/types.d.ts +80 -0
  124. package/dist/local-executor/types.js +2 -0
  125. package/dist/local-executor/workflow-lock.d.ts +81 -0
  126. package/dist/local-executor/workflow-lock.js +0 -0
  127. package/dist/lockfile/generator.d.ts +39 -0
  128. package/dist/lockfile/generator.js +688 -0
  129. package/dist/lockfile/hash-files.d.ts +14 -0
  130. package/dist/lockfile/hash-files.js +50 -0
  131. package/dist/lockfile/hasher.d.ts +36 -0
  132. package/dist/lockfile/hasher.js +46 -0
  133. package/dist/lockfile/index.d.ts +3 -0
  134. package/dist/lockfile/index.js +4 -0
  135. package/dist/lockfile/purity-analyzer.d.ts +25 -0
  136. package/dist/lockfile/purity-analyzer.js +204 -0
  137. package/dist/package-F7UXSDHW.json +74 -0
  138. package/dist/postinstall.d.ts +9 -0
  139. package/dist/postinstall.js +60 -0
  140. package/dist/pr-closed.json +28 -0
  141. package/dist/pr-opened.json +27 -0
  142. package/dist/pr-reopened.json +27 -0
  143. package/dist/pr-synchronize.json +27 -0
  144. package/dist/push.json +16 -0
  145. package/dist/release-published.json +23 -0
  146. package/dist/remote/client.d.ts +204 -0
  147. package/dist/remote/client.js +203 -0
  148. package/dist/remote/config.d.ts +54 -0
  149. package/dist/remote/config.js +92 -0
  150. package/dist/remote/encryption.d.ts +35 -0
  151. package/dist/remote/encryption.js +87 -0
  152. package/dist/remote/history.d.ts +91 -0
  153. package/dist/remote/history.js +146 -0
  154. package/dist/remote/oauth.d.ts +65 -0
  155. package/dist/remote/oauth.js +302 -0
  156. package/dist/remote/observer.d.ts +81 -0
  157. package/dist/remote/observer.js +174 -0
  158. package/dist/remote/output/json.d.ts +13 -0
  159. package/dist/remote/output/json.js +36 -0
  160. package/dist/remote/output/junit.d.ts +18 -0
  161. package/dist/remote/output/junit.js +50 -0
  162. package/dist/remote/output/streaming.d.ts +57 -0
  163. package/dist/remote/output/streaming.js +124 -0
  164. package/dist/remote/output/summary.d.ts +39 -0
  165. package/dist/remote/output/summary.js +99 -0
  166. package/dist/remote/uploader.d.ts +87 -0
  167. package/dist/remote/uploader.js +197 -0
  168. package/dist/review-comment-created.json +36 -0
  169. package/dist/review-submitted.json +35 -0
  170. package/dist/star-created.json +15 -0
  171. package/dist/status.json +26 -0
  172. package/dist/tag-push.json +20 -0
  173. package/dist/templates/agents-md.d.ts +8 -0
  174. package/dist/templates/agents-md.js +130 -0
  175. package/dist/templates/index.d.ts +43 -0
  176. package/dist/templates/index.js +48 -0
  177. package/dist/templates/package-json.d.ts +18 -0
  178. package/dist/templates/package-json.js +34 -0
  179. package/dist/templates/tsconfig-json.d.ts +9 -0
  180. package/dist/templates/tsconfig-json.js +26 -0
  181. package/dist/templates/workflows/hello-world.d.ts +2 -0
  182. package/dist/templates/workflows/hello-world.js +16 -0
  183. package/dist/templates/workflows/hello-world.ts +21 -0
  184. package/dist/templates/workflows/pr-checks.d.ts +2 -0
  185. package/dist/templates/workflows/pr-checks.js +40 -0
  186. package/dist/templates/workflows/pr-checks.ts +57 -0
  187. package/dist/test-runner/dry-run.d.ts +12 -0
  188. package/dist/test-runner/dry-run.js +66 -0
  189. package/dist/test-runner/event-types.d.ts +86 -0
  190. package/dist/test-runner/event-types.js +330 -0
  191. package/dist/test-runner/git-detector.d.ts +15 -0
  192. package/dist/test-runner/git-detector.js +30 -0
  193. package/dist/test-runner/index.d.ts +13 -0
  194. package/dist/test-runner/index.js +11 -0
  195. package/dist/test-runner/job-executor.d.ts +48 -0
  196. package/dist/test-runner/job-executor.js +245 -0
  197. package/dist/test-runner/output-formatter.d.ts +47 -0
  198. package/dist/test-runner/output-formatter.js +92 -0
  199. package/dist/test-runner/payload-builder.d.ts +20 -0
  200. package/dist/test-runner/payload-builder.js +216 -0
  201. package/dist/test-runner/rule-evaluator.d.ts +14 -0
  202. package/dist/test-runner/rule-evaluator.js +31 -0
  203. package/dist/test-runner/secrets-file.d.ts +24 -0
  204. package/dist/test-runner/secrets-file.js +62 -0
  205. package/dist/test-runner/step-context.d.ts +15 -0
  206. package/dist/test-runner/step-context.js +140 -0
  207. package/dist/test-runner/summary.d.ts +7 -0
  208. package/dist/types.d.ts +525 -0
  209. package/dist/types.js +33 -0
  210. package/dist/validation/index.d.ts +3 -0
  211. package/dist/validation/index.js +3 -0
  212. package/dist/validation/validator.d.ts +26 -0
  213. package/dist/validation/validator.js +164 -0
  214. package/dist/watch-started.json +15 -0
  215. package/dist/workflow-run-completed.json +23 -0
  216. package/dist/workflows/hello-world.ts +21 -0
  217. package/dist/workflows/pr-checks.ts +57 -0
  218. package/hack/postinstall.mjs +105 -0
  219. package/package.json +61 -5
  220. package/sbom.spdx.json +10997 -0
  221. package/index.js +0 -3
@@ -0,0 +1,204 @@
1
+ /**
2
+ * REST client for communicating with the KiCI orchestrator.
3
+ *
4
+ * Provides typed methods for triggering test runs, cancelling runs,
5
+ * managing uploads, and checking run status.
6
+ */
7
+ export declare class AuthenticationError extends Error {
8
+ constructor(message?: string);
9
+ }
10
+ export declare class NotFoundError extends Error {
11
+ constructor(message?: string);
12
+ }
13
+ export declare class ServerError extends Error {
14
+ statusCode?: number | undefined;
15
+ constructor(message?: string, statusCode?: number | undefined);
16
+ }
17
+ export declare class ConnectionError extends Error {
18
+ endpoint?: string | undefined;
19
+ constructor(message: string, endpoint?: string | undefined);
20
+ }
21
+ export interface TestTriggerInput {
22
+ fixtureId: string;
23
+ event: {
24
+ type: string;
25
+ action?: string;
26
+ targetBranch: string;
27
+ sourceBranch?: string;
28
+ payload: Record<string, unknown>;
29
+ changedFiles?: string[];
30
+ };
31
+ routingKey: string;
32
+ uploadId?: string;
33
+ /** CLI's ephemeral public key (base64, SPKI/DER) for overlay decryption */
34
+ cliPublicKey?: string;
35
+ secrets?: Record<string, string>;
36
+ workflowName?: string;
37
+ /** JSON-stringified lock file content for repos with no remote. */
38
+ inlineLockFile?: string;
39
+ /** When true, repo has no remote -- agent uses overlay tarball as full workspace. */
40
+ fullRepo?: boolean;
41
+ }
42
+ export interface TestTriggerResponse {
43
+ runId: string;
44
+ observeUrl: string;
45
+ status: 'accepted' | 'rejected';
46
+ reason?: string;
47
+ jobIds?: string[];
48
+ }
49
+ export interface TestCancelResponse {
50
+ status: 'cancelled' | 'not_found' | 'already_complete';
51
+ cancelledJobs?: number;
52
+ }
53
+ interface UploadInitInput {
54
+ routingKey: string;
55
+ sha?: string;
56
+ fileCount?: number;
57
+ compressedSize?: number;
58
+ }
59
+ interface UploadInitResponse {
60
+ uploadId: string;
61
+ signedUrl: string;
62
+ publicKey: string;
63
+ expiresIn: number;
64
+ }
65
+ interface UploadStatusResponse {
66
+ uploadId: string;
67
+ status: string;
68
+ routingKey?: string;
69
+ sha?: string | null;
70
+ fileCount?: number | null;
71
+ compressedSize?: number | null;
72
+ }
73
+ export interface RunStatusResponse {
74
+ runId: string;
75
+ status: string;
76
+ summary?: {
77
+ totalDurationMs: number;
78
+ jobs: Array<{
79
+ name: string;
80
+ status: string;
81
+ durationMs?: number;
82
+ }>;
83
+ };
84
+ }
85
+ export interface RunLogsResponse {
86
+ runId: string;
87
+ status: string;
88
+ /** Present when the run is still active — connect via WebSocket for live streaming. */
89
+ observeUrl?: string;
90
+ /** Present when the run is terminal — historical log entries. */
91
+ logs?: Array<{
92
+ jobName: string;
93
+ stepIndex: number;
94
+ stepName: string;
95
+ lines: string[];
96
+ }>;
97
+ }
98
+ export interface RegistrationItem {
99
+ id: string;
100
+ repoIdentifier: string;
101
+ workflowName: string;
102
+ triggerTypes: string[];
103
+ triggers: unknown[];
104
+ lastTriggeredAt: string | null;
105
+ nextFireAt: string | null;
106
+ sourceRepos: string[];
107
+ createdAt: string;
108
+ updatedAt: string;
109
+ }
110
+ interface RegistrationsListResponse {
111
+ registrations: RegistrationItem[];
112
+ registryVersion: number;
113
+ registryUpdatedAt: string;
114
+ }
115
+ interface OrchestratorClientConfig {
116
+ endpoint: string;
117
+ token: string;
118
+ }
119
+ /**
120
+ * Orchestrator capability manifest returned by `GET /api/v1/capabilities`.
121
+ *
122
+ * All fields are optional because the endpoint may not exist on older
123
+ * orchestrators. Callers treat missing fields as "unknown" and format an
124
+ * error that says so rather than failing hard.
125
+ */
126
+ export interface OrchestratorCapabilities {
127
+ orchestratorVersion?: string;
128
+ protocolVersion?: number;
129
+ minProtocolVersion?: number;
130
+ }
131
+ /**
132
+ * REST client for the KiCI orchestrator API.
133
+ *
134
+ * Handles authentication, request formatting, and typed response parsing
135
+ * for all test-trigger and upload operations.
136
+ */
137
+ export declare class OrchestratorClient {
138
+ private readonly baseUrl;
139
+ private readonly token;
140
+ private cachedCapabilities?;
141
+ constructor(config: OrchestratorClientConfig);
142
+ /**
143
+ * Fetch the orchestrator's capability manifest.
144
+ *
145
+ * Never throws — on any failure (old orchestrator returning 404, network
146
+ * error, malformed JSON) it returns an empty manifest. Callers use the
147
+ * returned fields to format actionable capability-gap errors and treat
148
+ * missing fields as "unknown".
149
+ *
150
+ * Memoised per client instance so repeated calls in a single CLI session
151
+ * hit the orchestrator once.
152
+ */
153
+ getCapabilities(): Promise<OrchestratorCapabilities>;
154
+ private fetchCapabilities;
155
+ /**
156
+ * Trigger a test run on the orchestrator.
157
+ *
158
+ * POST /api/v1/test/trigger
159
+ */
160
+ triggerTest(input: TestTriggerInput): Promise<TestTriggerResponse>;
161
+ /**
162
+ * Cancel a running test run.
163
+ *
164
+ * POST /api/v1/test/cancel
165
+ */
166
+ cancelTest(runId: string): Promise<TestCancelResponse>;
167
+ /**
168
+ * Initialize an upload and get a pre-signed URL.
169
+ *
170
+ * POST /api/v1/uploads/init
171
+ */
172
+ initUpload(opts: UploadInitInput): Promise<UploadInitResponse>;
173
+ /**
174
+ * Get the status of an upload.
175
+ *
176
+ * GET /api/v1/uploads/:uploadId/status
177
+ */
178
+ getUploadStatus(uploadId: string): Promise<UploadStatusResponse>;
179
+ /**
180
+ * List workflow registrations for an organization.
181
+ *
182
+ * GET /api/v1/orgs/:orgId/registrations
183
+ */
184
+ getRegistrations(orgId: string, filters?: Record<string, string>): Promise<RegistrationsListResponse>;
185
+ /**
186
+ * Get the status of a test run (polling fallback).
187
+ *
188
+ * GET /api/v1/test/runs/:runId
189
+ */
190
+ getRunStatus(runId: string): Promise<RunStatusResponse>;
191
+ /**
192
+ * Get logs for a test run.
193
+ *
194
+ * GET /api/v1/test/runs/:runId/logs
195
+ */
196
+ getRunLogs(runId: string, jobFilter?: string): Promise<RunLogsResponse>;
197
+ /**
198
+ * Make an authenticated request to the orchestrator.
199
+ * Handles error classification and connection errors.
200
+ */
201
+ private request;
202
+ }
203
+ export {};
204
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1,203 @@
1
+ import "../chunk-gOLHoazu.js";
2
+ import { toErrorMessage } from "@kici-dev/shared";
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
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Global KiCI configuration stored in ~/.kici/config.
3
+ * Contains authentication tokens and endpoint settings.
4
+ */
5
+ export interface GlobalConfig {
6
+ /** API key for authentication (legacy) */
7
+ token?: string;
8
+ /** Orchestrator URL for direct mode */
9
+ endpoint?: string;
10
+ /** Platform relay URL */
11
+ platformEndpoint?: string;
12
+ /** Connection mode: 'platform' or 'direct' */
13
+ connectionMode?: 'platform' | 'direct';
14
+ /** Routing key for webhook source identification (e.g., 'github:42') */
15
+ routingKey?: string;
16
+ /** Personal access token (from OAuth login) */
17
+ pat?: string;
18
+ /** PAT identifier (server-side ID) */
19
+ patId?: string;
20
+ /** PAT expiry timestamp (ISO 8601) */
21
+ patExpiresAt?: string;
22
+ /** Active organization ID */
23
+ activeOrgId?: string;
24
+ /** User email from OIDC token */
25
+ userEmail?: string;
26
+ }
27
+ /**
28
+ * Returns the global KiCI config directory path.
29
+ * Checks KICI_CONFIG_DIR env var first, falls back to ~/.kici.
30
+ */
31
+ export declare function getConfigDir(): string;
32
+ /**
33
+ * Returns the path to the global config file (~/.kici/config).
34
+ */
35
+ export declare function getConfigPath(): string;
36
+ /**
37
+ * Load the global KiCI config from ~/.kici/config.
38
+ * Returns an empty object if the file does not exist.
39
+ * Unknown keys are stripped; invalid values are ignored.
40
+ */
41
+ export declare function loadGlobalConfig(): Promise<GlobalConfig>;
42
+ /**
43
+ * Save the global KiCI config to ~/.kici/config.
44
+ * Creates the config directory if needed.
45
+ * Sets file permissions to 0o600 (owner read/write only) since it contains tokens.
46
+ */
47
+ export declare function saveGlobalConfig(config: GlobalConfig): Promise<void>;
48
+ /**
49
+ * Merge partial config into the existing global config.
50
+ * Loads existing config, merges with the partial, saves, and returns the merged result.
51
+ * Undefined values in the partial are ignored (existing values preserved).
52
+ */
53
+ export declare function mergeGlobalConfig(partial: Partial<GlobalConfig>): Promise<GlobalConfig>;
54
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1,92 @@
1
+ import "../chunk-gOLHoazu.js";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import os from "node:os";
5
+ //#region src/remote/config.ts
6
+ const VALID_CONNECTION_MODES = ["platform", "direct"];
7
+ /**
8
+ * Strips unknown keys and validates known fields from a raw config object.
9
+ * Returns a clean GlobalConfig with only recognized, valid fields.
10
+ */
11
+ function sanitizeConfig(raw) {
12
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return {};
13
+ const obj = raw;
14
+ const config = {};
15
+ if (typeof obj.token === "string") config.token = obj.token;
16
+ if (typeof obj.endpoint === "string") config.endpoint = obj.endpoint;
17
+ if (typeof obj.platformEndpoint === "string") config.platformEndpoint = obj.platformEndpoint;
18
+ if (typeof obj.connectionMode === "string" && VALID_CONNECTION_MODES.includes(obj.connectionMode)) config.connectionMode = obj.connectionMode;
19
+ if (typeof obj.routingKey === "string") config.routingKey = obj.routingKey;
20
+ if (typeof obj.pat === "string") config.pat = obj.pat;
21
+ if (typeof obj.patId === "string") config.patId = obj.patId;
22
+ if (typeof obj.patExpiresAt === "string") config.patExpiresAt = obj.patExpiresAt;
23
+ if (typeof obj.activeOrgId === "string") config.activeOrgId = obj.activeOrgId;
24
+ if (typeof obj.userEmail === "string") config.userEmail = obj.userEmail;
25
+ return config;
26
+ }
27
+ /**
28
+ * Returns the global KiCI config directory path.
29
+ * Checks KICI_CONFIG_DIR env var first, falls back to ~/.kici.
30
+ */
31
+ function getConfigDir() {
32
+ if (process.env.KICI_CONFIG_DIR) return process.env.KICI_CONFIG_DIR;
33
+ return path.join(os.homedir(), ".kici");
34
+ }
35
+ /**
36
+ * Returns the path to the global config file (~/.kici/config).
37
+ */
38
+ function getConfigPath() {
39
+ return path.join(getConfigDir(), "config");
40
+ }
41
+ /**
42
+ * Load the global KiCI config from ~/.kici/config.
43
+ * Returns an empty object if the file does not exist.
44
+ * Unknown keys are stripped; invalid values are ignored.
45
+ */
46
+ async function loadGlobalConfig() {
47
+ const configPath = getConfigPath();
48
+ try {
49
+ const content = await fs.readFile(configPath, "utf-8");
50
+ return sanitizeConfig(JSON.parse(content));
51
+ } catch (err) {
52
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") return {};
53
+ if (err instanceof SyntaxError) throw new Error(`Config file at ${configPath} contains invalid JSON. Delete it and re-run \`kici login\` to authenticate.`);
54
+ throw err;
55
+ }
56
+ }
57
+ /**
58
+ * Save the global KiCI config to ~/.kici/config.
59
+ * Creates the config directory if needed.
60
+ * Sets file permissions to 0o600 (owner read/write only) since it contains tokens.
61
+ */
62
+ async function saveGlobalConfig(config) {
63
+ const configDir = getConfigDir();
64
+ await fs.mkdir(configDir, { recursive: true });
65
+ const configPath = getConfigPath();
66
+ const content = JSON.stringify(config, null, 2) + "\n";
67
+ await fs.writeFile(configPath, content, { mode: 384 });
68
+ }
69
+ /**
70
+ * Merge partial config into the existing global config.
71
+ * Loads existing config, merges with the partial, saves, and returns the merged result.
72
+ * Undefined values in the partial are ignored (existing values preserved).
73
+ */
74
+ async function mergeGlobalConfig(partial) {
75
+ const merged = { ...await loadGlobalConfig() };
76
+ if (partial.token !== void 0) merged.token = partial.token;
77
+ if (partial.endpoint !== void 0) merged.endpoint = partial.endpoint;
78
+ if (partial.platformEndpoint !== void 0) merged.platformEndpoint = partial.platformEndpoint;
79
+ if (partial.connectionMode !== void 0) merged.connectionMode = partial.connectionMode;
80
+ if (partial.routingKey !== void 0) merged.routingKey = partial.routingKey;
81
+ if (partial.pat !== void 0) merged.pat = partial.pat;
82
+ if (partial.patId !== void 0) merged.patId = partial.patId;
83
+ if (partial.patExpiresAt !== void 0) merged.patExpiresAt = partial.patExpiresAt;
84
+ if (partial.activeOrgId !== void 0) merged.activeOrgId = partial.activeOrgId;
85
+ if (partial.userEmail !== void 0) merged.userEmail = partial.userEmail;
86
+ await saveGlobalConfig(merged);
87
+ return merged;
88
+ }
89
+ //#endregion
90
+ export { getConfigDir, getConfigPath, loadGlobalConfig, mergeGlobalConfig, saveGlobalConfig };
91
+
92
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,35 @@
1
+ import { deriveSharedSecret } from '@kici-dev/shared';
2
+ export { deriveSharedSecret };
3
+ /**
4
+ * Generate an ephemeral X25519 keypair.
5
+ * Keys are exported as DER buffers for compact wire format.
6
+ */
7
+ export declare function generateEphemeralKeypair(): {
8
+ publicKey: Buffer;
9
+ privateKey: Buffer;
10
+ };
11
+ /**
12
+ * Encrypt a tarball file using X25519 ECDH + AES-256-GCM.
13
+ *
14
+ * Generates an ephemeral CLI keypair, derives a shared secret with the
15
+ * orchestrator's public key, and encrypts the tarball.
16
+ *
17
+ * Wire format: [12-byte IV][16-byte auth tag][ciphertext]
18
+ *
19
+ * @returns The encrypted file path and the CLI's ephemeral public key
20
+ * (the agent needs this to derive the same shared secret for decryption).
21
+ */
22
+ export declare function encryptTarball(tarballPath: string, orchestratorPublicKey: Buffer): Promise<{
23
+ encryptedPath: string;
24
+ cliPublicKey: Buffer;
25
+ }>;
26
+ /**
27
+ * Decrypt an encrypted tarball using X25519 ECDH + AES-256-GCM.
28
+ *
29
+ * Derives the same shared secret from the orchestrator's private key
30
+ * and the CLI's ephemeral public key.
31
+ *
32
+ * @returns The path to the decrypted file (encrypted path with .enc suffix removed).
33
+ */
34
+ export declare function decryptTarball(encryptedPath: string, cliPublicKey: Buffer, orchestratorPrivateKey: Buffer): Promise<string>;
35
+ //# sourceMappingURL=encryption.d.ts.map
@@ -0,0 +1,87 @@
1
+ import "../chunk-gOLHoazu.js";
2
+ import fs from "node:fs/promises";
3
+ import { deriveSharedSecret } from "@kici-dev/shared";
4
+ import crypto from "node:crypto";
5
+ //#region src/remote/encryption.ts
6
+ /**
7
+ * Wire format for encrypted tarballs:
8
+ * [12-byte IV][16-byte auth tag][ciphertext]
9
+ *
10
+ * Uses AES-256-GCM with X25519 ECDH key exchange.
11
+ * Same pattern as engine/src/secrets/crypto.ts.
12
+ */
13
+ const IV_LENGTH = 12;
14
+ const AUTH_TAG_LENGTH = 16;
15
+ /**
16
+ * Generate an ephemeral X25519 keypair.
17
+ * Keys are exported as DER buffers for compact wire format.
18
+ */
19
+ function generateEphemeralKeypair() {
20
+ const { publicKey, privateKey } = crypto.generateKeyPairSync("x25519");
21
+ return {
22
+ publicKey: Buffer.from(publicKey.export({
23
+ type: "spki",
24
+ format: "der"
25
+ })),
26
+ privateKey: Buffer.from(privateKey.export({
27
+ type: "pkcs8",
28
+ format: "der"
29
+ }))
30
+ };
31
+ }
32
+ /**
33
+ * Encrypt a tarball file using X25519 ECDH + AES-256-GCM.
34
+ *
35
+ * Generates an ephemeral CLI keypair, derives a shared secret with the
36
+ * orchestrator's public key, and encrypts the tarball.
37
+ *
38
+ * Wire format: [12-byte IV][16-byte auth tag][ciphertext]
39
+ *
40
+ * @returns The encrypted file path and the CLI's ephemeral public key
41
+ * (the agent needs this to derive the same shared secret for decryption).
42
+ */
43
+ async function encryptTarball(tarballPath, orchestratorPublicKey) {
44
+ const { publicKey: cliPublicKey, privateKey: cliPrivateKey } = generateEphemeralKeypair();
45
+ const aesKey = deriveSharedSecret(cliPrivateKey, orchestratorPublicKey);
46
+ const plaintext = await fs.readFile(tarballPath);
47
+ const iv = crypto.randomBytes(IV_LENGTH);
48
+ const cipher = crypto.createCipheriv("aes-256-gcm", aesKey, iv);
49
+ const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
50
+ const authTag = cipher.getAuthTag();
51
+ const encrypted = Buffer.concat([
52
+ iv,
53
+ authTag,
54
+ ciphertext
55
+ ]);
56
+ const encryptedPath = `${tarballPath}.enc`;
57
+ await fs.writeFile(encryptedPath, encrypted);
58
+ return {
59
+ encryptedPath,
60
+ cliPublicKey
61
+ };
62
+ }
63
+ /**
64
+ * Decrypt an encrypted tarball using X25519 ECDH + AES-256-GCM.
65
+ *
66
+ * Derives the same shared secret from the orchestrator's private key
67
+ * and the CLI's ephemeral public key.
68
+ *
69
+ * @returns The path to the decrypted file (encrypted path with .enc suffix removed).
70
+ */
71
+ async function decryptTarball(encryptedPath, cliPublicKey, orchestratorPrivateKey) {
72
+ const aesKey = deriveSharedSecret(orchestratorPrivateKey, cliPublicKey);
73
+ const encrypted = await fs.readFile(encryptedPath);
74
+ 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);
77
+ const decipher = crypto.createDecipheriv("aes-256-gcm", aesKey, iv);
78
+ decipher.setAuthTag(authTag);
79
+ const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
80
+ const decryptedPath = encryptedPath.endsWith(".enc") ? encryptedPath.slice(0, -4) : `${encryptedPath}.dec`;
81
+ await fs.writeFile(decryptedPath, decrypted);
82
+ return decryptedPath;
83
+ }
84
+ //#endregion
85
+ export { decryptTarball, deriveSharedSecret, encryptTarball, generateEphemeralKeypair };
86
+
87
+ //# sourceMappingURL=encryption.js.map