@akanjs/devkit 2.3.9-rc.1 → 2.3.9-rc.10
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/akanContext.ts +195 -14
- package/akanMcpContract.test.ts +37 -0
- package/akanMcpContract.ts +701 -0
- package/devkitUtils.test.ts +2 -2
- package/executors.ts +22 -17
- package/getModelFileData.ts +5 -2
- package/index.ts +1 -0
- package/package.json +2 -2
- package/workflow/artifacts.ts +571 -0
- package/workflow/executor.ts +590 -0
- package/workflow/index.ts +11 -1089
- package/workflow/moduleIndex.test.ts +296 -0
- package/workflow/moduleIndex.ts +504 -0
- package/workflow/plan.ts +429 -0
- package/workflow/primitive.ts +59 -0
- package/workflow/render.ts +335 -0
- package/workflow/rolloutGate.test.ts +109 -0
- package/workflow/rolloutGate.ts +141 -0
- package/workflow/source.test.ts +62 -0
- package/workflow/source.ts +864 -0
- package/workflow/types.ts +475 -0
- package/workflow/uiPolicy.ts +45 -0
- package/workflow/utils.ts +23 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import type { Sys, Workspace } from "../commandDecorators";
|
|
2
|
+
import type { FieldDefaultValue } from "./source";
|
|
3
|
+
|
|
4
|
+
export type WorkflowInputType = "string" | "string-list" | "surface-mode" | "boolean";
|
|
5
|
+
export type WorkflowSurfaceMode = "infer" | "include" | "skip";
|
|
6
|
+
export type WorkflowInputValue = string | string[] | boolean | WorkflowSurfaceMode;
|
|
7
|
+
export type WorkflowFormat = "markdown" | "json";
|
|
8
|
+
export type WorkflowPlanInputs = Record<string, string | null>;
|
|
9
|
+
export type PrimitiveFormat = "markdown" | "json";
|
|
10
|
+
export type UiSurface = "view" | "unit" | "template";
|
|
11
|
+
export type WorkflowValidationKind = "sync" | "lint" | "typecheck" | "doctor" | "custom";
|
|
12
|
+
export type WorkflowFailureScope = "workspace-config" | "environment" | "source-change" | "unknown";
|
|
13
|
+
export type WorkflowValidationStatus = "passed" | "failed" | "unknown";
|
|
14
|
+
export interface WorkflowValidationSummary {
|
|
15
|
+
sourceChange: WorkflowValidationStatus;
|
|
16
|
+
generatedSync: WorkflowValidationStatus;
|
|
17
|
+
validationCommands: WorkflowValidationStatus;
|
|
18
|
+
baseline: WorkflowValidationStatus;
|
|
19
|
+
workspaceConfig: WorkflowValidationStatus;
|
|
20
|
+
environment: WorkflowValidationStatus;
|
|
21
|
+
}
|
|
22
|
+
export type WorkflowOverallStatus =
|
|
23
|
+
| "passed"
|
|
24
|
+
| "failed"
|
|
25
|
+
| "passed-with-baseline-blockers"
|
|
26
|
+
| "blocked-by-workspace-config"
|
|
27
|
+
| "blocked-by-environment";
|
|
28
|
+
|
|
29
|
+
export interface PrimitiveTargetInput {
|
|
30
|
+
app: string | null;
|
|
31
|
+
module: string | null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface AddFieldInput extends PrimitiveTargetInput {
|
|
35
|
+
field: string | null;
|
|
36
|
+
type: string | null;
|
|
37
|
+
defaultValue?: FieldDefaultValue;
|
|
38
|
+
surfaces?: string[] | null;
|
|
39
|
+
includeInLight?: boolean | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface AddEnumFieldInput extends PrimitiveTargetInput {
|
|
43
|
+
field: string | null;
|
|
44
|
+
values: string | null;
|
|
45
|
+
defaultValue?: FieldDefaultValue;
|
|
46
|
+
surfaces?: string[] | null;
|
|
47
|
+
includeInLight?: boolean | null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface WorkflowInputSpec {
|
|
51
|
+
type: WorkflowInputType;
|
|
52
|
+
required?: boolean;
|
|
53
|
+
description: string;
|
|
54
|
+
allowedValues?: readonly string[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface WorkflowStep {
|
|
58
|
+
id: string;
|
|
59
|
+
title: string;
|
|
60
|
+
tool: string;
|
|
61
|
+
description: string;
|
|
62
|
+
when?: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface WorkflowPredictedChange {
|
|
66
|
+
target: string;
|
|
67
|
+
action: "inspect" | "create" | "modify" | "sync" | "validate";
|
|
68
|
+
reason: string;
|
|
69
|
+
applyScope?: "auto" | "manual-review" | "generated-sync" | "validation";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface WorkflowValidation {
|
|
73
|
+
command: string;
|
|
74
|
+
reason: string;
|
|
75
|
+
kind?: WorkflowValidationKind;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface WorkflowSpec {
|
|
79
|
+
schemaVersion: 1;
|
|
80
|
+
name: string;
|
|
81
|
+
description: string;
|
|
82
|
+
whenToUse: string;
|
|
83
|
+
inputs: Record<string, WorkflowInputSpec>;
|
|
84
|
+
optionalSurfaces?: Record<string, WorkflowSurfaceMode>;
|
|
85
|
+
steps: readonly WorkflowStep[];
|
|
86
|
+
predictedChanges: readonly WorkflowPredictedChange[];
|
|
87
|
+
validation: readonly WorkflowValidation[];
|
|
88
|
+
completionCriteria: readonly string[];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface WorkflowDiagnostic {
|
|
92
|
+
severity: "warning" | "error";
|
|
93
|
+
code: string;
|
|
94
|
+
message: string;
|
|
95
|
+
input?: string;
|
|
96
|
+
command?: string;
|
|
97
|
+
kind?: WorkflowValidationKind;
|
|
98
|
+
failureScope?: WorkflowFailureScope;
|
|
99
|
+
scope?: "baseline" | "workflow" | "unknown";
|
|
100
|
+
context?: {
|
|
101
|
+
workflow?: string;
|
|
102
|
+
planPath?: string;
|
|
103
|
+
runId?: string;
|
|
104
|
+
target?: string;
|
|
105
|
+
paths?: string[];
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface WorkflowRecommendation {
|
|
110
|
+
code: string;
|
|
111
|
+
message: string;
|
|
112
|
+
kind: "auto-apply" | "validation" | "manual-action" | "input-guidance" | "import" | "placement" | "ui-component";
|
|
113
|
+
target?: string;
|
|
114
|
+
action?: string;
|
|
115
|
+
confidence?: "high" | "medium" | "low";
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface WorkflowPlanApproval {
|
|
119
|
+
required: true;
|
|
120
|
+
meaning: string;
|
|
121
|
+
applyTool: "apply_workflow";
|
|
122
|
+
canApplyWith?: Record<string, string>;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface AkanSourceSpan {
|
|
126
|
+
file: string;
|
|
127
|
+
startLine: number;
|
|
128
|
+
endLine: number;
|
|
129
|
+
startOffset: number;
|
|
130
|
+
endOffset: number;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export type AkanIndexedFileKind =
|
|
134
|
+
| "abstract"
|
|
135
|
+
| "constant"
|
|
136
|
+
| "dictionary"
|
|
137
|
+
| "service"
|
|
138
|
+
| "signal"
|
|
139
|
+
| "store"
|
|
140
|
+
| "template"
|
|
141
|
+
| "unit"
|
|
142
|
+
| "util"
|
|
143
|
+
| "view"
|
|
144
|
+
| "zone"
|
|
145
|
+
| "other";
|
|
146
|
+
|
|
147
|
+
export interface AkanIndexedFile {
|
|
148
|
+
kind: AkanIndexedFileKind;
|
|
149
|
+
path: string;
|
|
150
|
+
expectedPath: string;
|
|
151
|
+
filename: string;
|
|
152
|
+
expectedFilename: string;
|
|
153
|
+
present: boolean;
|
|
154
|
+
casing: "match" | "mismatch" | "missing";
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export type AkanFieldOutlineKind = "constant" | "dictionary" | "lightProjection";
|
|
158
|
+
|
|
159
|
+
export interface AkanFieldOutline {
|
|
160
|
+
name: string;
|
|
161
|
+
kind: AkanFieldOutlineKind;
|
|
162
|
+
order: number;
|
|
163
|
+
typeSummary?: string;
|
|
164
|
+
sourceSpan: AkanSourceSpan;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface AkanProjectionOutline {
|
|
168
|
+
className: string;
|
|
169
|
+
fields: AkanFieldOutline[];
|
|
170
|
+
sourceSpan?: AkanSourceSpan;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface AkanConstantIndex {
|
|
174
|
+
path: string;
|
|
175
|
+
inputClassName: string;
|
|
176
|
+
builderName: string | null;
|
|
177
|
+
fields: AkanFieldOutline[];
|
|
178
|
+
lightProjection?: AkanProjectionOutline;
|
|
179
|
+
sourceSpan?: AkanSourceSpan;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export interface AkanDictionaryIndex {
|
|
183
|
+
path: string;
|
|
184
|
+
modelClassName: string;
|
|
185
|
+
translatorName: string | null;
|
|
186
|
+
fields: AkanFieldOutline[];
|
|
187
|
+
sourceSpan?: AkanSourceSpan;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export interface AkanFieldPresence {
|
|
191
|
+
name: string;
|
|
192
|
+
requested: boolean;
|
|
193
|
+
constant: boolean;
|
|
194
|
+
dictionary: boolean;
|
|
195
|
+
lightProjection: boolean;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export interface AkanModuleContextIndex {
|
|
199
|
+
schemaVersion: 1;
|
|
200
|
+
app: string;
|
|
201
|
+
module: string;
|
|
202
|
+
moduleClassName: string;
|
|
203
|
+
files: AkanIndexedFile[];
|
|
204
|
+
fieldPresence: AkanFieldPresence[];
|
|
205
|
+
constant?: AkanConstantIndex;
|
|
206
|
+
dictionary?: AkanDictionaryIndex;
|
|
207
|
+
diagnostics: WorkflowDiagnostic[];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export type InspectAkanContextRequest =
|
|
211
|
+
| { type: "workspaceOverview" }
|
|
212
|
+
| { type: "moduleContext"; app: string; module: string }
|
|
213
|
+
| { type: "fieldInsertionContext"; app: string; module: string; field: string; fieldType: string }
|
|
214
|
+
| { type: "workflowDiagnostics"; runIdOrPlan: string }
|
|
215
|
+
| { type: "escape"; reason: string; nextStep?: string };
|
|
216
|
+
|
|
217
|
+
export interface InspectAkanContextProps {
|
|
218
|
+
question: string;
|
|
219
|
+
draft: {
|
|
220
|
+
reason: string;
|
|
221
|
+
type: InspectAkanContextRequest["type"];
|
|
222
|
+
};
|
|
223
|
+
review: string;
|
|
224
|
+
request: InspectAkanContextRequest;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface AkanContextEvidence {
|
|
228
|
+
kind: "workspace" | "module" | "field-insertion" | "workflow" | "escape";
|
|
229
|
+
summary: string;
|
|
230
|
+
path?: string;
|
|
231
|
+
target?: string;
|
|
232
|
+
sourceSpan?: AkanSourceSpan;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export interface AkanContextNext {
|
|
236
|
+
action: "answer" | "inspect" | "plan_workflow" | "validate" | "escape" | "clarify";
|
|
237
|
+
reason: string;
|
|
238
|
+
tool?: string;
|
|
239
|
+
args?: Record<string, unknown>;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export interface InspectAkanContextResult {
|
|
243
|
+
schemaVersion: 1;
|
|
244
|
+
type: InspectAkanContextRequest["type"];
|
|
245
|
+
question: string;
|
|
246
|
+
diagnostics: WorkflowDiagnostic[];
|
|
247
|
+
evidence: AkanContextEvidence[];
|
|
248
|
+
next: AkanContextNext;
|
|
249
|
+
data?: Record<string, unknown>;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export interface WorkflowPlan {
|
|
253
|
+
schemaVersion: 1;
|
|
254
|
+
workflow: string;
|
|
255
|
+
mode: "plan";
|
|
256
|
+
inputs: Record<string, WorkflowInputValue>;
|
|
257
|
+
optionalSurfaces: Record<string, WorkflowSurfaceMode>;
|
|
258
|
+
steps: readonly WorkflowStep[];
|
|
259
|
+
predictedChanges: readonly WorkflowPredictedChange[];
|
|
260
|
+
validation: readonly WorkflowValidation[];
|
|
261
|
+
diagnostics: WorkflowDiagnostic[];
|
|
262
|
+
recommendations: WorkflowRecommendation[];
|
|
263
|
+
requiresApproval: true;
|
|
264
|
+
approval?: WorkflowPlanApproval;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export interface WorkflowReport {
|
|
268
|
+
schemaVersion: 1;
|
|
269
|
+
workflow: string;
|
|
270
|
+
mode: "plan" | "dry-run" | "apply";
|
|
271
|
+
status: "passed" | "failed";
|
|
272
|
+
diagnostics: WorkflowDiagnostic[];
|
|
273
|
+
plan?: WorkflowPlan;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export interface WorkflowApplyCommand {
|
|
277
|
+
command: string;
|
|
278
|
+
reason: string;
|
|
279
|
+
stepId?: string;
|
|
280
|
+
kind?: WorkflowValidationKind;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export type WorkflowRunSource =
|
|
284
|
+
| { type: "plan"; path: string }
|
|
285
|
+
| { type: "apply-report"; path: string; runId?: string }
|
|
286
|
+
| { type: "run-report"; runId: string };
|
|
287
|
+
|
|
288
|
+
export interface WorkflowValidationCommandResult {
|
|
289
|
+
command: string;
|
|
290
|
+
reason: string;
|
|
291
|
+
kind?: WorkflowValidationKind;
|
|
292
|
+
status: "passed" | "failed";
|
|
293
|
+
exitCode: number;
|
|
294
|
+
failureScope?: WorkflowFailureScope;
|
|
295
|
+
stdout?: string;
|
|
296
|
+
stderr?: string;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export interface WorkflowKnownBlocker {
|
|
300
|
+
code: string;
|
|
301
|
+
message: string;
|
|
302
|
+
failureScope: WorkflowFailureScope;
|
|
303
|
+
command?: string;
|
|
304
|
+
kind?: WorkflowValidationKind;
|
|
305
|
+
count: number;
|
|
306
|
+
known?: boolean;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export interface WorkflowBaselineSummaryCode {
|
|
310
|
+
code: string;
|
|
311
|
+
severity: "warning" | "error" | "mixed";
|
|
312
|
+
count: number;
|
|
313
|
+
sampleMessage: string;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export interface WorkflowBaselineSummary {
|
|
317
|
+
status: WorkflowValidationStatus;
|
|
318
|
+
total: number;
|
|
319
|
+
totalErrors: number;
|
|
320
|
+
totalWarnings: number;
|
|
321
|
+
detailsIncluded: boolean;
|
|
322
|
+
knownBlockerCount: number;
|
|
323
|
+
byCode: WorkflowBaselineSummaryCode[];
|
|
324
|
+
contextPaths?: string[];
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export interface RepairAction {
|
|
328
|
+
command: string;
|
|
329
|
+
reason: string;
|
|
330
|
+
kind: "generated" | "format" | "imports" | "dictionary" | "module-shape";
|
|
331
|
+
safeToRun: boolean;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export interface PrimitiveChangedFile {
|
|
335
|
+
path: string;
|
|
336
|
+
action: "create" | "modify" | "remove";
|
|
337
|
+
reason: string;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export interface WorkflowPostApplyCheck {
|
|
341
|
+
code: string;
|
|
342
|
+
target: string;
|
|
343
|
+
status: "passed" | "failed";
|
|
344
|
+
message: string;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export type WorkflowNextActionCode = "answer" | "validate" | "manual-review" | "repair" | "blocked";
|
|
348
|
+
|
|
349
|
+
export interface PrimitiveGeneratedFile {
|
|
350
|
+
path: string;
|
|
351
|
+
action: "sync";
|
|
352
|
+
reason: string;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export interface PrimitiveValidationCommand {
|
|
356
|
+
command: string;
|
|
357
|
+
reason: string;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export interface PrimitiveNextAction {
|
|
361
|
+
command: string;
|
|
362
|
+
reason: string;
|
|
363
|
+
action?: WorkflowNextActionCode;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export interface PrimitiveWriteReport {
|
|
367
|
+
schemaVersion: 1;
|
|
368
|
+
command: string;
|
|
369
|
+
status: "passed" | "failed";
|
|
370
|
+
changedFiles: PrimitiveChangedFile[];
|
|
371
|
+
generatedFiles: PrimitiveGeneratedFile[];
|
|
372
|
+
validationCommands: PrimitiveValidationCommand[];
|
|
373
|
+
diagnostics: WorkflowDiagnostic[];
|
|
374
|
+
nextActions: PrimitiveNextAction[];
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export type PrimitiveFileMap = Record<string, { filename: string; content: string }>;
|
|
378
|
+
|
|
379
|
+
export interface WorkflowApplyReport {
|
|
380
|
+
schemaVersion: 1;
|
|
381
|
+
runId?: string;
|
|
382
|
+
applyReportPath?: string;
|
|
383
|
+
validationTarget?: string;
|
|
384
|
+
workflow: string;
|
|
385
|
+
mode: "dry-run" | "apply";
|
|
386
|
+
status: "passed" | "failed";
|
|
387
|
+
summary: {
|
|
388
|
+
sourceFilesChanged: PrimitiveChangedFile[];
|
|
389
|
+
generatedFilesSynced: PrimitiveGeneratedFile[];
|
|
390
|
+
};
|
|
391
|
+
changedFiles: PrimitiveChangedFile[];
|
|
392
|
+
generatedFiles: PrimitiveGeneratedFile[];
|
|
393
|
+
appliedCommands: WorkflowApplyCommand[];
|
|
394
|
+
recommendedValidationCommands: WorkflowApplyCommand[];
|
|
395
|
+
commands: WorkflowApplyCommand[];
|
|
396
|
+
diagnostics: WorkflowDiagnostic[];
|
|
397
|
+
postApplyChecks?: WorkflowPostApplyCheck[];
|
|
398
|
+
recommendations: WorkflowRecommendation[];
|
|
399
|
+
nextActions: PrimitiveNextAction[];
|
|
400
|
+
plan: WorkflowPlan;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export interface WorkflowValidationRunReport {
|
|
404
|
+
schemaVersion: 1;
|
|
405
|
+
runId: string;
|
|
406
|
+
workflow: string;
|
|
407
|
+
mode: "validate";
|
|
408
|
+
source: WorkflowRunSource;
|
|
409
|
+
status: "passed" | "failed";
|
|
410
|
+
sourceStatus: WorkflowValidationStatus;
|
|
411
|
+
workspaceStatus: WorkflowValidationStatus;
|
|
412
|
+
validationCommandsStatus: WorkflowValidationStatus;
|
|
413
|
+
baselineStatus: WorkflowValidationStatus;
|
|
414
|
+
summary: WorkflowValidationSummary;
|
|
415
|
+
overallStatus: WorkflowOverallStatus;
|
|
416
|
+
knownBlockers: WorkflowKnownBlocker[];
|
|
417
|
+
commands: WorkflowValidationCommandResult[];
|
|
418
|
+
diagnostics: WorkflowDiagnostic[];
|
|
419
|
+
baselineSummary: WorkflowBaselineSummary;
|
|
420
|
+
baselineDiagnostics?: WorkflowDiagnostic[];
|
|
421
|
+
workflowDiagnostics?: WorkflowDiagnostic[];
|
|
422
|
+
repairActions: RepairAction[];
|
|
423
|
+
nextActions: PrimitiveNextAction[];
|
|
424
|
+
plan?: WorkflowPlan;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export interface RepairReport {
|
|
428
|
+
schemaVersion: 1;
|
|
429
|
+
runId?: string;
|
|
430
|
+
repairReportPath?: string;
|
|
431
|
+
command: string;
|
|
432
|
+
kind: RepairAction["kind"];
|
|
433
|
+
target: string | null;
|
|
434
|
+
status: "passed" | "failed";
|
|
435
|
+
diagnostics: WorkflowDiagnostic[];
|
|
436
|
+
repairActions: RepairAction[];
|
|
437
|
+
nextActions: PrimitiveNextAction[];
|
|
438
|
+
commands: WorkflowValidationCommandResult[];
|
|
439
|
+
generatedFiles?: PrimitiveGeneratedFile[];
|
|
440
|
+
syncedAt?: string;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export interface GeneratedSyncState {
|
|
444
|
+
schemaVersion: 1;
|
|
445
|
+
target: string;
|
|
446
|
+
status: "passed" | "failed";
|
|
447
|
+
syncedAt: string;
|
|
448
|
+
command: string;
|
|
449
|
+
runId?: string;
|
|
450
|
+
generatedFiles: PrimitiveGeneratedFile[];
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
export type WorkflowRunArtifact = WorkflowApplyReport | WorkflowValidationRunReport | RepairReport;
|
|
454
|
+
|
|
455
|
+
export interface WorkflowStepResult {
|
|
456
|
+
changedFiles?: PrimitiveChangedFile[];
|
|
457
|
+
generatedFiles?: PrimitiveGeneratedFile[];
|
|
458
|
+
commands?: WorkflowApplyCommand[];
|
|
459
|
+
diagnostics?: WorkflowDiagnostic[];
|
|
460
|
+
postApplyChecks?: WorkflowPostApplyCheck[];
|
|
461
|
+
recommendations?: WorkflowRecommendation[];
|
|
462
|
+
nextActions?: PrimitiveNextAction[];
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export type WorkflowStepRunner = (step: WorkflowStep, plan: WorkflowPlan) => Promise<WorkflowStepResult | undefined>;
|
|
466
|
+
export type WorkflowStepRegistry = Record<string, WorkflowStepRunner>;
|
|
467
|
+
|
|
468
|
+
export interface WorkflowPrimitiveOperations {
|
|
469
|
+
workspace: Workspace;
|
|
470
|
+
createModule: (sys: Sys, module: string) => Promise<PrimitiveWriteReport>;
|
|
471
|
+
createScalar: (sys: Sys, scalar: string) => Promise<PrimitiveWriteReport>;
|
|
472
|
+
createUi: (input: PrimitiveTargetInput & { surface: UiSurface }) => Promise<PrimitiveWriteReport>;
|
|
473
|
+
addField: (input: AddFieldInput) => Promise<PrimitiveWriteReport>;
|
|
474
|
+
addEnumField: (input: AddEnumFieldInput) => Promise<PrimitiveWriteReport>;
|
|
475
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { normalizeFieldType } from "./source";
|
|
2
|
+
|
|
3
|
+
export type AddFieldUiComponent = "Field.Text" | "Field.Number" | "Field.Date" | "Field.ToggleSelect";
|
|
4
|
+
|
|
5
|
+
export const addFieldUiPolicyForType = (typeName: string) => {
|
|
6
|
+
const normalizedType = typeName.toLowerCase() === "enum" ? "enum" : normalizeFieldType(typeName);
|
|
7
|
+
if (normalizedType === "Int" || normalizedType === "Float") {
|
|
8
|
+
return {
|
|
9
|
+
normalizedType,
|
|
10
|
+
component: "Field.Number" as const,
|
|
11
|
+
confidence: "high" as const,
|
|
12
|
+
autoTemplateSupported: true,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
if (normalizedType === "Date") {
|
|
16
|
+
return {
|
|
17
|
+
normalizedType,
|
|
18
|
+
component: "Field.Date" as const,
|
|
19
|
+
confidence: "high" as const,
|
|
20
|
+
autoTemplateSupported: true,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
if (normalizedType === "Boolean" || normalizedType === "enum") {
|
|
24
|
+
return {
|
|
25
|
+
normalizedType,
|
|
26
|
+
component: "Field.ToggleSelect" as const,
|
|
27
|
+
confidence: "medium" as const,
|
|
28
|
+
autoTemplateSupported: false,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (normalizedType === "String") {
|
|
32
|
+
return {
|
|
33
|
+
normalizedType,
|
|
34
|
+
component: "Field.Text" as const,
|
|
35
|
+
confidence: "high" as const,
|
|
36
|
+
autoTemplateSupported: true,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
normalizedType,
|
|
41
|
+
component: "Field.Text" as const,
|
|
42
|
+
confidence: "low" as const,
|
|
43
|
+
autoTemplateSupported: false,
|
|
44
|
+
};
|
|
45
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { WorkflowDiagnostic, WorkflowValidationCommandResult } from "./types";
|
|
2
|
+
|
|
3
|
+
export const jsonText = (value: unknown, { trailingNewline = true }: { trailingNewline?: boolean } = {}) =>
|
|
4
|
+
`${JSON.stringify(value, null, 2)}${trailingNewline ? "\n" : ""}`;
|
|
5
|
+
|
|
6
|
+
export const workflowStatus = (diagnostics: readonly WorkflowDiagnostic[]) =>
|
|
7
|
+
diagnostics.some((diagnostic) => diagnostic.severity === "error") ? "failed" : "passed";
|
|
8
|
+
|
|
9
|
+
export const commandStatus = (commands: readonly WorkflowValidationCommandResult[]) =>
|
|
10
|
+
commands.some((command) => command.status === "failed") ? "failed" : "passed";
|
|
11
|
+
|
|
12
|
+
export const uniqueBy = <T>(values: readonly T[], key: (value: T) => string) => {
|
|
13
|
+
const seen = new Set<string>();
|
|
14
|
+
return values.filter((value) => {
|
|
15
|
+
const itemKey = key(value);
|
|
16
|
+
if (seen.has(itemKey)) return false;
|
|
17
|
+
seen.add(itemKey);
|
|
18
|
+
return true;
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const compactDiagnostics = (diagnostics: Array<WorkflowDiagnostic | false | null | undefined>) =>
|
|
23
|
+
diagnostics.filter((diagnostic): diagnostic is WorkflowDiagnostic => !!diagnostic);
|