@interf/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.
- package/README.md +71 -69
- package/builtin-workflows/interf/README.md +6 -6
- package/builtin-workflows/interf/compile/stages/shape/SKILL.md +7 -7
- package/builtin-workflows/interf/compile/stages/structure/SKILL.md +2 -2
- package/builtin-workflows/interf/compile/stages/summarize/SKILL.md +1 -1
- package/builtin-workflows/interf/{workspace.schema.json → compiled.schema.json} +5 -5
- package/builtin-workflows/interf/improve/SKILL.md +3 -3
- package/builtin-workflows/interf/use/query/SKILL.md +2 -2
- package/builtin-workflows/interf/workflow.json +42 -31
- package/dist/commands/check-draft.d.ts +19 -0
- package/dist/commands/check-draft.js +110 -0
- package/dist/commands/compile-controller.d.ts +4 -4
- package/dist/commands/compile-controller.js +117 -81
- package/dist/commands/compile.d.ts +5 -5
- package/dist/commands/compile.js +61 -62
- package/dist/commands/compiled-flow.d.ts +23 -0
- package/dist/commands/compiled-flow.js +112 -0
- package/dist/commands/create-workflow-wizard.d.ts +3 -3
- package/dist/commands/create-workflow-wizard.js +11 -11
- package/dist/commands/create.d.ts +2 -2
- package/dist/commands/create.js +50 -57
- package/dist/commands/default.js +2 -2
- package/dist/commands/executor-flow.d.ts +20 -1
- package/dist/commands/executor-flow.js +67 -7
- package/dist/commands/init.js +242 -289
- package/dist/commands/list.js +14 -10
- package/dist/commands/reset.js +6 -6
- package/dist/commands/source-config-wizard.d.ts +12 -8
- package/dist/commands/source-config-wizard.js +356 -119
- package/dist/commands/status.js +49 -26
- package/dist/commands/test-flow.d.ts +23 -10
- package/dist/commands/test-flow.js +278 -58
- package/dist/commands/test.d.ts +7 -1
- package/dist/commands/test.js +264 -65
- package/dist/commands/verify.js +23 -14
- package/dist/index.d.ts +7 -7
- package/dist/index.js +4 -4
- package/dist/lib/agent-args.js +2 -1
- package/dist/lib/agent-constants.js +1 -1
- package/dist/lib/agent-render.js +4 -4
- package/dist/lib/agent-shells.d.ts +8 -8
- package/dist/lib/agent-shells.js +231 -142
- package/dist/lib/compiled-compile.d.ts +52 -0
- package/dist/lib/compiled-compile.js +274 -0
- package/dist/lib/compiled-home.d.ts +5 -0
- package/dist/lib/compiled-home.js +32 -0
- package/dist/lib/compiled-layout.d.ts +2 -0
- package/dist/lib/compiled-layout.js +60 -0
- package/dist/lib/compiled-paths.d.ts +41 -0
- package/dist/lib/compiled-paths.js +111 -0
- package/dist/lib/{workspace-raw.d.ts → compiled-raw.d.ts} +8 -7
- package/dist/lib/{workspace-raw.js → compiled-raw.js} +16 -14
- package/dist/lib/compiled-reset.d.ts +1 -0
- package/dist/lib/compiled-reset.js +44 -0
- package/dist/lib/compiled-schema.d.ts +27 -0
- package/dist/lib/compiled-schema.js +110 -0
- package/dist/lib/config.d.ts +0 -1
- package/dist/lib/config.js +0 -1
- package/dist/lib/discovery.d.ts +1 -1
- package/dist/lib/discovery.js +3 -3
- package/dist/lib/interf-bootstrap.d.ts +1 -1
- package/dist/lib/interf-bootstrap.js +4 -4
- package/dist/lib/interf-detect.d.ts +10 -10
- package/dist/lib/interf-detect.js +78 -56
- package/dist/lib/interf-scaffold.d.ts +2 -2
- package/dist/lib/interf-scaffold.js +90 -57
- package/dist/lib/interf-workflow-package.d.ts +3 -3
- package/dist/lib/interf-workflow-package.js +30 -30
- package/dist/lib/interf.d.ts +5 -5
- package/dist/lib/interf.js +4 -4
- package/dist/lib/local-workflows.d.ts +4 -4
- package/dist/lib/local-workflows.js +35 -70
- package/dist/lib/obsidian.d.ts +1 -1
- package/dist/lib/parse.js +92 -1
- package/dist/lib/project-paths.d.ts +13 -0
- package/dist/lib/project-paths.js +29 -0
- package/dist/lib/runtime-acceptance.d.ts +7 -1
- package/dist/lib/runtime-acceptance.js +194 -59
- package/dist/lib/runtime-contracts.d.ts +2 -4
- package/dist/lib/runtime-contracts.js +17 -161
- package/dist/lib/runtime-inventory.d.ts +7 -0
- package/dist/lib/runtime-inventory.js +29 -0
- package/dist/lib/runtime-paths.js +5 -5
- package/dist/lib/runtime-prompt.js +9 -6
- package/dist/lib/runtime-reconcile.d.ts +2 -3
- package/dist/lib/runtime-reconcile.js +92 -171
- package/dist/lib/runtime-runs.js +30 -39
- package/dist/lib/runtime-types.d.ts +10 -19
- package/dist/lib/runtime.d.ts +2 -2
- package/dist/lib/runtime.js +1 -1
- package/dist/lib/schema.d.ts +163 -140
- package/dist/lib/schema.js +163 -124
- package/dist/lib/source-config.d.ts +24 -20
- package/dist/lib/source-config.js +154 -116
- package/dist/lib/state-artifacts.d.ts +5 -5
- package/dist/lib/state-artifacts.js +8 -8
- package/dist/lib/state-health.d.ts +4 -4
- package/dist/lib/state-health.js +108 -126
- package/dist/lib/state-io.d.ts +8 -8
- package/dist/lib/state-io.js +77 -50
- package/dist/lib/state-paths.js +5 -5
- package/dist/lib/state-view.d.ts +4 -4
- package/dist/lib/state-view.js +52 -55
- package/dist/lib/state.d.ts +5 -5
- package/dist/lib/state.js +4 -4
- package/dist/lib/summarize-plan.d.ts +3 -2
- package/dist/lib/summarize-plan.js +18 -16
- package/dist/lib/test-execution.js +9 -9
- package/dist/lib/test-matrices.d.ts +3 -3
- package/dist/lib/test-matrices.js +6 -6
- package/dist/lib/test-paths.d.ts +4 -4
- package/dist/lib/test-paths.js +16 -10
- package/dist/lib/test-sandbox.d.ts +1 -1
- package/dist/lib/test-sandbox.js +38 -31
- package/dist/lib/test-targets.d.ts +2 -2
- package/dist/lib/test-targets.js +11 -11
- package/dist/lib/test-types.d.ts +1 -1
- package/dist/lib/test.d.ts +1 -1
- package/dist/lib/test.js +1 -1
- package/dist/lib/util.d.ts +2 -0
- package/dist/lib/util.js +14 -1
- package/dist/lib/validate-compiled.d.ts +27 -0
- package/dist/lib/validate-compiled.js +236 -0
- package/dist/lib/validate-helpers.d.ts +0 -8
- package/dist/lib/validate-helpers.js +0 -30
- package/dist/lib/validate.d.ts +4 -4
- package/dist/lib/validate.js +49 -15
- package/dist/lib/workflow-abi.d.ts +37 -46
- package/dist/lib/workflow-abi.js +51 -76
- package/dist/lib/workflow-definitions.d.ts +11 -11
- package/dist/lib/workflow-definitions.js +36 -53
- package/dist/lib/workflow-helpers.d.ts +2 -3
- package/dist/lib/workflow-helpers.js +9 -13
- package/dist/lib/workflow-improvement.d.ts +3 -3
- package/dist/lib/workflow-improvement.js +48 -48
- package/dist/lib/workflow-review-paths.d.ts +3 -3
- package/dist/lib/workflow-review-paths.js +11 -11
- package/dist/lib/workflow-stage-runner.d.ts +1 -1
- package/dist/lib/workflow-stage-runner.js +8 -8
- package/dist/lib/workflows.d.ts +9 -9
- package/dist/lib/workflows.js +15 -17
- package/package.json +10 -9
- package/dist/commands/workspace-flow.d.ts +0 -23
- package/dist/commands/workspace-flow.js +0 -109
- package/dist/lib/registry.d.ts +0 -16
- package/dist/lib/registry.js +0 -65
- package/dist/lib/validate-workspace.d.ts +0 -121
- package/dist/lib/validate-workspace.js +0 -407
- package/dist/lib/workspace-compile.d.ts +0 -54
- package/dist/lib/workspace-compile.js +0 -476
- package/dist/lib/workspace-home.d.ts +0 -5
- package/dist/lib/workspace-home.js +0 -32
- package/dist/lib/workspace-layout.d.ts +0 -2
- package/dist/lib/workspace-layout.js +0 -60
- package/dist/lib/workspace-paths.d.ts +0 -41
- package/dist/lib/workspace-paths.js +0 -107
- package/dist/lib/workspace-reset.d.ts +0 -1
- package/dist/lib/workspace-reset.js +0 -43
- package/dist/lib/workspace-schema.d.ts +0 -17
- package/dist/lib/workspace-schema.js +0 -74
|
@@ -1,12 +1,84 @@
|
|
|
1
|
+
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
1
3
|
import * as p from "@clack/prompts";
|
|
2
|
-
import {
|
|
4
|
+
import { compiledMaxAttempts, compiledMaxLoops, resolveSourceDatasetPath, } from "../lib/source-config.js";
|
|
3
5
|
import { slugify } from "../lib/util.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export const
|
|
7
|
-
export const
|
|
6
|
+
import { resolveOrConfigureLocalExecutor } from "./executor-flow.js";
|
|
7
|
+
import { draftTruthChecks } from "./check-draft.js";
|
|
8
|
+
export const DEFAULT_COMPILED_NAME = "dataset1";
|
|
9
|
+
export const DEFAULT_COMPILED_CHECK_QUESTION_PLACEHOLDER = "A question you can already verify from this dataset";
|
|
10
|
+
export const DEFAULT_COMPILED_CHECK_ANSWER_PLACEHOLDER = "The expected answer in plain English";
|
|
11
|
+
export const DEFAULT_COMPILED_ABOUT_PLACEHOLDER = "Example: forward-demand metrics, board-prep questions, or chart reads from this dataset.";
|
|
12
|
+
export const DEFAULT_DATASET_PATH_PLACEHOLDER = "./dataset1";
|
|
8
13
|
export const DEFAULT_COMPILE_RETRY_ATTEMPTS = 1;
|
|
9
14
|
export const DEFAULT_SELF_IMPROVING_LOOPS = 3;
|
|
15
|
+
function normalizeOptionalPromptText(value) {
|
|
16
|
+
if (typeof value !== "string")
|
|
17
|
+
return undefined;
|
|
18
|
+
const normalized = value.trim();
|
|
19
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
20
|
+
}
|
|
21
|
+
function findSingleDatasetFolderCandidate(cwd) {
|
|
22
|
+
const ignoredEntries = new Set([
|
|
23
|
+
".DS_Store",
|
|
24
|
+
".git",
|
|
25
|
+
".interf",
|
|
26
|
+
"interf",
|
|
27
|
+
"interf.json",
|
|
28
|
+
"node_modules",
|
|
29
|
+
]);
|
|
30
|
+
let rootEntries = [];
|
|
31
|
+
try {
|
|
32
|
+
rootEntries = readdirSync(cwd);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const visibleEntries = rootEntries.filter((entry) => !ignoredEntries.has(entry));
|
|
38
|
+
const visibleFiles = [];
|
|
39
|
+
const visibleDirectories = [];
|
|
40
|
+
for (const entry of visibleEntries) {
|
|
41
|
+
try {
|
|
42
|
+
const entryPath = join(cwd, entry);
|
|
43
|
+
if (statSync(entryPath).isDirectory()) {
|
|
44
|
+
visibleDirectories.push(entry);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
visibleFiles.push(entry);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// ignore unreadable entries
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (visibleFiles.length > 0 || visibleDirectories.length !== 1) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
return `./${visibleDirectories[0]}`;
|
|
58
|
+
}
|
|
59
|
+
export function defaultDatasetPathForPrompt(name, introStyle, cwd = process.cwd()) {
|
|
60
|
+
const namedFolderPath = join(cwd, name);
|
|
61
|
+
if (existsSync(namedFolderPath)) {
|
|
62
|
+
try {
|
|
63
|
+
if (statSync(namedFolderPath).isDirectory()) {
|
|
64
|
+
return `./${name}`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// fall through
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (introStyle === "first") {
|
|
72
|
+
return findSingleDatasetFolderCandidate(cwd) ?? ".";
|
|
73
|
+
}
|
|
74
|
+
return `./${name}`;
|
|
75
|
+
}
|
|
76
|
+
export function datasetAboutPromptMessage(introStyle) {
|
|
77
|
+
if (introStyle === "edit") {
|
|
78
|
+
return "What should this dataset stay accurate about?";
|
|
79
|
+
}
|
|
80
|
+
return "What should this dataset be accurate about?";
|
|
81
|
+
}
|
|
10
82
|
function formatAttemptLabel(count, noun) {
|
|
11
83
|
return `${count} ${noun}${count === 1 ? "" : "s"}`;
|
|
12
84
|
}
|
|
@@ -20,14 +92,13 @@ export function resolveCompileLoopMode(maxAttempts, maxLoops) {
|
|
|
20
92
|
export function describeCompileLoopSelection(options) {
|
|
21
93
|
const mode = resolveCompileLoopMode(options.maxAttempts, options.maxLoops);
|
|
22
94
|
if (mode === "once") {
|
|
23
|
-
return "
|
|
95
|
+
return "Compile once.";
|
|
24
96
|
}
|
|
25
97
|
if (mode === "retry") {
|
|
26
|
-
return
|
|
98
|
+
return "Compile retries are enabled for this dataset.";
|
|
27
99
|
}
|
|
28
|
-
const attempts = options.maxAttempts ?? DEFAULT_COMPILE_RETRY_ATTEMPTS;
|
|
29
100
|
const loops = options.maxLoops ?? DEFAULT_SELF_IMPROVING_LOOPS;
|
|
30
|
-
return `
|
|
101
|
+
return `Self-improving loops are enabled for this dataset (${formatAttemptLabel(loops, "workflow revision")}).`;
|
|
31
102
|
}
|
|
32
103
|
export async function promptCheckCases(options) {
|
|
33
104
|
p.log.info(options.heading);
|
|
@@ -66,33 +137,189 @@ export async function promptCheckCases(options) {
|
|
|
66
137
|
return cases;
|
|
67
138
|
}
|
|
68
139
|
}
|
|
69
|
-
|
|
140
|
+
function printDraftTruthChecks(checks) {
|
|
141
|
+
console.log();
|
|
142
|
+
p.log.info(`Draft truth checks: ${checks.length}`);
|
|
143
|
+
for (const [index, check] of checks.entries()) {
|
|
144
|
+
console.log(` ${index + 1}. ${check.question}`);
|
|
145
|
+
console.log(` Expected: ${check.answer ?? ""}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async function promptDraftTruthChecks(options) {
|
|
149
|
+
let resolvedDatasetPath;
|
|
150
|
+
try {
|
|
151
|
+
const datasetConfig = {
|
|
152
|
+
path: options.datasetPath,
|
|
153
|
+
};
|
|
154
|
+
resolvedDatasetPath = resolveSourceDatasetPath(options.projectPath, datasetConfig);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
p.log.error(error instanceof Error ? error.message : String(error));
|
|
158
|
+
return "manual";
|
|
159
|
+
}
|
|
160
|
+
const resolved = await resolveOrConfigureLocalExecutor({
|
|
161
|
+
preflight: true,
|
|
162
|
+
purpose: "draft",
|
|
163
|
+
});
|
|
164
|
+
if (!resolved.executor) {
|
|
165
|
+
if (resolved.cancelled)
|
|
166
|
+
return null;
|
|
167
|
+
p.log.error(resolved.error ?? "No local agent detected for truth-check drafting.");
|
|
168
|
+
const fallback = await p.select({
|
|
169
|
+
message: "How do you want to continue?",
|
|
170
|
+
options: [
|
|
171
|
+
{
|
|
172
|
+
value: "manual",
|
|
173
|
+
label: "Add truth checks manually",
|
|
174
|
+
hint: "Write the questions and expected answers yourself",
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
value: "skip",
|
|
178
|
+
label: "Skip for now",
|
|
179
|
+
hint: "Save this dataset without truth checks",
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
});
|
|
183
|
+
if (p.isCancel(fallback))
|
|
184
|
+
return null;
|
|
185
|
+
return fallback === "manual" ? "manual" : [];
|
|
186
|
+
}
|
|
187
|
+
while (true) {
|
|
188
|
+
p.log.info("Drafting truth checks from the dataset files.");
|
|
189
|
+
const drafted = await draftTruthChecks({
|
|
190
|
+
datasetName: options.datasetName,
|
|
191
|
+
datasetPath: resolvedDatasetPath,
|
|
192
|
+
about: options.about,
|
|
193
|
+
executor: resolved.executor,
|
|
194
|
+
targetCount: 4,
|
|
195
|
+
});
|
|
196
|
+
if (!drafted.checks) {
|
|
197
|
+
p.log.error(drafted.error ?? "Could not draft truth checks from this dataset.");
|
|
198
|
+
const retryMode = await p.select({
|
|
199
|
+
message: "How do you want to continue?",
|
|
200
|
+
options: [
|
|
201
|
+
{
|
|
202
|
+
value: "retry",
|
|
203
|
+
label: "Try auto-create again",
|
|
204
|
+
hint: "Run the same local agent again on the dataset folder",
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
value: "manual",
|
|
208
|
+
label: "Add truth checks manually",
|
|
209
|
+
hint: "Write the checks yourself instead",
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
value: "skip",
|
|
213
|
+
label: "Skip for now",
|
|
214
|
+
hint: "Save this dataset without truth checks",
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
});
|
|
218
|
+
if (p.isCancel(retryMode))
|
|
219
|
+
return null;
|
|
220
|
+
if (retryMode === "retry")
|
|
221
|
+
continue;
|
|
222
|
+
return retryMode === "manual" ? "manual" : [];
|
|
223
|
+
}
|
|
224
|
+
printDraftTruthChecks(drafted.checks);
|
|
225
|
+
const nextStep = await p.select({
|
|
226
|
+
message: "Use these truth checks?",
|
|
227
|
+
options: [
|
|
228
|
+
{
|
|
229
|
+
value: "use",
|
|
230
|
+
label: "Use this draft (Recommended)",
|
|
231
|
+
hint: "Save these checks and edit them later if needed",
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
value: "retry",
|
|
235
|
+
label: "Draft again",
|
|
236
|
+
hint: "Run the same local agent again on the dataset folder",
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
value: "manual",
|
|
240
|
+
label: "Add them manually instead",
|
|
241
|
+
hint: "Discard this draft and write the checks yourself",
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
value: "skip",
|
|
245
|
+
label: "Skip for now",
|
|
246
|
+
hint: "Save this dataset without truth checks",
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
});
|
|
250
|
+
if (p.isCancel(nextStep))
|
|
251
|
+
return null;
|
|
252
|
+
if (nextStep === "retry")
|
|
253
|
+
continue;
|
|
254
|
+
if (nextStep === "manual")
|
|
255
|
+
return "manual";
|
|
256
|
+
if (nextStep === "skip")
|
|
257
|
+
return [];
|
|
258
|
+
return drafted.checks;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
async function promptCompiledChecks(options) {
|
|
70
262
|
if (!options.initialChecks?.length) {
|
|
71
263
|
if (options.initialAbout) {
|
|
72
|
-
p.log.info(`
|
|
264
|
+
p.log.info(`About: ${options.initialAbout}`);
|
|
73
265
|
}
|
|
74
|
-
p.log.info("Truth checks
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
266
|
+
p.log.info("Truth checks are the questions this dataset should already answer correctly.");
|
|
267
|
+
const mode = await p.select({
|
|
268
|
+
message: "How do you want to create them?",
|
|
269
|
+
options: [
|
|
270
|
+
{
|
|
271
|
+
value: "draft",
|
|
272
|
+
label: "Auto-create a draft (Recommended)",
|
|
273
|
+
hint: "Let a local agent draft a few clear, verifiable checks from this dataset",
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
value: "manual",
|
|
277
|
+
label: "Add them manually",
|
|
278
|
+
hint: "Write the questions and expected answers yourself",
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
value: "skip",
|
|
282
|
+
label: "Skip for now",
|
|
283
|
+
hint: "You can save the dataset first and add checks later",
|
|
284
|
+
},
|
|
285
|
+
],
|
|
80
286
|
});
|
|
81
|
-
if (p.isCancel(
|
|
287
|
+
if (p.isCancel(mode))
|
|
82
288
|
return null;
|
|
83
|
-
if (
|
|
289
|
+
if (mode === "skip")
|
|
84
290
|
return [];
|
|
291
|
+
if (mode === "draft") {
|
|
292
|
+
const drafted = await promptDraftTruthChecks({
|
|
293
|
+
projectPath: options.projectPath,
|
|
294
|
+
datasetName: options.datasetName,
|
|
295
|
+
datasetPath: options.datasetPath,
|
|
296
|
+
about: options.initialAbout,
|
|
297
|
+
});
|
|
298
|
+
if (drafted === null)
|
|
299
|
+
return null;
|
|
300
|
+
if (drafted === "manual") {
|
|
301
|
+
return promptCheckCases({
|
|
302
|
+
heading: "Truth checks",
|
|
303
|
+
questionMessage: "Question 1?",
|
|
304
|
+
questionPlaceholder: DEFAULT_COMPILED_CHECK_QUESTION_PLACEHOLDER,
|
|
305
|
+
answerMessage: "Expected answer 1?",
|
|
306
|
+
answerPlaceholder: DEFAULT_COMPILED_CHECK_ANSWER_PLACEHOLDER,
|
|
307
|
+
addAnotherMessage: "Add another question?",
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
return drafted;
|
|
311
|
+
}
|
|
85
312
|
return promptCheckCases({
|
|
86
313
|
heading: "Truth checks",
|
|
87
314
|
questionMessage: "Question 1?",
|
|
88
|
-
questionPlaceholder:
|
|
315
|
+
questionPlaceholder: DEFAULT_COMPILED_CHECK_QUESTION_PLACEHOLDER,
|
|
89
316
|
answerMessage: "Expected answer 1?",
|
|
90
|
-
answerPlaceholder:
|
|
317
|
+
answerPlaceholder: DEFAULT_COMPILED_CHECK_ANSWER_PLACEHOLDER,
|
|
91
318
|
addAnotherMessage: "Add another question?",
|
|
92
319
|
});
|
|
93
320
|
}
|
|
94
321
|
if (options.initialAbout) {
|
|
95
|
-
p.log.info(`
|
|
322
|
+
p.log.info(`About: ${options.initialAbout}`);
|
|
96
323
|
}
|
|
97
324
|
p.log.info(`Current truth checks: ${options.initialChecks.length}`);
|
|
98
325
|
const mode = await p.select({
|
|
@@ -113,10 +340,15 @@ async function promptWorkspaceChecks(options) {
|
|
|
113
340
|
label: "Replace all",
|
|
114
341
|
hint: "Rewrite the truth checks from scratch",
|
|
115
342
|
},
|
|
343
|
+
{
|
|
344
|
+
value: "redraft",
|
|
345
|
+
label: "Replace with auto-created draft",
|
|
346
|
+
hint: "Let a local agent rewrite the checks from the dataset files",
|
|
347
|
+
},
|
|
116
348
|
{
|
|
117
349
|
value: "clear",
|
|
118
350
|
label: "Clear them for now",
|
|
119
|
-
hint: "Keep this
|
|
351
|
+
hint: "Keep this dataset without saved truth checks",
|
|
120
352
|
},
|
|
121
353
|
],
|
|
122
354
|
});
|
|
@@ -128,16 +360,37 @@ async function promptWorkspaceChecks(options) {
|
|
|
128
360
|
if (mode === "clear") {
|
|
129
361
|
return [];
|
|
130
362
|
}
|
|
363
|
+
if (mode === "redraft") {
|
|
364
|
+
const drafted = await promptDraftTruthChecks({
|
|
365
|
+
projectPath: options.projectPath,
|
|
366
|
+
datasetName: options.datasetName,
|
|
367
|
+
datasetPath: options.datasetPath,
|
|
368
|
+
about: options.initialAbout,
|
|
369
|
+
});
|
|
370
|
+
if (drafted === null)
|
|
371
|
+
return null;
|
|
372
|
+
if (drafted === "manual") {
|
|
373
|
+
return promptCheckCases({
|
|
374
|
+
heading: "Replace truth checks",
|
|
375
|
+
questionMessage: "Question 1?",
|
|
376
|
+
questionPlaceholder: DEFAULT_COMPILED_CHECK_QUESTION_PLACEHOLDER,
|
|
377
|
+
answerMessage: "Expected answer 1?",
|
|
378
|
+
answerPlaceholder: DEFAULT_COMPILED_CHECK_ANSWER_PLACEHOLDER,
|
|
379
|
+
addAnotherMessage: "Add another question?",
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
return drafted;
|
|
383
|
+
}
|
|
131
384
|
const nextChecks = await promptCheckCases({
|
|
132
385
|
heading: mode === "add" ? "Add more truth checks" : "Replace truth checks",
|
|
133
386
|
questionMessage: mode === "add"
|
|
134
387
|
? `Question ${options.initialChecks.length + 1}?`
|
|
135
388
|
: "Question 1?",
|
|
136
|
-
questionPlaceholder:
|
|
389
|
+
questionPlaceholder: DEFAULT_COMPILED_CHECK_QUESTION_PLACEHOLDER,
|
|
137
390
|
answerMessage: mode === "add"
|
|
138
391
|
? `Expected answer ${options.initialChecks.length + 1}?`
|
|
139
392
|
: "Expected answer 1?",
|
|
140
|
-
answerPlaceholder:
|
|
393
|
+
answerPlaceholder: DEFAULT_COMPILED_CHECK_ANSWER_PLACEHOLDER,
|
|
141
394
|
addAnotherMessage: "Add another question?",
|
|
142
395
|
startIndex: mode === "add" ? options.initialChecks.length + 1 : 1,
|
|
143
396
|
});
|
|
@@ -145,24 +398,6 @@ async function promptWorkspaceChecks(options) {
|
|
|
145
398
|
return null;
|
|
146
399
|
return mode === "add" ? [...options.initialChecks, ...nextChecks] : nextChecks;
|
|
147
400
|
}
|
|
148
|
-
async function promptRetryAttempts(options) {
|
|
149
|
-
const minimum = options.minimum ?? 1;
|
|
150
|
-
const maxAttempts = await p.text({
|
|
151
|
-
message: options.message,
|
|
152
|
-
placeholder: String(Math.max(minimum, DEFAULT_COMPILE_RETRY_ATTEMPTS)),
|
|
153
|
-
initialValue: String(Math.max(options.initialMaxAttempts ?? DEFAULT_COMPILE_RETRY_ATTEMPTS, minimum)),
|
|
154
|
-
validate: (value) => {
|
|
155
|
-
const parsed = Number.parseInt(value.trim(), 10);
|
|
156
|
-
if (!Number.isInteger(parsed) || parsed < minimum || parsed > 5) {
|
|
157
|
-
return `Enter a whole number from ${minimum} to 5`;
|
|
158
|
-
}
|
|
159
|
-
return undefined;
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
if (p.isCancel(maxAttempts))
|
|
163
|
-
return null;
|
|
164
|
-
return workspaceMaxAttempts(Number.parseInt(String(maxAttempts).trim(), 10)) ?? DEFAULT_COMPILE_RETRY_ATTEMPTS;
|
|
165
|
-
}
|
|
166
401
|
async function promptSelfImprovingLoops(options) {
|
|
167
402
|
const maxLoops = await p.text({
|
|
168
403
|
message: options.message,
|
|
@@ -178,13 +413,14 @@ async function promptSelfImprovingLoops(options) {
|
|
|
178
413
|
});
|
|
179
414
|
if (p.isCancel(maxLoops))
|
|
180
415
|
return null;
|
|
181
|
-
return
|
|
416
|
+
return compiledMaxLoops(Number.parseInt(String(maxLoops).trim(), 10)) ?? DEFAULT_SELF_IMPROVING_LOOPS;
|
|
182
417
|
}
|
|
183
418
|
export async function promptCompileLoopSelection(options) {
|
|
184
419
|
if (!options.hasChecks) {
|
|
185
420
|
return {};
|
|
186
421
|
}
|
|
187
422
|
const currentMode = resolveCompileLoopMode(options.initialMaxAttempts, options.initialMaxLoops);
|
|
423
|
+
const currentPromptMode = currentMode === "self-improving" ? "self-improving" : "once";
|
|
188
424
|
const recommendedMode = options.recommendedMode ?? "self-improving";
|
|
189
425
|
const includeCompileOnce = options.includeCompileOnce !== false;
|
|
190
426
|
const hasSavedPolicy = typeof options.initialMaxAttempts === "number" ||
|
|
@@ -199,37 +435,35 @@ export async function promptCompileLoopSelection(options) {
|
|
|
199
435
|
const optionsByMode = {
|
|
200
436
|
once: {
|
|
201
437
|
value: "once",
|
|
202
|
-
label: "
|
|
203
|
-
hint: "
|
|
204
|
-
},
|
|
205
|
-
retry: {
|
|
206
|
-
value: "retry",
|
|
207
|
-
label: "Retry the same workflow",
|
|
208
|
-
hint: `Run compile + test up to ${formatAttemptLabel(Math.max(options.initialMaxAttempts ?? 2, 2), "attempt")}`,
|
|
438
|
+
label: "Compile once",
|
|
439
|
+
hint: "Build the compiled dataset once with the selected workflow",
|
|
209
440
|
},
|
|
210
441
|
"self-improving": {
|
|
211
442
|
value: "self-improving",
|
|
212
443
|
label: recommendedMode === "self-improving"
|
|
213
444
|
? "Self-improving loops (Recommended)"
|
|
214
445
|
: "Self-improving loops",
|
|
215
|
-
hint: `
|
|
446
|
+
hint: `Let Interf revise the workflow and retry up to ${options.initialMaxLoops ?? DEFAULT_SELF_IMPROVING_LOOPS} time${(options.initialMaxLoops ?? DEFAULT_SELF_IMPROVING_LOOPS) === 1 ? "" : "s"}`,
|
|
447
|
+
},
|
|
448
|
+
retry: {
|
|
449
|
+
value: "retry",
|
|
450
|
+
label: "Compile once",
|
|
451
|
+
hint: "Build the compiled dataset once with the selected workflow",
|
|
216
452
|
},
|
|
217
453
|
};
|
|
218
454
|
const orderedModes = (hasSavedPolicy
|
|
219
455
|
? [
|
|
220
|
-
|
|
221
|
-
...(recommendedMode !==
|
|
222
|
-
"retry",
|
|
456
|
+
currentPromptMode,
|
|
457
|
+
...(recommendedMode !== currentPromptMode ? [recommendedMode] : []),
|
|
223
458
|
"once",
|
|
224
459
|
]
|
|
225
460
|
: [
|
|
226
461
|
recommendedMode,
|
|
227
|
-
"retry",
|
|
228
462
|
"once",
|
|
229
463
|
]).filter((mode, index, list) => list.indexOf(mode) === index)
|
|
230
464
|
.filter((mode) => includeCompileOnce || mode !== "once");
|
|
231
465
|
const selectedMode = await p.select({
|
|
232
|
-
message: options.message ?? "How should this
|
|
466
|
+
message: options.message ?? "How should this dataset compile?",
|
|
233
467
|
options: orderedModes.map((mode) => optionsByMode[mode]),
|
|
234
468
|
});
|
|
235
469
|
if (p.isCancel(selectedMode))
|
|
@@ -237,57 +471,42 @@ export async function promptCompileLoopSelection(options) {
|
|
|
237
471
|
if (selectedMode === "once") {
|
|
238
472
|
return {};
|
|
239
473
|
}
|
|
240
|
-
const maxAttempts = await promptRetryAttempts({
|
|
241
|
-
initialMaxAttempts: options.initialMaxAttempts ?? DEFAULT_COMPILE_RETRY_ATTEMPTS,
|
|
242
|
-
minimum: selectedMode === "retry" ? 2 : 1,
|
|
243
|
-
message: selectedMode === "retry"
|
|
244
|
-
? "Maximum compile attempts for the same workflow?"
|
|
245
|
-
: "Attempts per workflow variation?",
|
|
246
|
-
});
|
|
247
|
-
if (maxAttempts === null)
|
|
248
|
-
return null;
|
|
249
|
-
if (selectedMode === "retry") {
|
|
250
|
-
return {
|
|
251
|
-
max_attempts: maxAttempts,
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
474
|
const maxLoops = await promptSelfImprovingLoops({
|
|
255
475
|
initialMaxLoops: options.initialMaxLoops ?? DEFAULT_SELF_IMPROVING_LOOPS,
|
|
256
|
-
message: "
|
|
476
|
+
message: "How many workflow revisions should Interf try?",
|
|
257
477
|
});
|
|
258
478
|
if (maxLoops === null)
|
|
259
479
|
return null;
|
|
260
480
|
return {
|
|
261
|
-
max_attempts:
|
|
481
|
+
max_attempts: compiledMaxAttempts(DEFAULT_COMPILE_RETRY_ATTEMPTS) ?? DEFAULT_COMPILE_RETRY_ATTEMPTS,
|
|
262
482
|
max_loops: maxLoops,
|
|
263
483
|
};
|
|
264
484
|
}
|
|
265
|
-
export async function
|
|
485
|
+
export async function promptSingleCompiledConfig(options = {}) {
|
|
266
486
|
const initial = options.initial;
|
|
267
487
|
const introStyle = options.introStyle ?? "first";
|
|
268
|
-
const collectChecksFirst = introStyle === "first" && options.skipNamePrompt && !options.fixedName;
|
|
269
488
|
if (introStyle === "first") {
|
|
270
|
-
p.log.info("
|
|
271
|
-
p.log.info("
|
|
489
|
+
p.log.info("Pick the dataset folder you want to measure.");
|
|
490
|
+
p.log.info("Then say what this dataset should be accurate about and save a few truth checks you can verify.");
|
|
272
491
|
}
|
|
273
492
|
else if (introStyle === "additional") {
|
|
274
|
-
p.log.info("Add another
|
|
493
|
+
p.log.info("Add another dataset only if this project needs a separate folder or set of truth checks.");
|
|
275
494
|
}
|
|
276
495
|
const fixedName = options.fixedName ? slugify(String(options.fixedName)) : undefined;
|
|
277
496
|
if (options.fixedName && !fixedName) {
|
|
278
|
-
p.log.error("Current
|
|
497
|
+
p.log.error("Current dataset id needs letters, numbers, or dashes.");
|
|
279
498
|
return null;
|
|
280
499
|
}
|
|
281
|
-
let name = fixedName ?? (options.skipNamePrompt ? slugify(String(initial?.name ??
|
|
500
|
+
let name = fixedName ?? (options.skipNamePrompt ? slugify(String(initial?.name ?? DEFAULT_COMPILED_NAME)) : undefined);
|
|
282
501
|
if (name) {
|
|
283
502
|
if (options.fixedName) {
|
|
284
|
-
p.log.info(`Editing truth checks for
|
|
503
|
+
p.log.info(`Editing truth checks for dataset "${name}".`);
|
|
285
504
|
}
|
|
286
505
|
}
|
|
287
506
|
else {
|
|
288
|
-
const suggestedName = initial?.name ?? slugify(String(initial?.about ?? "")) ??
|
|
507
|
+
const suggestedName = initial?.name ?? slugify(String(initial?.about ?? "")) ?? DEFAULT_COMPILED_NAME;
|
|
289
508
|
const rawName = await p.text({
|
|
290
|
-
message: "
|
|
509
|
+
message: "Dataset id?",
|
|
291
510
|
placeholder: suggestedName,
|
|
292
511
|
initialValue: suggestedName,
|
|
293
512
|
validate: (value) => (value.trim().length === 0 ? "Name is required" : undefined),
|
|
@@ -296,60 +515,78 @@ export async function promptSingleWorkspaceConfig(options = {}) {
|
|
|
296
515
|
return null;
|
|
297
516
|
name = slugify(String(rawName));
|
|
298
517
|
if (!name) {
|
|
299
|
-
p.log.error("
|
|
518
|
+
p.log.error("Dataset id needs letters, numbers, or dashes.");
|
|
300
519
|
return null;
|
|
301
520
|
}
|
|
302
521
|
if (name !== rawName) {
|
|
303
|
-
p.log.info(`
|
|
522
|
+
p.log.info(`Dataset id: ${name}`);
|
|
304
523
|
}
|
|
305
524
|
}
|
|
306
|
-
let about = initial?.about
|
|
307
|
-
|
|
525
|
+
let about = normalizeOptionalPromptText(initial?.about);
|
|
526
|
+
const defaultDatasetPath = initial?.path ?? defaultDatasetPathForPrompt(name, introStyle, options.projectPath ?? process.cwd());
|
|
527
|
+
const datasetPath = await p.text({
|
|
528
|
+
message: "Dataset folder?",
|
|
529
|
+
placeholder: DEFAULT_DATASET_PATH_PLACEHOLDER,
|
|
530
|
+
initialValue: defaultDatasetPath,
|
|
531
|
+
validate: (value) => {
|
|
532
|
+
const normalized = value.trim();
|
|
533
|
+
if (normalized.length === 0)
|
|
534
|
+
return "Dataset folder is required";
|
|
535
|
+
try {
|
|
536
|
+
resolveSourceDatasetPath(options.projectPath ?? process.cwd(), { path: normalized });
|
|
537
|
+
return undefined;
|
|
538
|
+
}
|
|
539
|
+
catch (error) {
|
|
540
|
+
return error instanceof Error ? error.message : String(error);
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
});
|
|
544
|
+
if (p.isCancel(datasetPath))
|
|
545
|
+
return null;
|
|
546
|
+
const normalizedDatasetPath = String(datasetPath).trim();
|
|
308
547
|
let compileLoopSelection = {
|
|
309
548
|
...(typeof initial?.max_attempts === "number" ? { max_attempts: initial.max_attempts } : {}),
|
|
310
549
|
...(typeof initial?.max_loops === "number" ? { max_loops: initial.max_loops } : {}),
|
|
311
550
|
};
|
|
312
|
-
if (collectChecksFirst) {
|
|
313
|
-
checks = await promptWorkspaceChecks({
|
|
314
|
-
initialChecks: initial?.checks,
|
|
315
|
-
});
|
|
316
|
-
if (checks === null)
|
|
317
|
-
return null;
|
|
318
|
-
}
|
|
319
551
|
if (!(options.skipAboutPrompt && initial?.about)) {
|
|
320
|
-
|
|
321
|
-
message:
|
|
322
|
-
placeholder:
|
|
323
|
-
initialValue:
|
|
552
|
+
const aboutInput = await p.text({
|
|
553
|
+
message: datasetAboutPromptMessage(introStyle),
|
|
554
|
+
placeholder: DEFAULT_COMPILED_ABOUT_PLACEHOLDER,
|
|
555
|
+
initialValue: about ?? "",
|
|
324
556
|
});
|
|
325
|
-
if (p.isCancel(
|
|
557
|
+
if (p.isCancel(aboutInput))
|
|
326
558
|
return null;
|
|
559
|
+
about = normalizeOptionalPromptText(aboutInput);
|
|
327
560
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
561
|
+
const checks = await promptCompiledChecks({
|
|
562
|
+
projectPath: options.projectPath ?? process.cwd(),
|
|
563
|
+
datasetName: name,
|
|
564
|
+
datasetPath: normalizedDatasetPath,
|
|
565
|
+
initialAbout: about,
|
|
566
|
+
initialChecks: initial?.checks,
|
|
567
|
+
});
|
|
568
|
+
if (checks === null)
|
|
569
|
+
return null;
|
|
570
|
+
if (introStyle === "edit") {
|
|
571
|
+
compileLoopSelection = await promptCompileLoopSelection({
|
|
572
|
+
initialMaxAttempts: initial?.max_attempts,
|
|
573
|
+
initialMaxLoops: initial?.max_loops,
|
|
574
|
+
hasChecks: checks.length > 0,
|
|
575
|
+
intro: [
|
|
576
|
+
...(options.selectedWorkflowLabel
|
|
577
|
+
? [`Workflow: ${options.selectedWorkflowLabel}`]
|
|
578
|
+
: []),
|
|
579
|
+
"Compile mode",
|
|
580
|
+
"Choose whether this dataset should compile once or keep revising the workflow until it passes the same truth checks.",
|
|
581
|
+
],
|
|
332
582
|
});
|
|
333
|
-
if (
|
|
583
|
+
if (compileLoopSelection === null)
|
|
334
584
|
return null;
|
|
335
585
|
}
|
|
336
|
-
compileLoopSelection = await promptCompileLoopSelection({
|
|
337
|
-
initialMaxAttempts: initial?.max_attempts,
|
|
338
|
-
initialMaxLoops: initial?.max_loops,
|
|
339
|
-
hasChecks: checks.length > 0,
|
|
340
|
-
intro: [
|
|
341
|
-
...(options.selectedWorkflowLabel
|
|
342
|
-
? [`Workflow: ${options.selectedWorkflowLabel}`]
|
|
343
|
-
: []),
|
|
344
|
-
"Compile mode",
|
|
345
|
-
"Choose whether this workspace should compile once, retry the same workflow, or run self-improving loops that edit the workflow and retest it on the same truth checks.",
|
|
346
|
-
],
|
|
347
|
-
});
|
|
348
|
-
if (compileLoopSelection === null)
|
|
349
|
-
return null;
|
|
350
586
|
return {
|
|
351
587
|
name,
|
|
352
|
-
|
|
588
|
+
path: normalizedDatasetPath,
|
|
589
|
+
...(about ? { about } : {}),
|
|
353
590
|
...(typeof compileLoopSelection.max_attempts === "number"
|
|
354
591
|
? { max_attempts: compileLoopSelection.max_attempts }
|
|
355
592
|
: {}),
|