@kici-dev/compiler 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/commands/compile.js +1 -13
  3. package/dist/commands/preview.js +1 -8
  4. package/dist/commands/types.js +1 -2
  5. package/dist/errors/formatter.d.ts +2 -4
  6. package/dist/errors/formatter.js +1 -3
  7. package/dist/errors/index.d.ts +1 -1
  8. package/dist/errors/index.js +2 -2
  9. package/dist/generators/secrets-dts.d.ts +0 -1
  10. package/dist/generators/secrets-dts.js +1 -2
  11. package/dist/llm-context/llms-architecture.txt +27 -13
  12. package/dist/llm-context/llms-cli.txt +26 -6
  13. package/dist/llm-context/llms-features.txt +272 -91
  14. package/dist/llm-context/llms-full.txt +649 -235
  15. package/dist/llm-context/llms-getting-started.txt +20 -20
  16. package/dist/llm-context/llms-patterns.txt +10 -6
  17. package/dist/llm-context/llms-providers.txt +4 -6
  18. package/dist/llm-context/llms-sdk-runtime.txt +37 -36
  19. package/dist/llm-context/llms-sdk.txt +253 -57
  20. package/dist/llm-context/llms.txt +6 -6
  21. package/dist/local-plane/plane-manager.js +2 -2
  22. package/dist/lockfile/generator.js +137 -42
  23. package/dist/lockfile/index.d.ts +0 -2
  24. package/dist/lockfile/index.js +1 -2
  25. package/dist/templates/package-json.js +1 -1
  26. package/dist/test-runner/dry-run.d.ts +1 -2
  27. package/dist/test-runner/dry-run.js +1 -18
  28. package/dist/types.d.ts +32 -8
  29. package/dist/types.js +7 -1
  30. package/dist/validation/validator.js +40 -0
  31. package/package.json +6 -6
  32. package/sbom.spdx.json +126 -121
  33. package/dist/lockfile/purity-analyzer.d.ts +0 -25
  34. package/dist/lockfile/purity-analyzer.js +0 -204
  35. package/dist/lockfile/purity-diagnostics.d.ts +0 -31
  36. package/dist/lockfile/purity-diagnostics.js +0 -52
@@ -1,25 +0,0 @@
1
- /**
2
- * AST-based purity analysis for dynamic job functions.
3
- * Determines whether a function can be safely evaluated inline by the orchestrator
4
- * (via vm.runInNewContext) without requiring a full init job dispatch.
5
- *
6
- * A function is "pure" if it:
7
- * - Is synchronous (not async)
8
- * - Only references its parameters and safe globals
9
- * - Does not perform I/O, mutation, or use external scope
10
- * - Only uses const/let for local declarations (no var)
11
- */
12
- /** Result of purity analysis */
13
- interface PurityResult {
14
- pure: boolean;
15
- reason?: string;
16
- }
17
- /**
18
- * Analyze whether a function source string represents a pure function.
19
- *
20
- * @param fnSource - The function source code (e.g., "(event) => event.ref")
21
- * @returns PurityResult indicating whether the function is pure
22
- */
23
- export declare function analyzePurity(fnSource: string): PurityResult;
24
- export {};
25
- //# sourceMappingURL=purity-analyzer.d.ts.map
@@ -1,204 +0,0 @@
1
- import "../rolldown-runtime-ClRpJifh.js";
2
- import ts from "typescript";
3
- //#region src/lockfile/purity-analyzer.ts
4
- /**
5
- * AST-based purity analysis for dynamic job functions.
6
- * Determines whether a function can be safely evaluated inline by the orchestrator
7
- * (via vm.runInNewContext) without requiring a full init job dispatch.
8
- *
9
- * A function is "pure" if it:
10
- * - Is synchronous (not async)
11
- * - Only references its parameters and safe globals
12
- * - Does not perform I/O, mutation, or use external scope
13
- * - Only uses const/let for local declarations (no var)
14
- */
15
- /**
16
- * Safe globals that pure functions are allowed to reference.
17
- * These are deterministic, side-effect-free built-ins.
18
- */
19
- const SAFE_GLOBALS = /* @__PURE__ */ new Set([
20
- "undefined",
21
- "null",
22
- "true",
23
- "false",
24
- "NaN",
25
- "Infinity",
26
- "String",
27
- "Number",
28
- "Boolean",
29
- "Array",
30
- "Object",
31
- "JSON",
32
- "Math",
33
- "parseInt",
34
- "parseFloat",
35
- "isNaN",
36
- "isFinite",
37
- "encodeURIComponent",
38
- "decodeURIComponent",
39
- "encodeURI",
40
- "decodeURI"
41
- ]);
42
- /**
43
- * Assignment operators that indicate mutation.
44
- */
45
- const ASSIGNMENT_OPERATORS = /* @__PURE__ */ new Set([
46
- ts.SyntaxKind.EqualsToken,
47
- ts.SyntaxKind.PlusEqualsToken,
48
- ts.SyntaxKind.MinusEqualsToken,
49
- ts.SyntaxKind.AsteriskEqualsToken,
50
- ts.SyntaxKind.SlashEqualsToken,
51
- ts.SyntaxKind.PercentEqualsToken,
52
- ts.SyntaxKind.AmpersandEqualsToken,
53
- ts.SyntaxKind.BarEqualsToken,
54
- ts.SyntaxKind.CaretEqualsToken,
55
- ts.SyntaxKind.LessThanLessThanEqualsToken,
56
- ts.SyntaxKind.GreaterThanGreaterThanEqualsToken,
57
- ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken,
58
- ts.SyntaxKind.AsteriskAsteriskEqualsToken,
59
- ts.SyntaxKind.BarBarEqualsToken,
60
- ts.SyntaxKind.AmpersandAmpersandEqualsToken,
61
- ts.SyntaxKind.QuestionQuestionEqualsToken
62
- ]);
63
- /**
64
- * Analyze whether a function source string represents a pure function.
65
- *
66
- * @param fnSource - The function source code (e.g., "(event) => event.ref")
67
- * @returns PurityResult indicating whether the function is pure
68
- */
69
- function analyzePurity(fnSource) {
70
- const wrapped = "const __fn = " + fnSource;
71
- const firstStatement = ts.createSourceFile("inline.js", wrapped, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS).statements[0];
72
- if (!ts.isVariableStatement(firstStatement)) return {
73
- pure: false,
74
- reason: "failed to parse function source"
75
- };
76
- const declaration = firstStatement.declarationList.declarations[0];
77
- if (!declaration.initializer) return {
78
- pure: false,
79
- reason: "failed to parse function source"
80
- };
81
- const fnNode = declaration.initializer;
82
- if (!ts.isArrowFunction(fnNode) && !ts.isFunctionExpression(fnNode)) return {
83
- pure: false,
84
- reason: "not a function expression"
85
- };
86
- if (ts.getModifiers(fnNode)?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword)) return {
87
- pure: false,
88
- reason: "async functions cannot be inlined"
89
- };
90
- if (ts.isFunctionExpression(fnNode) && fnNode.asteriskToken) return {
91
- pure: false,
92
- reason: "generator functions cannot be inlined"
93
- };
94
- const paramNames = /* @__PURE__ */ new Set();
95
- for (const param of fnNode.parameters) collectBindingNames(param.name, paramNames);
96
- const localNames = /* @__PURE__ */ new Set();
97
- return checkNode(fnNode.body, paramNames, localNames) ?? { pure: true };
98
- }
99
- /**
100
- * Recursively collect binding names from parameter declarations,
101
- * including destructured patterns.
102
- */
103
- function collectBindingNames(node, names) {
104
- if (ts.isIdentifier(node)) names.add(node.text);
105
- else if (ts.isObjectBindingPattern(node)) for (const element of node.elements) collectBindingNames(element.name, names);
106
- else if (ts.isArrayBindingPattern(node)) {
107
- for (const element of node.elements) if (!ts.isOmittedExpression(element)) collectBindingNames(element.name, names);
108
- }
109
- }
110
- /**
111
- * Check a node and its children for impurity.
112
- * Returns a PurityResult if impure, or undefined if pure so far.
113
- */
114
- function checkNode(node, paramNames, localNames) {
115
- switch (node.kind) {
116
- case ts.SyntaxKind.AwaitExpression: return {
117
- pure: false,
118
- reason: "contains await expression"
119
- };
120
- case ts.SyntaxKind.ImportDeclaration: return {
121
- pure: false,
122
- reason: "contains import declaration"
123
- };
124
- case ts.SyntaxKind.YieldExpression: return {
125
- pure: false,
126
- reason: "contains yield expression"
127
- };
128
- case ts.SyntaxKind.ClassDeclaration:
129
- case ts.SyntaxKind.ClassExpression: return {
130
- pure: false,
131
- reason: "contains class declaration"
132
- };
133
- case ts.SyntaxKind.ThisKeyword: return {
134
- pure: false,
135
- reason: "references 'this'"
136
- };
137
- case ts.SyntaxKind.DeleteExpression: return {
138
- pure: false,
139
- reason: "contains 'delete' expression"
140
- };
141
- case ts.SyntaxKind.ThrowStatement: return {
142
- pure: false,
143
- reason: "contains throw statement"
144
- };
145
- case ts.SyntaxKind.TryStatement: return {
146
- pure: false,
147
- reason: "contains try/catch"
148
- };
149
- }
150
- if (ts.isNewExpression(node)) return {
151
- pure: false,
152
- reason: "contains 'new' expression"
153
- };
154
- if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) return {
155
- pure: false,
156
- reason: "contains dynamic import"
157
- };
158
- if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "require") return {
159
- pure: false,
160
- reason: "contains require() call"
161
- };
162
- if (ts.isPostfixUnaryExpression(node)) {
163
- if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken) return {
164
- pure: false,
165
- reason: "contains mutation operator"
166
- };
167
- }
168
- if (ts.isPrefixUnaryExpression(node)) {
169
- if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken) return {
170
- pure: false,
171
- reason: "contains mutation operator"
172
- };
173
- }
174
- if (ts.isBinaryExpression(node) && ASSIGNMENT_OPERATORS.has(node.operatorToken.kind)) return {
175
- pure: false,
176
- reason: "contains assignment"
177
- };
178
- if (ts.isVariableDeclarationList(node)) if (node.flags & ts.NodeFlags.Const || node.flags & ts.NodeFlags.Let) for (const decl of node.declarations) collectBindingNames(decl.name, localNames);
179
- else return {
180
- pure: false,
181
- reason: "'var' declarations are not allowed (use const or let)"
182
- };
183
- if (ts.isIdentifier(node)) {
184
- const parent = node.parent;
185
- if (ts.isPropertyAccessExpression(parent) && parent.name === node) {} else if (ts.isPropertyAssignment(parent) && parent.name === node) {} else if (ts.isShorthandPropertyAssignment(parent) && parent.name === node) {
186
- if (!paramNames.has(node.text) && !localNames.has(node.text) && !SAFE_GLOBALS.has(node.text)) return {
187
- pure: false,
188
- reason: `references unknown identifier '${node.text}'`
189
- };
190
- } else if (ts.isVariableDeclaration(parent) && parent.name === node) {} else if (ts.isBindingElement(parent) && parent.name === node) {} else if (ts.isParameter(parent) && parent.name === node) {} else if (!paramNames.has(node.text) && !localNames.has(node.text) && !SAFE_GLOBALS.has(node.text)) return {
191
- pure: false,
192
- reason: `references unknown identifier '${node.text}'`
193
- };
194
- }
195
- const children = node.getChildren();
196
- for (const child of children) {
197
- const result = checkNode(child, paramNames, localNames);
198
- if (result) return result;
199
- }
200
- }
201
- //#endregion
202
- export { analyzePurity };
203
-
204
- //# sourceMappingURL=purity-analyzer.js.map
@@ -1,31 +0,0 @@
1
- import type { Job } from '@kici-dev/sdk';
2
- import type { WorkflowWithSource } from '../types.js';
3
- /** Which dynamic-value slot on a job carried the impure function. */
4
- export declare enum DynamicValueField {
5
- Context = "context",
6
- Env = "env",
7
- ConcurrencyGroup = "concurrencyGroup"
8
- }
9
- /**
10
- * One impure dynamic-value function found on a static job. Each impurity forces
11
- * the orchestrator to dispatch an agent-side `__init__` job (~5-10s) instead of
12
- * inlining the value, so we surface it to the author at compile / preview time.
13
- */
14
- export interface JobPurityWarning {
15
- workflowName: string;
16
- sourceFile?: string;
17
- jobName: string;
18
- field: DynamicValueField;
19
- reason: string;
20
- }
21
- /**
22
- * Analyze a single static job's dynamic-value functions (context(s), env,
23
- * concurrencyGroup) for impurity. Returns one warning per impure function.
24
- */
25
- export declare function analyzeJobPurity(job: Job, workflowName: string, sourceFile?: string): JobPurityWarning[];
26
- /**
27
- * Walk every workflow's static jobs and collect impurity warnings. Function-typed
28
- * jobs (dynamic job generators) are skipped — their purity is analyzed at dispatch.
29
- */
30
- export declare function collectWorkflowPurityWarnings(workflows: WorkflowWithSource[]): JobPurityWarning[];
31
- //# sourceMappingURL=purity-diagnostics.d.ts.map
@@ -1,52 +0,0 @@
1
- import "../rolldown-runtime-ClRpJifh.js";
2
- import { analyzePurity } from "./purity-analyzer.js";
3
- //#region src/lockfile/purity-diagnostics.ts
4
- /** Which dynamic-value slot on a job carried the impure function. */
5
- let DynamicValueField = /* @__PURE__ */ function(DynamicValueField) {
6
- DynamicValueField["Context"] = "context";
7
- DynamicValueField["Env"] = "env";
8
- DynamicValueField["ConcurrencyGroup"] = "concurrencyGroup";
9
- return DynamicValueField;
10
- }({});
11
- function pushIfImpure(out, fn, field, base) {
12
- if (typeof fn !== "function") return;
13
- const result = analyzePurity(fn.toString());
14
- if (!result.pure) out.push({
15
- ...base,
16
- field,
17
- reason: result.reason ?? "unknown"
18
- });
19
- }
20
- /**
21
- * Analyze a single static job's dynamic-value functions (context(s), env,
22
- * concurrencyGroup) for impurity. Returns one warning per impure function.
23
- */
24
- function analyzeJobPurity(job, workflowName, sourceFile) {
25
- const out = [];
26
- const base = {
27
- workflowName,
28
- sourceFile,
29
- jobName: job.name
30
- };
31
- const contextRefs = job.contexts ?? (job.context !== void 0 ? [job.context] : void 0);
32
- if (contextRefs) for (const ref of contextRefs) pushIfImpure(out, ref, "context", base);
33
- pushIfImpure(out, job.env, "env", base);
34
- pushIfImpure(out, job.concurrencyGroup, "concurrencyGroup", base);
35
- return out;
36
- }
37
- /**
38
- * Walk every workflow's static jobs and collect impurity warnings. Function-typed
39
- * jobs (dynamic job generators) are skipped — their purity is analyzed at dispatch.
40
- */
41
- function collectWorkflowPurityWarnings(workflows) {
42
- const out = [];
43
- for (const { workflow, source } of workflows) for (const job of workflow.jobs) {
44
- if (typeof job === "function") continue;
45
- out.push(...analyzeJobPurity(job, workflow.name, source.file));
46
- }
47
- return out;
48
- }
49
- //#endregion
50
- export { DynamicValueField, analyzeJobPurity, collectWorkflowPurityWarnings };
51
-
52
- //# sourceMappingURL=purity-diagnostics.js.map