@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.
- package/LICENSE +202 -0
- package/README.md +1 -6
- package/dist/assets/api-TJJVHrjC.json +118 -0
- package/dist/assets/descriptor-BTtjzN9L.json +1382 -0
- package/dist/assets/package-BpQF9kR8.json +74 -0
- package/dist/assets/package-Ceo2h27X.json +89 -0
- package/dist/assets/source_context-D0atuL28.json +20 -0
- package/dist/assets/type-BFqO8SCZ.json +202 -0
- package/dist/auth/headless-detect.d.ts +14 -0
- package/dist/auth/headless-detect.js +25 -0
- package/dist/chunk-gOLHoazu.js +4 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +193 -0
- package/dist/commands/cancel.d.ts +22 -0
- package/dist/commands/cancel.js +124 -0
- package/dist/commands/compile.d.ts +17 -0
- package/dist/commands/compile.js +99 -0
- package/dist/commands/docs.d.ts +26 -0
- package/dist/commands/docs.js +60 -0
- package/dist/commands/drain-worker.d.ts +19 -0
- package/dist/commands/drain-worker.js +45 -0
- package/dist/commands/endpoints.d.ts +53 -0
- package/dist/commands/endpoints.js +185 -0
- package/dist/commands/fixture.d.ts +14 -0
- package/dist/commands/fixture.js +104 -0
- package/dist/commands/hook.d.ts +20 -0
- package/dist/commands/hook.js +97 -0
- package/dist/commands/index.d.ts +33 -0
- package/dist/commands/index.js +20 -0
- package/dist/commands/init.d.ts +35 -0
- package/dist/commands/init.js +393 -0
- package/dist/commands/login.d.ts +23 -0
- package/dist/commands/login.js +144 -0
- package/dist/commands/logout.d.ts +18 -0
- package/dist/commands/logout.js +55 -0
- package/dist/commands/org.d.ts +27 -0
- package/dist/commands/org.js +126 -0
- package/dist/commands/run.d.ts +21 -0
- package/dist/commands/run.js +562 -0
- package/dist/commands/secrets-list.d.ts +16 -0
- package/dist/commands/secrets-list.js +85 -0
- package/dist/commands/status.d.ts +30 -0
- package/dist/commands/status.js +210 -0
- package/dist/commands/test.d.ts +61 -0
- package/dist/commands/test.js +220 -0
- package/dist/commands/types.d.ts +18 -0
- package/dist/commands/types.js +74 -0
- package/dist/commands/watch.d.ts +14 -0
- package/dist/commands/watch.js +97 -0
- package/dist/commands/workflows.d.ts +28 -0
- package/dist/commands/workflows.js +154 -0
- package/dist/comment-created.json +30 -0
- package/dist/create-branch.json +17 -0
- package/dist/delete-branch.json +15 -0
- package/dist/dispatch.json +15 -0
- package/dist/errors/capability-gap.d.ts +50 -0
- package/dist/errors/capability-gap.js +54 -0
- package/dist/errors/codes.d.ts +25 -0
- package/dist/errors/formatter.d.ts +32 -0
- package/dist/errors/formatter.js +35 -0
- package/dist/errors/index.d.ts +5 -0
- package/dist/errors/index.js +4 -0
- package/dist/execution/executor.d.ts +61 -0
- package/dist/execution/executor.js +230 -0
- package/dist/execution/index.d.ts +4 -0
- package/dist/execution/index.js +3 -0
- package/dist/execution/sdk-alias.d.ts +33 -0
- package/dist/execution/sdk-alias.js +102 -0
- package/dist/fixtures/compiler.d.ts +47 -0
- package/dist/fixtures/compiler.js +177 -0
- package/dist/fixtures/defaults/comment-created.json +30 -0
- package/dist/fixtures/defaults/create-branch.json +17 -0
- package/dist/fixtures/defaults/delete-branch.json +15 -0
- package/dist/fixtures/defaults/dispatch.json +15 -0
- package/dist/fixtures/defaults/fork.json +19 -0
- package/dist/fixtures/defaults/index.d.ts +16 -0
- package/dist/fixtures/defaults/index.js +105 -0
- package/dist/fixtures/defaults/index.ts +145 -0
- package/dist/fixtures/defaults/pr-closed.json +28 -0
- package/dist/fixtures/defaults/pr-opened.json +27 -0
- package/dist/fixtures/defaults/pr-reopened.json +27 -0
- package/dist/fixtures/defaults/pr-synchronize.json +27 -0
- package/dist/fixtures/defaults/push.json +16 -0
- package/dist/fixtures/defaults/release-published.json +23 -0
- package/dist/fixtures/defaults/review-comment-created.json +36 -0
- package/dist/fixtures/defaults/review-submitted.json +35 -0
- package/dist/fixtures/defaults/star-created.json +15 -0
- package/dist/fixtures/defaults/status.json +26 -0
- package/dist/fixtures/defaults/tag-push.json +20 -0
- package/dist/fixtures/defaults/watch-started.json +15 -0
- package/dist/fixtures/defaults/workflow-run-completed.json +23 -0
- package/dist/fork.json +19 -0
- package/dist/format.d.ts +5 -0
- package/dist/format.js +20 -0
- package/dist/generators/secrets-dts.d.ts +29 -0
- package/dist/generators/secrets-dts.js +67 -0
- package/dist/hooks/detector.d.ts +39 -0
- package/dist/hooks/detector.js +133 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.js +5 -0
- package/dist/hooks/installer.d.ts +24 -0
- package/dist/hooks/installer.js +328 -0
- package/dist/hooks/templates.d.ts +26 -0
- package/dist/hooks/templates.js +63 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -0
- package/dist/llm-context/llms-full.txt +9974 -0
- package/dist/llm-context/llms.txt +61 -0
- package/dist/local-executor/dag-scheduler.d.ts +44 -0
- package/dist/local-executor/dag-scheduler.js +183 -0
- package/dist/local-executor/index.d.ts +23 -0
- package/dist/local-executor/index.js +309 -0
- package/dist/local-executor/job-runner.d.ts +40 -0
- package/dist/local-executor/job-runner.js +307 -0
- package/dist/local-executor/output-streamer.d.ts +31 -0
- package/dist/local-executor/output-streamer.js +166 -0
- package/dist/local-executor/payload-generator.d.ts +16 -0
- package/dist/local-executor/payload-generator.js +138 -0
- package/dist/local-executor/picker.d.ts +33 -0
- package/dist/local-executor/picker.js +109 -0
- package/dist/local-executor/secret-loader.d.ts +18 -0
- package/dist/local-executor/secret-loader.js +105 -0
- package/dist/local-executor/types.d.ts +80 -0
- package/dist/local-executor/types.js +2 -0
- package/dist/local-executor/workflow-lock.d.ts +81 -0
- package/dist/local-executor/workflow-lock.js +0 -0
- package/dist/lockfile/generator.d.ts +39 -0
- package/dist/lockfile/generator.js +688 -0
- package/dist/lockfile/hash-files.d.ts +14 -0
- package/dist/lockfile/hash-files.js +50 -0
- package/dist/lockfile/hasher.d.ts +36 -0
- package/dist/lockfile/hasher.js +46 -0
- package/dist/lockfile/index.d.ts +3 -0
- package/dist/lockfile/index.js +4 -0
- package/dist/lockfile/purity-analyzer.d.ts +25 -0
- package/dist/lockfile/purity-analyzer.js +204 -0
- package/dist/package-F7UXSDHW.json +74 -0
- package/dist/postinstall.d.ts +9 -0
- package/dist/postinstall.js +60 -0
- package/dist/pr-closed.json +28 -0
- package/dist/pr-opened.json +27 -0
- package/dist/pr-reopened.json +27 -0
- package/dist/pr-synchronize.json +27 -0
- package/dist/push.json +16 -0
- package/dist/release-published.json +23 -0
- package/dist/remote/client.d.ts +204 -0
- package/dist/remote/client.js +203 -0
- package/dist/remote/config.d.ts +54 -0
- package/dist/remote/config.js +92 -0
- package/dist/remote/encryption.d.ts +35 -0
- package/dist/remote/encryption.js +87 -0
- package/dist/remote/history.d.ts +91 -0
- package/dist/remote/history.js +146 -0
- package/dist/remote/oauth.d.ts +65 -0
- package/dist/remote/oauth.js +302 -0
- package/dist/remote/observer.d.ts +81 -0
- package/dist/remote/observer.js +174 -0
- package/dist/remote/output/json.d.ts +13 -0
- package/dist/remote/output/json.js +36 -0
- package/dist/remote/output/junit.d.ts +18 -0
- package/dist/remote/output/junit.js +50 -0
- package/dist/remote/output/streaming.d.ts +57 -0
- package/dist/remote/output/streaming.js +124 -0
- package/dist/remote/output/summary.d.ts +39 -0
- package/dist/remote/output/summary.js +99 -0
- package/dist/remote/uploader.d.ts +87 -0
- package/dist/remote/uploader.js +197 -0
- package/dist/review-comment-created.json +36 -0
- package/dist/review-submitted.json +35 -0
- package/dist/star-created.json +15 -0
- package/dist/status.json +26 -0
- package/dist/tag-push.json +20 -0
- package/dist/templates/agents-md.d.ts +8 -0
- package/dist/templates/agents-md.js +130 -0
- package/dist/templates/index.d.ts +43 -0
- package/dist/templates/index.js +48 -0
- package/dist/templates/package-json.d.ts +18 -0
- package/dist/templates/package-json.js +34 -0
- package/dist/templates/tsconfig-json.d.ts +9 -0
- package/dist/templates/tsconfig-json.js +26 -0
- package/dist/templates/workflows/hello-world.d.ts +2 -0
- package/dist/templates/workflows/hello-world.js +16 -0
- package/dist/templates/workflows/hello-world.ts +21 -0
- package/dist/templates/workflows/pr-checks.d.ts +2 -0
- package/dist/templates/workflows/pr-checks.js +40 -0
- package/dist/templates/workflows/pr-checks.ts +57 -0
- package/dist/test-runner/dry-run.d.ts +12 -0
- package/dist/test-runner/dry-run.js +66 -0
- package/dist/test-runner/event-types.d.ts +86 -0
- package/dist/test-runner/event-types.js +330 -0
- package/dist/test-runner/git-detector.d.ts +15 -0
- package/dist/test-runner/git-detector.js +30 -0
- package/dist/test-runner/index.d.ts +13 -0
- package/dist/test-runner/index.js +11 -0
- package/dist/test-runner/job-executor.d.ts +48 -0
- package/dist/test-runner/job-executor.js +245 -0
- package/dist/test-runner/output-formatter.d.ts +47 -0
- package/dist/test-runner/output-formatter.js +92 -0
- package/dist/test-runner/payload-builder.d.ts +20 -0
- package/dist/test-runner/payload-builder.js +216 -0
- package/dist/test-runner/rule-evaluator.d.ts +14 -0
- package/dist/test-runner/rule-evaluator.js +31 -0
- package/dist/test-runner/secrets-file.d.ts +24 -0
- package/dist/test-runner/secrets-file.js +62 -0
- package/dist/test-runner/step-context.d.ts +15 -0
- package/dist/test-runner/step-context.js +140 -0
- package/dist/test-runner/summary.d.ts +7 -0
- package/dist/types.d.ts +525 -0
- package/dist/types.js +33 -0
- package/dist/validation/index.d.ts +3 -0
- package/dist/validation/index.js +3 -0
- package/dist/validation/validator.d.ts +26 -0
- package/dist/validation/validator.js +164 -0
- package/dist/watch-started.json +15 -0
- package/dist/workflow-run-completed.json +23 -0
- package/dist/workflows/hello-world.ts +21 -0
- package/dist/workflows/pr-checks.ts +57 -0
- package/hack/postinstall.mjs +105 -0
- package/package.json +61 -5
- package/sbom.spdx.json +10997 -0
- package/index.js +0 -3
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import { compilerError } from "../errors/formatter.js";
|
|
3
|
+
import "../errors/index.js";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import fs from "node:fs/promises";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { pathToFileURL } from "node:url";
|
|
8
|
+
//#region src/execution/executor.ts
|
|
9
|
+
/**
|
|
10
|
+
* Load a TypeScript workflow/config module by direct dynamic import.
|
|
11
|
+
*
|
|
12
|
+
* Relies on the shared `@kici-dev/shared/ts-loader-hook` ESM loader hook
|
|
13
|
+
* registered by `packages/kici/bin/kici.js` (the same hook the agent registers
|
|
14
|
+
* in its sandbox process). No Rolldown bundling: host-repo imports and
|
|
15
|
+
* transitive deps with dynamic import() resolve via Node's normal ESM loader
|
|
16
|
+
* against the workspace's node_modules — the same module graph any other
|
|
17
|
+
* `npx tsx` invocation would see. This keeps ops-style workflows (which
|
|
18
|
+
* import repo-local modules like scripts/lib/*) working the same as minimal
|
|
19
|
+
* workflows that only touch @kici-dev/sdk.
|
|
20
|
+
*/
|
|
21
|
+
async function loadModule(entryPoint, errorContext) {
|
|
22
|
+
let hashBundleSource;
|
|
23
|
+
try {
|
|
24
|
+
hashBundleSource = await fs.readFile(entryPoint, "utf-8");
|
|
25
|
+
} catch {}
|
|
26
|
+
try {
|
|
27
|
+
return {
|
|
28
|
+
module: await import(pathToFileURL(entryPoint).href + `?t=${Date.now()}`),
|
|
29
|
+
hashBundleSource
|
|
30
|
+
};
|
|
31
|
+
} catch (err) {
|
|
32
|
+
const message = err.message ?? "Failed to load module";
|
|
33
|
+
throw compilerError("E003", `Failed to load ${errorContext.fileLabel} module: ${message}`, {
|
|
34
|
+
location: {
|
|
35
|
+
file: errorContext.filePath,
|
|
36
|
+
line: 1,
|
|
37
|
+
column: 1
|
|
38
|
+
},
|
|
39
|
+
suggestion: `Check for TypeScript or runtime errors in your ${errorContext.fileLabel}. Make sure you invoke the workflow via the kici CLI (the bin shim registers the oxc-transform loader hook that handles TS files).`
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Execute a TypeScript config file and extract workflow definitions.
|
|
45
|
+
*
|
|
46
|
+
* Process:
|
|
47
|
+
* 1. Read TypeScript source from disk
|
|
48
|
+
* 2. Transform to ESM JavaScript via rolldown (in-memory)
|
|
49
|
+
* 3. Write temp file for Node.js dynamic import (required by ESM spec)
|
|
50
|
+
* 4. Dynamic import the compiled module
|
|
51
|
+
* 5. Extract and return workflow definitions
|
|
52
|
+
* 6. Clean up temp file
|
|
53
|
+
*
|
|
54
|
+
* @param configPath - Path to workflow file (relative or absolute)
|
|
55
|
+
* @returns Workflows exported from the config
|
|
56
|
+
* @throws CompilerError on file not found, TypeScript errors, or missing exports
|
|
57
|
+
*/
|
|
58
|
+
async function executeConfig(configPath) {
|
|
59
|
+
const absolutePath = path.resolve(configPath);
|
|
60
|
+
try {
|
|
61
|
+
await fs.access(absolutePath);
|
|
62
|
+
} catch {
|
|
63
|
+
throw compilerError("E001", `Config file not found: ${absolutePath}`, { suggestion: "Ensure workflow files exist in .kici/workflows/" });
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
await fs.readFile(absolutePath, "utf-8");
|
|
67
|
+
} catch {
|
|
68
|
+
throw compilerError("E001", `Failed to read config file: ${absolutePath}`, { suggestion: "Check file permissions" });
|
|
69
|
+
}
|
|
70
|
+
const { module, hashBundleSource } = await loadModule(absolutePath, {
|
|
71
|
+
fileLabel: "config file",
|
|
72
|
+
filePath: absolutePath
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
workflows: extractWorkflows(module, absolutePath, hashBundleSource),
|
|
76
|
+
configPath: absolutePath
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Extract workflow definitions from a module's exports with source tracking.
|
|
81
|
+
*
|
|
82
|
+
* Supports:
|
|
83
|
+
* - Default export: single workflow or array of workflows
|
|
84
|
+
* - Named exports: any export that is a Workflow object
|
|
85
|
+
*
|
|
86
|
+
* @param module - The imported module
|
|
87
|
+
* @param filePath - Absolute path to the source file
|
|
88
|
+
* @returns Array of WorkflowWithSource objects
|
|
89
|
+
*/
|
|
90
|
+
function extractWorkflows(module, filePath, bundleSource) {
|
|
91
|
+
const workflows = [];
|
|
92
|
+
if (module.default) {
|
|
93
|
+
const defaultExport = module.default;
|
|
94
|
+
if (isWorkflow(defaultExport)) workflows.push({
|
|
95
|
+
workflow: defaultExport,
|
|
96
|
+
source: {
|
|
97
|
+
file: filePath,
|
|
98
|
+
exportName: "default"
|
|
99
|
+
},
|
|
100
|
+
bundleSource
|
|
101
|
+
});
|
|
102
|
+
else if (Array.isArray(defaultExport)) defaultExport.forEach((item, index) => {
|
|
103
|
+
if (isWorkflow(item)) workflows.push({
|
|
104
|
+
workflow: item,
|
|
105
|
+
source: {
|
|
106
|
+
file: filePath,
|
|
107
|
+
exportName: "default",
|
|
108
|
+
arrayIndex: index
|
|
109
|
+
},
|
|
110
|
+
bundleSource
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
for (const [key, value] of Object.entries(module)) {
|
|
115
|
+
if (key === "default") continue;
|
|
116
|
+
if (isWorkflow(value)) workflows.push({
|
|
117
|
+
workflow: value,
|
|
118
|
+
source: {
|
|
119
|
+
file: filePath,
|
|
120
|
+
exportName: key
|
|
121
|
+
},
|
|
122
|
+
bundleSource
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (workflows.length === 0) throw compilerError("E004", "Config does not export any workflows", {
|
|
126
|
+
location: {
|
|
127
|
+
file: filePath,
|
|
128
|
+
line: 1,
|
|
129
|
+
column: 1
|
|
130
|
+
},
|
|
131
|
+
suggestion: "Export a workflow using: export default workflow(\"name\", { ... }) or export const myWorkflow = workflow(...)"
|
|
132
|
+
});
|
|
133
|
+
return workflows;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Type guard to check if a value is a Workflow object.
|
|
137
|
+
* Uses _tag discriminant from SDK.
|
|
138
|
+
*/
|
|
139
|
+
function isWorkflow(value) {
|
|
140
|
+
return typeof value === "object" && value !== null && "_tag" in value && value._tag === "Workflow";
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Resolve the .kici directory path, handling the case where the user
|
|
144
|
+
* is already inside the .kici directory (or a subdirectory of it).
|
|
145
|
+
*
|
|
146
|
+
* Resolution order:
|
|
147
|
+
* 1. If the resolved path has a workflows/ subdirectory, use it directly
|
|
148
|
+
* 2. If CWD itself is named .kici and has workflows/, use CWD
|
|
149
|
+
* 3. Fall through to the original resolved path (downstream code will error)
|
|
150
|
+
*
|
|
151
|
+
* @param kiciDir - Path to .kici directory (defaults to '.kici')
|
|
152
|
+
* @returns Absolute path to the .kici directory
|
|
153
|
+
*/
|
|
154
|
+
function resolveKiciDir(kiciDir) {
|
|
155
|
+
const raw = kiciDir ?? ".kici";
|
|
156
|
+
const resolved = path.resolve(raw);
|
|
157
|
+
if (existsSync(path.join(resolved, "workflows"))) return resolved;
|
|
158
|
+
if (raw === ".kici") {
|
|
159
|
+
const cwd = process.cwd();
|
|
160
|
+
if (path.basename(cwd) === ".kici" && existsSync(path.join(cwd, "workflows"))) return cwd;
|
|
161
|
+
}
|
|
162
|
+
return resolved;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Discover and execute all workflow files from .kici/workflows/ directory.
|
|
166
|
+
*
|
|
167
|
+
* Process:
|
|
168
|
+
* 1. Locate .kici/workflows/ directory (defaults to .kici relative to cwd)
|
|
169
|
+
* 2. Find all *.ts files in the directory
|
|
170
|
+
* 3. Execute each file to extract workflow definitions
|
|
171
|
+
* 4. Collect and return all workflows
|
|
172
|
+
*
|
|
173
|
+
* @param kiciDir - Path to .kici directory (defaults to '.kici' relative to cwd)
|
|
174
|
+
* @returns Discovery result with all workflows and directory paths
|
|
175
|
+
* @throws CompilerError if .kici/workflows/ doesn't exist or no workflows found
|
|
176
|
+
*/
|
|
177
|
+
async function discoverWorkflows(kiciDir) {
|
|
178
|
+
const absoluteKiciDir = resolveKiciDir(kiciDir);
|
|
179
|
+
const workflowDir = path.join(absoluteKiciDir, "workflows");
|
|
180
|
+
try {
|
|
181
|
+
if (!(await fs.stat(workflowDir)).isDirectory()) throw compilerError("E001", `.kici/workflows/ is not a directory: ${workflowDir}`, { suggestion: "Run \"kici init\" to create the .kici/workflows/ directory" });
|
|
182
|
+
} catch (err) {
|
|
183
|
+
if (err.code === "ENOENT") throw compilerError("E001", `.kici/workflows/ directory not found: ${workflowDir}`, { suggestion: "Run \"kici init\" to create the .kici/workflows/ directory" });
|
|
184
|
+
throw err;
|
|
185
|
+
}
|
|
186
|
+
let files;
|
|
187
|
+
try {
|
|
188
|
+
files = (await fs.readdir(workflowDir, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => path.join(workflowDir, entry.name));
|
|
189
|
+
} catch {
|
|
190
|
+
throw compilerError("E001", `Failed to read .kici/workflows/ directory: ${workflowDir}`, { suggestion: "Check directory permissions" });
|
|
191
|
+
}
|
|
192
|
+
if (files.length === 0) throw compilerError("E001", "No workflow files found in .kici/workflows/", { suggestion: "Add *.ts workflow files to .kici/workflows/ or run \"kici init\"" });
|
|
193
|
+
const allWorkflows = [];
|
|
194
|
+
for (const file of files) {
|
|
195
|
+
const result = await executeWorkflowFile(file);
|
|
196
|
+
allWorkflows.push(...result.workflows);
|
|
197
|
+
}
|
|
198
|
+
if (allWorkflows.length === 0) throw compilerError("E004", "No workflows exported from .kici/workflows/ files", { suggestion: "Ensure your workflow files export workflows using: export const myWorkflow = workflow(...)" });
|
|
199
|
+
return {
|
|
200
|
+
workflows: allWorkflows,
|
|
201
|
+
workflowDir,
|
|
202
|
+
kiciDir: absoluteKiciDir
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Execute a single workflow file and extract workflow definitions.
|
|
207
|
+
* Similar to executeConfig but for individual workflow files.
|
|
208
|
+
*
|
|
209
|
+
* @param filePath - Absolute path to workflow file
|
|
210
|
+
* @returns Execution result with workflows from this file
|
|
211
|
+
*/
|
|
212
|
+
async function executeWorkflowFile(filePath) {
|
|
213
|
+
try {
|
|
214
|
+
await fs.access(filePath);
|
|
215
|
+
} catch {
|
|
216
|
+
throw compilerError("E001", `Failed to read workflow file: ${filePath}`, { suggestion: "Check file permissions" });
|
|
217
|
+
}
|
|
218
|
+
const { module, hashBundleSource } = await loadModule(filePath, {
|
|
219
|
+
fileLabel: "workflow file",
|
|
220
|
+
filePath
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
workflows: extractWorkflows(module, filePath, hashBundleSource),
|
|
224
|
+
configPath: filePath
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
//#endregion
|
|
228
|
+
export { discoverWorkflows, executeConfig, resolveKiciDir };
|
|
229
|
+
|
|
230
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK aliasing for development mode
|
|
3
|
+
*
|
|
4
|
+
* Enables automatic aliasing of @kici-dev/sdk imports to a local development repository when:
|
|
5
|
+
* 1. sdkPath is configured in .kici/package.json
|
|
6
|
+
* 2. Current project is NOT the kici development repo itself
|
|
7
|
+
*
|
|
8
|
+
* This allows developers to test SDK changes in real-time without publishing or manual linking.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Get rolldown alias configuration for SDK development mode.
|
|
12
|
+
*
|
|
13
|
+
* Returns alias mapping if:
|
|
14
|
+
* - sdkPath is configured in .kici/package.json
|
|
15
|
+
* - Current project is NOT the kici repo itself
|
|
16
|
+
* - SDK build exists at configured path
|
|
17
|
+
*
|
|
18
|
+
* @returns Alias config for rolldown (empty object if aliasing disabled)
|
|
19
|
+
*/
|
|
20
|
+
export declare function getSdkAliasConfig(): Promise<Record<string, string>>;
|
|
21
|
+
/**
|
|
22
|
+
* Get TypeScript path mappings for IDE support.
|
|
23
|
+
*
|
|
24
|
+
* Returns path mapping configuration to include in tsconfig.json:
|
|
25
|
+
* - Points @kici-dev/sdk to local source for autocomplete
|
|
26
|
+
* - Only if sdkPath is configured and valid
|
|
27
|
+
*
|
|
28
|
+
* @returns TypeScript paths config, or null if not applicable
|
|
29
|
+
*/
|
|
30
|
+
export declare function getTypeScriptPaths(): Promise<{
|
|
31
|
+
'@kici-dev/sdk': [string];
|
|
32
|
+
} | null>;
|
|
33
|
+
//# sourceMappingURL=sdk-alias.d.ts.map
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { logger } from "@kici-dev/shared";
|
|
6
|
+
//#region src/execution/sdk-alias.ts
|
|
7
|
+
/**
|
|
8
|
+
* SDK aliasing for development mode
|
|
9
|
+
*
|
|
10
|
+
* Enables automatic aliasing of @kici-dev/sdk imports to a local development repository when:
|
|
11
|
+
* 1. sdkPath is configured in .kici/package.json
|
|
12
|
+
* 2. Current project is NOT the kici development repo itself
|
|
13
|
+
*
|
|
14
|
+
* This allows developers to test SDK changes in real-time without publishing or manual linking.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Get rolldown alias configuration for SDK development mode.
|
|
18
|
+
*
|
|
19
|
+
* Returns alias mapping if:
|
|
20
|
+
* - sdkPath is configured in .kici/package.json
|
|
21
|
+
* - Current project is NOT the kici repo itself
|
|
22
|
+
* - SDK build exists at configured path
|
|
23
|
+
*
|
|
24
|
+
* @returns Alias config for rolldown (empty object if aliasing disabled)
|
|
25
|
+
*/
|
|
26
|
+
async function getSdkAliasConfig() {
|
|
27
|
+
const basePath = await getSdkPathFromPackageJson();
|
|
28
|
+
if (!basePath) return {};
|
|
29
|
+
if (await isInKiciRepo()) {
|
|
30
|
+
if (process.env.KICI_DEBUG === "true") logger.warn("[kici] SDK aliasing disabled: running inside kici development repo");
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
const sdkPath = resolveAndValidateSdkPath(basePath);
|
|
34
|
+
if (!sdkPath) return {};
|
|
35
|
+
logger.warn(`[kici] Development mode: using local SDK from ${path.dirname(path.dirname(sdkPath))}`);
|
|
36
|
+
return { "@kici-dev/sdk": sdkPath };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Read sdkPath from .kici/package.json configuration.
|
|
40
|
+
*
|
|
41
|
+
* @returns Absolute path to SDK repo, or null if not configured
|
|
42
|
+
*/
|
|
43
|
+
async function getSdkPathFromPackageJson() {
|
|
44
|
+
try {
|
|
45
|
+
const content = await readFile(path.resolve(process.cwd(), ".kici", "package.json"), "utf-8");
|
|
46
|
+
const sdkPath = JSON.parse(content).kici?.sdkPath;
|
|
47
|
+
if (!sdkPath) return null;
|
|
48
|
+
return path.resolve(sdkPath);
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if current project is the kici development repository.
|
|
55
|
+
*
|
|
56
|
+
* Checks if root package.json has kici.development flag set to true.
|
|
57
|
+
*
|
|
58
|
+
* @returns true if running inside kici repo
|
|
59
|
+
*/
|
|
60
|
+
async function isInKiciRepo() {
|
|
61
|
+
try {
|
|
62
|
+
const content = await readFile(path.resolve(process.cwd(), "package.json"), "utf-8");
|
|
63
|
+
return JSON.parse(content).kici?.development === true;
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolve and validate the SDK dist path from a base kici repo path.
|
|
70
|
+
*
|
|
71
|
+
* @returns Absolute path to SDK dist/index.js, or null if not found
|
|
72
|
+
*/
|
|
73
|
+
function resolveAndValidateSdkPath(basePath) {
|
|
74
|
+
const sdkPath = path.resolve(basePath, "packages/sdk/dist/index.js");
|
|
75
|
+
if (!existsSync(sdkPath)) {
|
|
76
|
+
logger.warn("[kici] sdkPath configured but SDK not found at path");
|
|
77
|
+
logger.warn(`[kici] Expected: ${sdkPath}`);
|
|
78
|
+
logger.warn("[kici] Hint: run \"pnpm build\" in the kici repo");
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
if (process.env.KICI_DEBUG === "true") logger.warn(`[kici] SDK alias resolved to: ${sdkPath}`);
|
|
82
|
+
return sdkPath;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get TypeScript path mappings for IDE support.
|
|
86
|
+
*
|
|
87
|
+
* Returns path mapping configuration to include in tsconfig.json:
|
|
88
|
+
* - Points @kici-dev/sdk to local source for autocomplete
|
|
89
|
+
* - Only if sdkPath is configured and valid
|
|
90
|
+
*
|
|
91
|
+
* @returns TypeScript paths config, or null if not applicable
|
|
92
|
+
*/
|
|
93
|
+
async function getTypeScriptPaths() {
|
|
94
|
+
const basePath = await getSdkPathFromPackageJson();
|
|
95
|
+
if (!basePath) return null;
|
|
96
|
+
if (await isInKiciRepo()) return null;
|
|
97
|
+
return { "@kici-dev/sdk": [path.resolve(basePath, "packages/sdk/src/index.ts")] };
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { getSdkAliasConfig, getTypeScriptPaths };
|
|
101
|
+
|
|
102
|
+
//# sourceMappingURL=sdk-alias.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixture auto-compilation pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Discovers and dynamic-imports Fixture exports from `.kici/tests/*.ts` files.
|
|
5
|
+
* TypeScript transformation is handled by the shared oxc-transform ESM loader
|
|
6
|
+
* hook registered by the kici CLI bin (`@kici-dev/shared/ts-loader-hook`),
|
|
7
|
+
* which is the same hook the agent registers. Fixture files are imported in
|
|
8
|
+
* place so Node resolves `@kici-dev/sdk` from the customer's
|
|
9
|
+
* `.kici/node_modules/` — no temp files, no Rolldown bundle step.
|
|
10
|
+
*/
|
|
11
|
+
import type { Fixture } from '@kici-dev/sdk';
|
|
12
|
+
/** A compiled fixture with source tracking */
|
|
13
|
+
export interface CompiledFixture {
|
|
14
|
+
/** Fixture ID */
|
|
15
|
+
id: string;
|
|
16
|
+
/** Absolute path to the source file */
|
|
17
|
+
sourceFile: string;
|
|
18
|
+
/** Resolved fixture definition */
|
|
19
|
+
fixture: Fixture;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Discover fixture files in the tests directory.
|
|
23
|
+
*
|
|
24
|
+
* Scans recursively for `*.ts` files.
|
|
25
|
+
* Returns empty array if directory doesn't exist (not an error).
|
|
26
|
+
*/
|
|
27
|
+
export declare function discoverFixtureFiles(testsDir: string): Promise<string[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Compile and extract fixtures from all `.kici/tests/*.ts` files.
|
|
30
|
+
*
|
|
31
|
+
* Process:
|
|
32
|
+
* 1. Discover fixture files.
|
|
33
|
+
* 2. Dynamic-import each `.ts` file (transformed on the fly by the shared
|
|
34
|
+
* oxc-transform ESM loader hook registered by the kici CLI bin).
|
|
35
|
+
* 3. Extract Fixture exports.
|
|
36
|
+
* 4. Resolve async factory fixtures.
|
|
37
|
+
* 5. Validate no duplicate fixture IDs.
|
|
38
|
+
*/
|
|
39
|
+
export declare function compileFixtures(testsDir: string): Promise<CompiledFixture[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Filter compiled fixtures by pattern.
|
|
42
|
+
*
|
|
43
|
+
* - Exact match on fixture ID
|
|
44
|
+
* - Glob pattern matching via picomatch
|
|
45
|
+
*/
|
|
46
|
+
export declare function filterFixtures(fixtures: CompiledFixture[], pattern: string): CompiledFixture[];
|
|
47
|
+
//# sourceMappingURL=compiler.d.ts.map
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
|
+
import picomatch from "picomatch";
|
|
6
|
+
//#region src/fixtures/compiler.ts
|
|
7
|
+
/**
|
|
8
|
+
* Fixture auto-compilation pipeline.
|
|
9
|
+
*
|
|
10
|
+
* Discovers and dynamic-imports Fixture exports from `.kici/tests/*.ts` files.
|
|
11
|
+
* TypeScript transformation is handled by the shared oxc-transform ESM loader
|
|
12
|
+
* hook registered by the kici CLI bin (`@kici-dev/shared/ts-loader-hook`),
|
|
13
|
+
* which is the same hook the agent registers. Fixture files are imported in
|
|
14
|
+
* place so Node resolves `@kici-dev/sdk` from the customer's
|
|
15
|
+
* `.kici/node_modules/` — no temp files, no Rolldown bundle step.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Discover fixture files in the tests directory.
|
|
19
|
+
*
|
|
20
|
+
* Scans recursively for `*.ts` files.
|
|
21
|
+
* Returns empty array if directory doesn't exist (not an error).
|
|
22
|
+
*/
|
|
23
|
+
async function discoverFixtureFiles(testsDir) {
|
|
24
|
+
const absoluteDir = path.resolve(testsDir);
|
|
25
|
+
try {
|
|
26
|
+
if (!(await fs.stat(absoluteDir)).isDirectory()) return [];
|
|
27
|
+
} catch {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
return (await scanDirectory(absoluteDir)).sort();
|
|
31
|
+
}
|
|
32
|
+
async function scanDirectory(dir) {
|
|
33
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
34
|
+
const results = [];
|
|
35
|
+
for (const entry of entries) {
|
|
36
|
+
const fullPath = path.join(dir, entry.name);
|
|
37
|
+
if (entry.isDirectory()) {
|
|
38
|
+
const nested = await scanDirectory(fullPath);
|
|
39
|
+
results.push(...nested);
|
|
40
|
+
} else if (entry.isFile() && entry.name.endsWith(".ts") && !entry.name.endsWith(".d.ts")) results.push(fullPath);
|
|
41
|
+
}
|
|
42
|
+
return results;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Compile and extract fixtures from all `.kici/tests/*.ts` files.
|
|
46
|
+
*
|
|
47
|
+
* Process:
|
|
48
|
+
* 1. Discover fixture files.
|
|
49
|
+
* 2. Dynamic-import each `.ts` file (transformed on the fly by the shared
|
|
50
|
+
* oxc-transform ESM loader hook registered by the kici CLI bin).
|
|
51
|
+
* 3. Extract Fixture exports.
|
|
52
|
+
* 4. Resolve async factory fixtures.
|
|
53
|
+
* 5. Validate no duplicate fixture IDs.
|
|
54
|
+
*/
|
|
55
|
+
async function compileFixtures(testsDir) {
|
|
56
|
+
const files = await discoverFixtureFiles(testsDir);
|
|
57
|
+
if (files.length === 0) return [];
|
|
58
|
+
const allFixtures = [];
|
|
59
|
+
for (const file of files) {
|
|
60
|
+
const fixtures = await loadFixtureFile(file);
|
|
61
|
+
allFixtures.push(...fixtures);
|
|
62
|
+
}
|
|
63
|
+
const seenIds = /* @__PURE__ */ new Map();
|
|
64
|
+
for (const cf of allFixtures) {
|
|
65
|
+
const existing = seenIds.get(cf.id);
|
|
66
|
+
if (existing) throw new Error(`Duplicate fixture ID "${cf.id}" found in:\n - ${existing}\n - ${cf.sourceFile}`);
|
|
67
|
+
seenIds.set(cf.id, cf.sourceFile);
|
|
68
|
+
}
|
|
69
|
+
return allFixtures;
|
|
70
|
+
}
|
|
71
|
+
async function loadFixtureFile(filePath) {
|
|
72
|
+
const createdLinks = await ensureRuntimeSymlinks(filePath);
|
|
73
|
+
let mod;
|
|
74
|
+
try {
|
|
75
|
+
mod = await import(pathToFileURL(filePath).href + `?t=${Date.now()}`);
|
|
76
|
+
} catch (err) {
|
|
77
|
+
throw new Error(`Failed to load fixture module ${filePath}: ${err.message}`);
|
|
78
|
+
} finally {
|
|
79
|
+
for (const link of createdLinks.reverse()) await fs.rm(link, {
|
|
80
|
+
recursive: true,
|
|
81
|
+
force: true
|
|
82
|
+
}).catch(() => {});
|
|
83
|
+
}
|
|
84
|
+
const fixtures = [];
|
|
85
|
+
for (const [key, value] of Object.entries(mod)) {
|
|
86
|
+
if (key === "default") continue;
|
|
87
|
+
if (isFixture(value)) {
|
|
88
|
+
const resolved = await resolveFixture(value);
|
|
89
|
+
fixtures.push({
|
|
90
|
+
id: resolved.id,
|
|
91
|
+
sourceFile: filePath,
|
|
92
|
+
fixture: resolved
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return fixtures;
|
|
97
|
+
}
|
|
98
|
+
const RUNTIME_PACKAGES = [
|
|
99
|
+
"@kici-dev/sdk",
|
|
100
|
+
"zx",
|
|
101
|
+
"@kici-dev/shared"
|
|
102
|
+
];
|
|
103
|
+
async function ensureRuntimeSymlinks(filePath) {
|
|
104
|
+
const created = [];
|
|
105
|
+
let nodeModulesDir = await findNearestNodeModules(path.dirname(filePath));
|
|
106
|
+
if (!nodeModulesDir) {
|
|
107
|
+
nodeModulesDir = path.join(path.dirname(filePath), "node_modules");
|
|
108
|
+
await fs.mkdir(nodeModulesDir, { recursive: true });
|
|
109
|
+
created.push(nodeModulesDir);
|
|
110
|
+
}
|
|
111
|
+
for (const pkg of RUNTIME_PACKAGES) {
|
|
112
|
+
const linkPath = path.join(nodeModulesDir, pkg);
|
|
113
|
+
try {
|
|
114
|
+
await fs.access(linkPath);
|
|
115
|
+
continue;
|
|
116
|
+
} catch {}
|
|
117
|
+
try {
|
|
118
|
+
const pkgDir = await findPackageRoot(fileURLToPath(import.meta.resolve(pkg)));
|
|
119
|
+
const linkParent = path.dirname(linkPath);
|
|
120
|
+
if (linkParent !== nodeModulesDir) await fs.mkdir(linkParent, { recursive: true });
|
|
121
|
+
await fs.symlink(pkgDir, linkPath);
|
|
122
|
+
created.push(linkPath);
|
|
123
|
+
} catch {}
|
|
124
|
+
}
|
|
125
|
+
return created;
|
|
126
|
+
}
|
|
127
|
+
async function findNearestNodeModules(startDir) {
|
|
128
|
+
let dir = startDir;
|
|
129
|
+
while (dir !== path.dirname(dir)) {
|
|
130
|
+
const nm = path.join(dir, "node_modules");
|
|
131
|
+
try {
|
|
132
|
+
if ((await fs.stat(nm)).isDirectory()) return nm;
|
|
133
|
+
} catch {}
|
|
134
|
+
dir = path.dirname(dir);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async function findPackageRoot(filePath) {
|
|
138
|
+
let dir = path.dirname(filePath);
|
|
139
|
+
while (dir !== path.dirname(dir)) try {
|
|
140
|
+
await fs.access(path.join(dir, "package.json"));
|
|
141
|
+
return dir;
|
|
142
|
+
} catch {
|
|
143
|
+
dir = path.dirname(dir);
|
|
144
|
+
}
|
|
145
|
+
return path.dirname(filePath);
|
|
146
|
+
}
|
|
147
|
+
function isFixture(value) {
|
|
148
|
+
if (typeof value !== "object" || value === null) return false;
|
|
149
|
+
const obj = value;
|
|
150
|
+
return typeof obj.id === "string" && obj.id.length > 0 && (typeof obj.options === "object" || typeof obj.options === "function") && obj.options !== null;
|
|
151
|
+
}
|
|
152
|
+
async function resolveFixture(fixture) {
|
|
153
|
+
if (typeof fixture.options === "function") {
|
|
154
|
+
const resolved = await fixture.options();
|
|
155
|
+
return Object.freeze({
|
|
156
|
+
id: fixture.id,
|
|
157
|
+
options: Object.freeze(resolved)
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return fixture;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Filter compiled fixtures by pattern.
|
|
164
|
+
*
|
|
165
|
+
* - Exact match on fixture ID
|
|
166
|
+
* - Glob pattern matching via picomatch
|
|
167
|
+
*/
|
|
168
|
+
function filterFixtures(fixtures, pattern) {
|
|
169
|
+
const exact = fixtures.find((f) => f.id === pattern);
|
|
170
|
+
if (exact) return [exact];
|
|
171
|
+
const isMatch = picomatch(pattern);
|
|
172
|
+
return fixtures.filter((f) => isMatch(f.id)).sort((a, b) => a.id.localeCompare(b.id));
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
175
|
+
export { compileFixtures, discoverFixtureFiles, filterFixtures };
|
|
176
|
+
|
|
177
|
+
//# sourceMappingURL=compiler.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"action": "created",
|
|
3
|
+
"comment": {
|
|
4
|
+
"id": 1,
|
|
5
|
+
"body": "Looks good to me!",
|
|
6
|
+
"user": {
|
|
7
|
+
"login": "test-user"
|
|
8
|
+
},
|
|
9
|
+
"created_at": "2026-01-01T00:00:00Z"
|
|
10
|
+
},
|
|
11
|
+
"issue": {
|
|
12
|
+
"number": 42,
|
|
13
|
+
"title": "Test issue",
|
|
14
|
+
"state": "open",
|
|
15
|
+
"pull_request": {
|
|
16
|
+
"url": "https://api.github.com/repos/test-org/test-repo/pulls/42"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"name": "test-repo",
|
|
21
|
+
"full_name": "test-org/test-repo",
|
|
22
|
+
"owner": {
|
|
23
|
+
"login": "test-org"
|
|
24
|
+
},
|
|
25
|
+
"default_branch": "main"
|
|
26
|
+
},
|
|
27
|
+
"sender": {
|
|
28
|
+
"login": "test-user"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ref": "feature/new",
|
|
3
|
+
"ref_type": "branch",
|
|
4
|
+
"master_branch": "main",
|
|
5
|
+
"description": null,
|
|
6
|
+
"repository": {
|
|
7
|
+
"name": "test-repo",
|
|
8
|
+
"full_name": "test-org/test-repo",
|
|
9
|
+
"owner": {
|
|
10
|
+
"login": "test-org"
|
|
11
|
+
},
|
|
12
|
+
"default_branch": "main"
|
|
13
|
+
},
|
|
14
|
+
"sender": {
|
|
15
|
+
"login": "test-user"
|
|
16
|
+
}
|
|
17
|
+
}
|