@wix/ditto-codegen-public 1.0.473 → 1.0.474
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/dist/opencode-tools/validate.ts +49 -2
- package/dist/out.js +724 -174
- package/package.json +2 -2
|
@@ -1,8 +1,30 @@
|
|
|
1
1
|
import { tool } from "@opencode-ai/plugin";
|
|
2
|
+
import { readdir } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
const EDITOR_COMPONENTS_DIR = "src/extensions/site/components";
|
|
6
|
+
|
|
7
|
+
async function containsTypeScriptFile(directory: string): Promise<boolean> {
|
|
8
|
+
let entries;
|
|
9
|
+
try {
|
|
10
|
+
entries = await readdir(directory, { withFileTypes: true });
|
|
11
|
+
} catch (error) {
|
|
12
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return false;
|
|
13
|
+
throw error;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
for (const entry of entries) {
|
|
17
|
+
const path = join(directory, entry.name);
|
|
18
|
+
if (entry.isDirectory() && (await containsTypeScriptFile(path))) return true;
|
|
19
|
+
if (entry.isFile() && /\.tsx?$/.test(entry.name)) return true;
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
2
23
|
|
|
3
24
|
export default tool({
|
|
4
25
|
description:
|
|
5
|
-
"Run project validation: TypeScript check by default, optionally a full build
|
|
26
|
+
"Run project validation: TypeScript check by default, optionally a full build " +
|
|
27
|
+
"and editor-component manifest generation. " +
|
|
6
28
|
"Use this instead of running npm install, tsc, and wix build separately.",
|
|
7
29
|
args: {
|
|
8
30
|
installDeps: tool.schema
|
|
@@ -18,7 +40,8 @@ export default tool({
|
|
|
18
40
|
.boolean()
|
|
19
41
|
.optional()
|
|
20
42
|
.describe(
|
|
21
|
-
"Default false (tsc only). Pass true to also run `wix build
|
|
43
|
+
"Default false (tsc only). Pass true to also run `wix build` and generate " +
|
|
44
|
+
"manifests when editor components exist. validate " +
|
|
22
45
|
"runs tsc FIRST and builds only if tsc passes, so pass runBuild: true on " +
|
|
23
46
|
"the FIRST call to typecheck+build in one pass — it fails fast on type " +
|
|
24
47
|
"errors before the ~20s build, so a separate tsc-only call is redundant. " +
|
|
@@ -67,6 +90,30 @@ export default tool({
|
|
|
67
90
|
}
|
|
68
91
|
steps.push("wix build: OK");
|
|
69
92
|
|
|
93
|
+
const hasEditorComponents = await containsTypeScriptFile(
|
|
94
|
+
join(cwd, EDITOR_COMPONENTS_DIR),
|
|
95
|
+
);
|
|
96
|
+
if (!hasEditorComponents) {
|
|
97
|
+
steps.push(
|
|
98
|
+
"wix generate manifest: skipped (no editor components)",
|
|
99
|
+
);
|
|
100
|
+
return steps.join("\n");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const manifest = await Bun.$`npx wix generate manifest`
|
|
104
|
+
.cwd(cwd)
|
|
105
|
+
.nothrow()
|
|
106
|
+
.quiet();
|
|
107
|
+
if (manifest.exitCode !== 0) {
|
|
108
|
+
return [
|
|
109
|
+
...steps,
|
|
110
|
+
`FAILED at wix generate manifest (exit ${manifest.exitCode}):`,
|
|
111
|
+
manifest.stdout.toString(),
|
|
112
|
+
manifest.stderr.toString(),
|
|
113
|
+
].join("\n");
|
|
114
|
+
}
|
|
115
|
+
steps.push("wix generate manifest: OK");
|
|
116
|
+
|
|
70
117
|
return steps.join("\n");
|
|
71
118
|
},
|
|
72
119
|
});
|
package/dist/out.js
CHANGED
|
@@ -10700,6 +10700,41 @@ var require_ProcessExecutionError = __commonJS({
|
|
|
10700
10700
|
}
|
|
10701
10701
|
});
|
|
10702
10702
|
|
|
10703
|
+
// ../codegen-types/dist/errors/HostValidationError.js
|
|
10704
|
+
var require_HostValidationError = __commonJS({
|
|
10705
|
+
"../codegen-types/dist/errors/HostValidationError.js"(exports2) {
|
|
10706
|
+
"use strict";
|
|
10707
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
10708
|
+
exports2.HostValidationError = void 0;
|
|
10709
|
+
var BaseCodegenError_1 = require_BaseCodegenError();
|
|
10710
|
+
var ErrorTypes_1 = require_ErrorTypes();
|
|
10711
|
+
var HostValidationError = class extends BaseCodegenError_1.BaseCodegenError {
|
|
10712
|
+
constructor(message, options) {
|
|
10713
|
+
super(message);
|
|
10714
|
+
this.name = "HostValidationError";
|
|
10715
|
+
this.errorType = ErrorTypes_1.ErrorType.PROCESS_EXECUTION_ERROR;
|
|
10716
|
+
this.expected = true;
|
|
10717
|
+
this.retryable = false;
|
|
10718
|
+
this.stage = options.stage;
|
|
10719
|
+
this.command = options.command;
|
|
10720
|
+
this.exitCode = options.exitCode;
|
|
10721
|
+
this.timedOut = options.timedOut;
|
|
10722
|
+
this.diagnosticSummary = options.diagnosticSummary;
|
|
10723
|
+
}
|
|
10724
|
+
getAdditionalProperties() {
|
|
10725
|
+
return {
|
|
10726
|
+
stage: this.stage,
|
|
10727
|
+
command: this.command,
|
|
10728
|
+
timedOut: this.timedOut,
|
|
10729
|
+
...this.exitCode === void 0 ? {} : { exitCode: this.exitCode },
|
|
10730
|
+
...this.diagnosticSummary ? { diagnosticSummary: this.diagnosticSummary } : {}
|
|
10731
|
+
};
|
|
10732
|
+
}
|
|
10733
|
+
};
|
|
10734
|
+
exports2.HostValidationError = HostValidationError;
|
|
10735
|
+
}
|
|
10736
|
+
});
|
|
10737
|
+
|
|
10703
10738
|
// ../codegen-types/dist/errors/UnexpectedError.js
|
|
10704
10739
|
var require_UnexpectedError = __commonJS({
|
|
10705
10740
|
"../codegen-types/dist/errors/UnexpectedError.js"(exports2) {
|
|
@@ -10858,6 +10893,7 @@ var require_errors2 = __commonJS({
|
|
|
10858
10893
|
__exportStar2(require_enums(), exports2);
|
|
10859
10894
|
__exportStar2(require_BaseCodegenError(), exports2);
|
|
10860
10895
|
__exportStar2(require_ProcessExecutionError(), exports2);
|
|
10896
|
+
__exportStar2(require_HostValidationError(), exports2);
|
|
10861
10897
|
__exportStar2(require_UnexpectedError(), exports2);
|
|
10862
10898
|
__exportStar2(require_TimeoutError(), exports2);
|
|
10863
10899
|
__exportStar2(require_MissingJobIdError(), exports2);
|
|
@@ -11055,8 +11091,8 @@ var require_CodeGenService = __commonJS({
|
|
|
11055
11091
|
retryable: error.retryable,
|
|
11056
11092
|
expected: error.expected,
|
|
11057
11093
|
..."processType" in error && error.processType && { processType: PROCESS_TYPE[error.processType] },
|
|
11058
|
-
..."exitCode" in error
|
|
11059
|
-
..."stderr" in error
|
|
11094
|
+
..."exitCode" in error ? { exitCode: error.exitCode } : {},
|
|
11095
|
+
..."diagnosticSummary" in error ? { stderr: error.diagnosticSummary } : "stderr" in error ? { stderr: error.stderr } : {}
|
|
11060
11096
|
};
|
|
11061
11097
|
}
|
|
11062
11098
|
function toApiExtension(ext) {
|
|
@@ -11611,10 +11647,19 @@ RECOVERY STRATEGY:
|
|
|
11611
11647
|
or split it across several files and import them.
|
|
11612
11648
|
3. Prefer many small steps over one big step.`;
|
|
11613
11649
|
function buildRecoveryPrompt(originalPrompt, filesChanged, error, failureReason) {
|
|
11650
|
+
const isHostValidationFailure = failureReason === "host validation failure";
|
|
11614
11651
|
const strategy = failureReason === "stall" ? `
|
|
11615
11652
|
${INCREMENTAL_WRITE_STRATEGY}
|
|
11616
11653
|
` : "";
|
|
11617
|
-
|
|
11654
|
+
const introduction = isHostValidationFailure ? "You are continuing a code generation task because the agent finished, but the required project validation failed." : "You are continuing a code generation task that was interrupted due to a session error.";
|
|
11655
|
+
const recoveryInstructions = isHostValidationFailure ? `1. Review the failed validation stage and diagnostics above
|
|
11656
|
+
2. Inspect the files already changed and fix only the cause of the validation failure
|
|
11657
|
+
3. Run full validation after fixing the reported problem
|
|
11658
|
+
4. Complete the original task without adding unrelated features` : `1. Review the files listed above that were already created/modified in the previous session
|
|
11659
|
+
2. Continue with any remaining work needed to fulfill the original task
|
|
11660
|
+
3. Do NOT recreate files that already exist and are correct - only modify them if needed
|
|
11661
|
+
4. Complete any remaining extensions or files that haven't been created yet`;
|
|
11662
|
+
return buildPrompt(`${introduction}
|
|
11618
11663
|
|
|
11619
11664
|
ORIGINAL TASK:
|
|
11620
11665
|
${originalPrompt}
|
|
@@ -11626,10 +11671,7 @@ PREVIOUS SESSION ERROR:
|
|
|
11626
11671
|
${error}
|
|
11627
11672
|
${strategy}
|
|
11628
11673
|
INSTRUCTIONS:
|
|
11629
|
-
|
|
11630
|
-
2. Continue with any remaining work needed to fulfill the original task
|
|
11631
|
-
3. Do NOT recreate files that already exist and are correct - only modify them if needed
|
|
11632
|
-
4. Complete any remaining extensions or files that haven't been created yet`);
|
|
11674
|
+
${recoveryInstructions}`);
|
|
11633
11675
|
}
|
|
11634
11676
|
}
|
|
11635
11677
|
});
|
|
@@ -11838,12 +11880,13 @@ var require_subagents = __commonJS({
|
|
|
11838
11880
|
exports2.PRIMARY_AGENT_NAME = "codegen";
|
|
11839
11881
|
exports2.VALIDATOR_SUBAGENT_NAME = "codegen-validator";
|
|
11840
11882
|
exports2.SUBAGENT_AGENT_NAMES = [exports2.VALIDATOR_SUBAGENT_NAME];
|
|
11841
|
-
var VALIDATOR_DESCRIPTION = `Runs validate (tsc + wix build) and fixes the reported errors, consulting the
|
|
11842
|
-
skills or wix-mcp for SDK-shape errors; returns when
|
|
11883
|
+
var VALIDATOR_DESCRIPTION = `Runs validate (tsc + wix build + editor-component manifests) and fixes the reported errors, consulting the
|
|
11884
|
+
skills or wix-mcp for SDK-shape errors; returns when validation is clean
|
|
11843
11885
|
or reports what it couldn't fix. Validation step only \u2014 never generates features.`;
|
|
11844
11886
|
var VALIDATOR_PROMPT = `Run 'validate({ runBuild: true })', fix the errors it reports, and re-run until
|
|
11845
11887
|
it passes. You are fixing EXISTING code \u2014 do NOT add features or rewrite whole
|
|
11846
|
-
files, and do NOT run 'npx wix generate manifest' \u2014
|
|
11888
|
+
files, and do NOT run 'npx wix generate manifest' directly \u2014 the validate tool
|
|
11889
|
+
does that automatically when editor components exist.
|
|
11847
11890
|
NEVER force a green build by suppressing types: no 'as any', no
|
|
11848
11891
|
'@ts-ignore', no NEW '@ts-expect-error', and do NOT switch a correct named import to
|
|
11849
11892
|
'import * as' just to satisfy tsc \u2014 that ships code that compiles but breaks
|
|
@@ -14971,12 +15014,12 @@ var require_codegen_rules = __commonJS({
|
|
|
14971
15014
|
var shared_rules_1 = require_shared_rules();
|
|
14972
15015
|
var model_knobs_1 = require_model_knobs();
|
|
14973
15016
|
var DELEGATED_VALIDATION = {
|
|
14974
|
-
toolRule: "- `validate` (tsc + build) is run by the `codegen-validator` subagent \u2014 do NOT call it directly; delegate via `task` at step 5.",
|
|
14975
|
-
step: `5. **Validate**: Dispatch ONE \`task({ subagent: "codegen-validator", prompt: "Run validate({ runBuild: true }) \u2014 it typechecks
|
|
15017
|
+
toolRule: "- `validate` (tsc + build + editor-component manifests) is run by the `codegen-validator` subagent \u2014 do NOT call it directly; delegate via `task` at step 5.",
|
|
15018
|
+
step: `5. **Validate**: Dispatch ONE \`task({ subagent: "codegen-validator", prompt: "Run validate({ runBuild: true }) \u2014 it typechecks, builds, and generates manifests when editor components exist. Fix any errors and re-run until it passes. Pass installDeps: true only if package.json changed and npm install was not already run in this session." })\`. Wait for the subagent to return. Do NOT call \`validate\` directly from the primary agent, and do NOT make a separate tsc-only call first \u2014 the single runBuild pass already fails fast on type errors. VERIFY the subagent actually FINISHED with clean validation: read its returned summary and confirm it converged. If it reports remaining/unresolved errors or was cut off before finishing (e.g. "Maximum steps reached"), do NOT treat it as success \u2014 re-dispatch \`codegen-validator\` to finish the remaining errors before moving on. Do NOT inspect extension types or run \`npx wix generate manifest\` directly; \`validate\` handles manifest generation when editor components exist.`
|
|
14976
15019
|
};
|
|
14977
15020
|
var DIRECT_VALIDATION = {
|
|
14978
|
-
toolRule: "- `validate` (tsc + build) \u2014 you call it yourself at step 5. Do NOT delegate it.",
|
|
14979
|
-
step: `5. **Validate**: Call \`validate({ runBuild: true })\` yourself \u2014 it typechecks
|
|
15021
|
+
toolRule: "- `validate` (tsc + build + editor-component manifests) \u2014 you call it yourself at step 5. Do NOT delegate it.",
|
|
15022
|
+
step: `5. **Validate**: Call \`validate({ runBuild: true })\` yourself \u2014 it typechecks, builds, and generates manifests when editor components exist (tsc runs first and fails fast before the build). Fix any errors and re-run until it passes. Pass installDeps: true only if package.json changed and npm install was not already run in this session. Do NOT delegate this to a subagent, and do NOT make a separate tsc-only call first \u2014 the single runBuild pass already fails fast on type errors. NEVER force a green build: no \`as any\`, no \`@ts-ignore\`, no NEW \`@ts-expect-error\`, no switching a correct named import to \`import * as\`, and no changing runtime behaviour (e.g. unwanted \`defaultProps\` values) or deleting the failing code just to satisfy tsc. Do NOT move on until validation is clean. Do NOT inspect extension types or run \`npx wix generate manifest\` directly; \`validate\` handles manifest generation when editor components exist.`
|
|
14980
15023
|
};
|
|
14981
15024
|
var buildCoreRules = (validation) => `CORE PRINCIPLES:
|
|
14982
15025
|
- Do NOT invent or assume new types, modules, functions, props, events, or imports.
|
|
@@ -15021,7 +15064,7 @@ FILE CREATION:
|
|
|
15021
15064
|
- Do NOT output comments in code unless they explain non-obvious logic.
|
|
15022
15065
|
|
|
15023
15066
|
GENERATED FILES:
|
|
15024
|
-
- \`src/extensions/site/components/**/*.generated.ts\` is an auto-generated editor-react-component manifest \u2014 NEVER hand-edit. Change a manifest VALUE in the component's \`*.extension.ts\`; change anything else in the \`*.tsx\` / \`*.module.css\` / \`*.props.ts\` source
|
|
15067
|
+
- \`src/extensions/site/components/**/*.generated.ts\` is an auto-generated editor-react-component manifest \u2014 NEVER hand-edit. Change a manifest VALUE in the component's \`*.extension.ts\`; change anything else in the \`*.tsx\` / \`*.module.css\` / \`*.props.ts\` source. \`validate({ runBuild: true })\` regenerates the manifest when editor components exist. No other \`.generated.ts\` path is affected.
|
|
15025
15068
|
- A write guard rejects \`write\`/\`edit\`/\`batch-write\`/\`multi-edit\`/\`apply_patch\` there, dropping the ENTIRE call \u2014 never batch that path with real edits (or put it in a patch alongside other hunks), or those are lost too and must be resubmitted.
|
|
15026
15069
|
|
|
15027
15070
|
TYPESCRIPT:
|
|
@@ -15125,7 +15168,7 @@ MINIMIZE TEXT OUTPUT \u2014 CRITICAL:
|
|
|
15125
15168
|
- Every text token costs money. Use tools, not words.
|
|
15126
15169
|
|
|
15127
15170
|
TOOL USAGE:
|
|
15128
|
-
- \`validate\` for
|
|
15171
|
+
- \`validate\` for TypeScript, build, and editor-component manifest validation. Run it after resolving the conflicts; it generates manifests when editor components exist.
|
|
15129
15172
|
${(0, shared_rules_1.buildFileOperationsRules)("resolving conflicts")}
|
|
15130
15173
|
- NEVER run preview, dev, release, or promote commands.
|
|
15131
15174
|
|
|
@@ -15767,6 +15810,361 @@ export const SubagentToolLogger = async () => {
|
|
|
15767
15810
|
}
|
|
15768
15811
|
});
|
|
15769
15812
|
|
|
15813
|
+
// dist/extension-reporting/detect.js
|
|
15814
|
+
var require_detect = __commonJS({
|
|
15815
|
+
"dist/extension-reporting/detect.js"(exports2) {
|
|
15816
|
+
"use strict";
|
|
15817
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
15818
|
+
exports2.BUILDER_EXTENSION_TYPES = void 0;
|
|
15819
|
+
exports2.isSpiExtension = isSpiExtension;
|
|
15820
|
+
exports2.isExtensionsFile = isExtensionsFile;
|
|
15821
|
+
exports2.detectExtension = detectExtension;
|
|
15822
|
+
exports2.matchQuotedExtensionConfigProperty = matchQuotedExtensionConfigProperty;
|
|
15823
|
+
exports2.extractExtensionDisplayTitle = extractExtensionDisplayTitle;
|
|
15824
|
+
exports2.injectCreatedBy = injectCreatedBy;
|
|
15825
|
+
var CONTAINER_ROOT_PREFIX = /^\/user-code\//;
|
|
15826
|
+
var EXTENSION_FILE_PATTERN = /\/extensions\.ts$|\.extension\.ts$/;
|
|
15827
|
+
var SPI_EXTENSION_TYPES = [
|
|
15828
|
+
"ecomShippingRates",
|
|
15829
|
+
"ecomAdditionalFees",
|
|
15830
|
+
"ecomValidations",
|
|
15831
|
+
"ecomDiscountTriggers",
|
|
15832
|
+
"ecomGiftCards",
|
|
15833
|
+
"ecomPaymentSettings",
|
|
15834
|
+
"bookingsStaffSortingProvider"
|
|
15835
|
+
];
|
|
15836
|
+
exports2.BUILDER_EXTENSION_TYPES = [
|
|
15837
|
+
"dashboardPage",
|
|
15838
|
+
"dashboardModal",
|
|
15839
|
+
"dashboardPlugin",
|
|
15840
|
+
"dashboardMenuPlugin",
|
|
15841
|
+
"embeddedScript",
|
|
15842
|
+
"event",
|
|
15843
|
+
"customElement",
|
|
15844
|
+
"siteComponent",
|
|
15845
|
+
"editorReactComponent",
|
|
15846
|
+
"sitePlugin",
|
|
15847
|
+
...SPI_EXTENSION_TYPES,
|
|
15848
|
+
"contextProvider",
|
|
15849
|
+
"functionLibrary",
|
|
15850
|
+
"dataCollections"
|
|
15851
|
+
];
|
|
15852
|
+
var SPI_EXTENSION_TYPE_SET = new Set(SPI_EXTENSION_TYPES);
|
|
15853
|
+
function isSpiExtension(extensionType) {
|
|
15854
|
+
return SPI_EXTENSION_TYPE_SET.has(extensionType);
|
|
15855
|
+
}
|
|
15856
|
+
function normalizeFilePath(filePath) {
|
|
15857
|
+
return filePath.replace(CONTAINER_ROOT_PREFIX, "");
|
|
15858
|
+
}
|
|
15859
|
+
function isExtensionsFile(filePath) {
|
|
15860
|
+
return EXTENSION_FILE_PATTERN.test(filePath);
|
|
15861
|
+
}
|
|
15862
|
+
function detectExtension(content) {
|
|
15863
|
+
for (const extensionType of exports2.BUILDER_EXTENSION_TYPES) {
|
|
15864
|
+
if (content.includes(`extensions.${extensionType}(`) || content.includes(`experimentalExtensions.${extensionType}(`)) {
|
|
15865
|
+
return extensionType;
|
|
15866
|
+
}
|
|
15867
|
+
}
|
|
15868
|
+
return null;
|
|
15869
|
+
}
|
|
15870
|
+
function toTitleCase(str) {
|
|
15871
|
+
return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
15872
|
+
}
|
|
15873
|
+
function extractExtensionName(filePath) {
|
|
15874
|
+
const parts = normalizeFilePath(filePath).split("/");
|
|
15875
|
+
const folderName = parts[parts.length - 2] || "";
|
|
15876
|
+
return toTitleCase(folderName);
|
|
15877
|
+
}
|
|
15878
|
+
function matchQuotedExtensionConfigProperty(content, propName) {
|
|
15879
|
+
const objectPropertyQuotedStringValuePattern = `\\b${propName}\\s*:\\s*(?:"([^"\\\\]*)"|'([^'\\\\]*)')`;
|
|
15880
|
+
const objectPropertyQuotedStringValueRegex = new RegExp(
|
|
15881
|
+
objectPropertyQuotedStringValuePattern,
|
|
15882
|
+
// `m` = multiline: `^` / `$` match line starts/ends, not only the whole string.
|
|
15883
|
+
"m"
|
|
15884
|
+
);
|
|
15885
|
+
const quotedStringValueMatch = content.match(objectPropertyQuotedStringValueRegex);
|
|
15886
|
+
if (!quotedStringValueMatch)
|
|
15887
|
+
return null;
|
|
15888
|
+
return quotedStringValueMatch[1] ?? quotedStringValueMatch[2] ?? null;
|
|
15889
|
+
}
|
|
15890
|
+
function extractExtensionDisplayTitle(content, filePath) {
|
|
15891
|
+
const title = matchQuotedExtensionConfigProperty(content, "title");
|
|
15892
|
+
if (title)
|
|
15893
|
+
return title;
|
|
15894
|
+
const name = matchQuotedExtensionConfigProperty(content, "name");
|
|
15895
|
+
if (name)
|
|
15896
|
+
return name;
|
|
15897
|
+
const displayName = matchQuotedExtensionConfigProperty(content, "displayName");
|
|
15898
|
+
if (displayName)
|
|
15899
|
+
return displayName;
|
|
15900
|
+
const idSuffix = matchQuotedExtensionConfigProperty(content, "idSuffix");
|
|
15901
|
+
if (idSuffix)
|
|
15902
|
+
return idSuffix;
|
|
15903
|
+
return extractExtensionName(filePath);
|
|
15904
|
+
}
|
|
15905
|
+
function injectCreatedBy(content) {
|
|
15906
|
+
if (content.includes("createdBy"))
|
|
15907
|
+
return content;
|
|
15908
|
+
const isGeneric = content.includes("genericExtension(");
|
|
15909
|
+
const createdByValue = isGeneric ? ' createdBy: "CODE_GEN",' : ' createdBy: {\n author: "CODE_GEN",\n },';
|
|
15910
|
+
return content.replace(/(\S)(\n)(}\))(;?\s*)$/, (_match, preChar, newline, closeBrace, tail) => {
|
|
15911
|
+
const needsComma = preChar !== "," && preChar !== "{";
|
|
15912
|
+
const separator = needsComma ? `${preChar},` : preChar;
|
|
15913
|
+
return `${separator}${newline}${createdByValue}
|
|
15914
|
+
${closeBrace}${tail}`;
|
|
15915
|
+
});
|
|
15916
|
+
}
|
|
15917
|
+
}
|
|
15918
|
+
});
|
|
15919
|
+
|
|
15920
|
+
// dist/git/repository-status.js
|
|
15921
|
+
var require_repository_status = __commonJS({
|
|
15922
|
+
"dist/git/repository-status.js"(exports2) {
|
|
15923
|
+
"use strict";
|
|
15924
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
15925
|
+
exports2.isMissingGitRepository = isMissingGitRepository;
|
|
15926
|
+
exports2.hasGitRepository = hasGitRepository;
|
|
15927
|
+
var child_process_1 = require("child_process");
|
|
15928
|
+
var util_1 = require("util");
|
|
15929
|
+
var execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
15930
|
+
function isMissingGitRepository(exitCode, stderr) {
|
|
15931
|
+
return exitCode === 128 && /^fatal: not a git repository\b/m.test(stderr);
|
|
15932
|
+
}
|
|
15933
|
+
async function hasGitRepository(cwd) {
|
|
15934
|
+
try {
|
|
15935
|
+
await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
15936
|
+
cwd,
|
|
15937
|
+
env: { ...process.env, LC_ALL: "C" }
|
|
15938
|
+
});
|
|
15939
|
+
return true;
|
|
15940
|
+
} catch (error) {
|
|
15941
|
+
if (error instanceof Error && "code" in error && typeof error.code === "number" && "stderr" in error && typeof error.stderr === "string" && isMissingGitRepository(error.code, error.stderr))
|
|
15942
|
+
return false;
|
|
15943
|
+
throw error;
|
|
15944
|
+
}
|
|
15945
|
+
}
|
|
15946
|
+
}
|
|
15947
|
+
});
|
|
15948
|
+
|
|
15949
|
+
// dist/extension-reporting/prepare-created-by.js
|
|
15950
|
+
var require_prepare_created_by = __commonJS({
|
|
15951
|
+
"dist/extension-reporting/prepare-created-by.js"(exports2) {
|
|
15952
|
+
"use strict";
|
|
15953
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
15954
|
+
exports2.prepareCreatedExtensionFiles = prepareCreatedExtensionFiles;
|
|
15955
|
+
exports2.prepareCreatedByForValidation = prepareCreatedByForValidation;
|
|
15956
|
+
var child_process_1 = require("child_process");
|
|
15957
|
+
var promises_1 = require("fs/promises");
|
|
15958
|
+
var path_12 = require("path");
|
|
15959
|
+
var util_1 = require("util");
|
|
15960
|
+
var detect_1 = require_detect();
|
|
15961
|
+
var repository_status_1 = require_repository_status();
|
|
15962
|
+
var execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
15963
|
+
async function prepareCreatedExtensionFiles(paths, read, write, inject, builders) {
|
|
15964
|
+
for (const path of new Set(paths)) {
|
|
15965
|
+
if (!/(^|\/)extensions\.ts$|\.extension\.ts$/.test(path))
|
|
15966
|
+
continue;
|
|
15967
|
+
const original = await read(path);
|
|
15968
|
+
if (!builders.some((builder) => original.includes(`extensions.${builder}(`) || original.includes(`experimentalExtensions.${builder}(`)))
|
|
15969
|
+
continue;
|
|
15970
|
+
const injected = inject(original);
|
|
15971
|
+
if (injected !== original)
|
|
15972
|
+
await write(path, injected);
|
|
15973
|
+
}
|
|
15974
|
+
}
|
|
15975
|
+
async function prepareCreatedByForValidation(cwd, baseline) {
|
|
15976
|
+
if (!await (0, repository_status_1.hasGitRepository)(cwd))
|
|
15977
|
+
return;
|
|
15978
|
+
const [added, untracked] = await Promise.all([
|
|
15979
|
+
execFileAsync("git", baseline ? [
|
|
15980
|
+
"diff",
|
|
15981
|
+
"--name-only",
|
|
15982
|
+
"--diff-filter=A",
|
|
15983
|
+
"--no-renames",
|
|
15984
|
+
"-z",
|
|
15985
|
+
baseline
|
|
15986
|
+
] : ["ls-files", "--cached", "-z"], { cwd }),
|
|
15987
|
+
execFileAsync("git", ["ls-files", "--others", "--exclude-standard", "-z"], {
|
|
15988
|
+
cwd
|
|
15989
|
+
})
|
|
15990
|
+
]);
|
|
15991
|
+
await prepareCreatedExtensionFiles((added.stdout + untracked.stdout).split("\0").filter(Boolean), (path) => (0, promises_1.readFile)((0, path_12.join)(cwd, path), "utf8"), (path, content) => (0, promises_1.writeFile)((0, path_12.join)(cwd, path), content, "utf8"), detect_1.injectCreatedBy, detect_1.BUILDER_EXTENSION_TYPES);
|
|
15992
|
+
}
|
|
15993
|
+
}
|
|
15994
|
+
});
|
|
15995
|
+
|
|
15996
|
+
// dist/opencode-integration/plugins/validation-state.js
|
|
15997
|
+
var require_validation_state = __commonJS({
|
|
15998
|
+
"dist/opencode-integration/plugins/validation-state.js"(exports2) {
|
|
15999
|
+
"use strict";
|
|
16000
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
16001
|
+
exports2.VALIDATION_NUDGE = exports2.VALIDATION_STATE_PLUGIN_FILENAME = exports2.VALIDATION_LOADED_EVENT_TYPE = exports2.VALIDATION_STATE_EVENT_TYPE = void 0;
|
|
16002
|
+
exports2.isReadOnlyShellCommand = isReadOnlyShellCommand;
|
|
16003
|
+
exports2.buildValidationStateSource = buildValidationStateSource;
|
|
16004
|
+
exports2.writeValidationStatePlugin = writeValidationStatePlugin;
|
|
16005
|
+
var write_plugin_1 = require_write_plugin();
|
|
16006
|
+
var detect_1 = require_detect();
|
|
16007
|
+
var prepare_created_by_1 = require_prepare_created_by();
|
|
16008
|
+
var repository_status_1 = require_repository_status();
|
|
16009
|
+
function isReadOnlyShellCommand(command) {
|
|
16010
|
+
return /^(?:ls|pwd|cat|head|tail|wc|grep)(?:[ \t]+[A-Za-z0-9_./:@%+=,-]+)*[ \t]*$/.test(command);
|
|
16011
|
+
}
|
|
16012
|
+
exports2.VALIDATION_STATE_EVENT_TYPE = "validation_state";
|
|
16013
|
+
exports2.VALIDATION_LOADED_EVENT_TYPE = "validation_loaded";
|
|
16014
|
+
exports2.VALIDATION_STATE_PLUGIN_FILENAME = "validation-state.ts";
|
|
16015
|
+
exports2.VALIDATION_NUDGE = "Project files need validation. Follow your validation workflow (delegate to codegen-validator if your instructions require it), run validate({ runBuild: true }), and fix any errors before finishing.";
|
|
16016
|
+
function buildValidationStateSource() {
|
|
16017
|
+
return String.raw`// Generated by @wix/ditto-codegen (validation-state). Do not edit.
|
|
16018
|
+
const EVENT_TYPE = ${JSON.stringify(exports2.VALIDATION_STATE_EVENT_TYPE)};
|
|
16019
|
+
const LOADED_EVENT_TYPE = ${JSON.stringify(exports2.VALIDATION_LOADED_EVENT_TYPE)};
|
|
16020
|
+
const VALIDATION_NUDGE = ${JSON.stringify(exports2.VALIDATION_NUDGE)};
|
|
16021
|
+
const BUILDERS = ${JSON.stringify(detect_1.BUILDER_EXTENSION_TYPES)};
|
|
16022
|
+
const injectCreatedBy = ${detect_1.injectCreatedBy.toString()};
|
|
16023
|
+
const prepareCreatedExtensionFiles = ${prepare_created_by_1.prepareCreatedExtensionFiles.toString()};
|
|
16024
|
+
const isMissingGitRepository = ${repository_status_1.isMissingGitRepository.toString()};
|
|
16025
|
+
const isReadOnlyShellCommand = ${isReadOnlyShellCommand.toString()};
|
|
16026
|
+
const MUTATING_TOOLS = new Set(["write", "edit", "apply_patch", "batch-write", "multi-edit", "wix-generate", "bash"]);
|
|
16027
|
+
|
|
16028
|
+
export const ValidationState = async ({ client, directory, $ }) => {
|
|
16029
|
+
const runGit = async (args) => {
|
|
16030
|
+
const command = Object.assign(["LC_ALL=C git ", ""], { raw: ["LC_ALL=C git ", ""] });
|
|
16031
|
+
return await $(command, args).cwd(directory).nothrow().quiet();
|
|
16032
|
+
};
|
|
16033
|
+
const git = async (args) => {
|
|
16034
|
+
const result = await runGit(args);
|
|
16035
|
+
if (result.exitCode !== 0) throw new Error("Cannot inspect project validation state: " + result.stderr.toString());
|
|
16036
|
+
return result.stdout.toString().split("\0").filter(Boolean);
|
|
16037
|
+
};
|
|
16038
|
+
|
|
16039
|
+
const repository = await runGit(["rev-parse", "--is-inside-work-tree"]);
|
|
16040
|
+
// No loaded marker: the host must run the compatibility gate instead.
|
|
16041
|
+
if (isMissingGitRepository(repository.exitCode, repository.stderr.toString())) return {};
|
|
16042
|
+
if (repository.exitCode !== 0) throw new Error("Cannot inspect Git repository: " + repository.stderr.toString());
|
|
16043
|
+
const snapshot = async () => {
|
|
16044
|
+
const paths = [...new Set(await git(["ls-files", "--cached", "--others", "--exclude-standard", "-z"]))]
|
|
16045
|
+
.filter((path) => !path.startsWith(".agents/")).sort();
|
|
16046
|
+
const hash = new Bun.CryptoHasher("sha256");
|
|
16047
|
+
for (const path of paths) {
|
|
16048
|
+
hash.update(path + "\0");
|
|
16049
|
+
const file = Bun.file(directory + "/" + path);
|
|
16050
|
+
hash.update(await file.exists() ? await file.arrayBuffer() : "<deleted>");
|
|
16051
|
+
hash.update("\0");
|
|
16052
|
+
}
|
|
16053
|
+
return hash.digest("hex");
|
|
16054
|
+
};
|
|
16055
|
+
const prepareMetadata = async () => {
|
|
16056
|
+
if (process.env.CODEGEN_PREPARE_EXTENSION_METADATA !== "1") return;
|
|
16057
|
+
const baseline = process.env.CODEGEN_VALIDATION_BASELINE;
|
|
16058
|
+
const paths = [
|
|
16059
|
+
...await git(baseline ? ["diff", "--name-only", "--diff-filter=A", "--no-renames", "-z", baseline] : ["ls-files", "--cached", "-z"]),
|
|
16060
|
+
...await git(["ls-files", "--others", "--exclude-standard", "-z"]),
|
|
16061
|
+
];
|
|
16062
|
+
await prepareCreatedExtensionFiles(paths,
|
|
16063
|
+
(path) => Bun.file(directory + "/" + path).text(),
|
|
16064
|
+
async (path, content) => { await Bun.write(directory + "/" + path, content); },
|
|
16065
|
+
injectCreatedBy, BUILDERS);
|
|
16066
|
+
};
|
|
16067
|
+
|
|
16068
|
+
let cleanFingerprint = await snapshot();
|
|
16069
|
+
let currentFingerprint = cleanFingerprint;
|
|
16070
|
+
let hasValidationFailure = process.env.CODEGEN_REQUIRE_VALIDATION === "1";
|
|
16071
|
+
let hasUnvalidatedMutation = false;
|
|
16072
|
+
let lastClean;
|
|
16073
|
+
let mutationEpoch = 0;
|
|
16074
|
+
let revisionNudges = 0;
|
|
16075
|
+
let totalNudges = 0;
|
|
16076
|
+
const remindedMessages = new Set();
|
|
16077
|
+
const validations = new Map();
|
|
16078
|
+
const activeMutations = new Set();
|
|
16079
|
+
const key = (input) => input.sessionID + ":" + input.callID;
|
|
16080
|
+
const emit = (sessionID, clean) => {
|
|
16081
|
+
if (lastClean === clean) return;
|
|
16082
|
+
lastClean = clean;
|
|
16083
|
+
process.stdout.write(JSON.stringify({ type: EVENT_TYPE, sessionID, clean }) + "\n");
|
|
16084
|
+
};
|
|
16085
|
+
const refresh = async (sessionID) => {
|
|
16086
|
+
const fingerprint = await snapshot();
|
|
16087
|
+
if (fingerprint !== currentFingerprint) revisionNudges = 0;
|
|
16088
|
+
currentFingerprint = fingerprint;
|
|
16089
|
+
const clean = !hasValidationFailure && !hasUnvalidatedMutation && activeMutations.size === 0 &&
|
|
16090
|
+
validations.size === 0 && fingerprint === cleanFingerprint;
|
|
16091
|
+
emit(sessionID, clean);
|
|
16092
|
+
return clean;
|
|
16093
|
+
};
|
|
16094
|
+
process.stdout.write(JSON.stringify({ type: LOADED_EVENT_TYPE }) + "\n");
|
|
16095
|
+
if (hasValidationFailure) emit("repair", false);
|
|
16096
|
+
|
|
16097
|
+
return {
|
|
16098
|
+
event: async ({ event }) => {
|
|
16099
|
+
const part = event.type === "message.part.updated" ? event.properties?.part : undefined;
|
|
16100
|
+
if (part?.type !== "tool" || part.state?.status !== "error") return;
|
|
16101
|
+
const callKey = part.sessionID + ":" + part.callID;
|
|
16102
|
+
activeMutations.delete(callKey);
|
|
16103
|
+
if (validations.delete(callKey)) hasValidationFailure = true;
|
|
16104
|
+
},
|
|
16105
|
+
"tool.execute.before": async (input, output) => {
|
|
16106
|
+
const args = output.args;
|
|
16107
|
+
if (input.tool === "validate") {
|
|
16108
|
+
if (args.runBuild === true || args.installDeps === true) {
|
|
16109
|
+
emit(input.sessionID, false);
|
|
16110
|
+
hasValidationFailure = true;
|
|
16111
|
+
await prepareMetadata();
|
|
16112
|
+
currentFingerprint = await snapshot();
|
|
16113
|
+
validations.set(key(input), mutationEpoch);
|
|
16114
|
+
}
|
|
16115
|
+
} else if (MUTATING_TOOLS.has(input.tool)) {
|
|
16116
|
+
if (input.tool !== "bash" || typeof args.command !== "string" || !isReadOnlyShellCommand(args.command)) {
|
|
16117
|
+
hasUnvalidatedMutation = true;
|
|
16118
|
+
revisionNudges = 0;
|
|
16119
|
+
}
|
|
16120
|
+
mutationEpoch += 1;
|
|
16121
|
+
activeMutations.add(key(input));
|
|
16122
|
+
emit(input.sessionID, false);
|
|
16123
|
+
}
|
|
16124
|
+
},
|
|
16125
|
+
"tool.execute.after": async (input, output) => {
|
|
16126
|
+
if (input.tool === "validate") {
|
|
16127
|
+
const epoch = validations.get(key(input));
|
|
16128
|
+
validations.delete(key(input));
|
|
16129
|
+
const passed = typeof output.output === "string" && !/^FAILED at/m.test(output.output);
|
|
16130
|
+
if (!passed) hasValidationFailure = true;
|
|
16131
|
+
if (passed && input.args?.runBuild === true) {
|
|
16132
|
+
const fingerprint = await snapshot();
|
|
16133
|
+
if (epoch === mutationEpoch && activeMutations.size === 0 && validations.size === 0) {
|
|
16134
|
+
cleanFingerprint = fingerprint;
|
|
16135
|
+
hasValidationFailure = false;
|
|
16136
|
+
hasUnvalidatedMutation = false;
|
|
16137
|
+
}
|
|
16138
|
+
}
|
|
16139
|
+
await refresh(input.sessionID);
|
|
16140
|
+
} else if (MUTATING_TOOLS.has(input.tool)) {
|
|
16141
|
+
activeMutations.delete(key(input));
|
|
16142
|
+
await refresh(input.sessionID);
|
|
16143
|
+
}
|
|
16144
|
+
},
|
|
16145
|
+
"experimental.text.complete": async (input) => {
|
|
16146
|
+
if (await refresh(input.sessionID)) return;
|
|
16147
|
+
const messageKey = input.sessionID + ":" + input.messageID;
|
|
16148
|
+
if (remindedMessages.has(messageKey) || revisionNudges >= 2 || totalNudges >= 8) return;
|
|
16149
|
+
remindedMessages.add(messageKey);
|
|
16150
|
+
revisionNudges += 1;
|
|
16151
|
+
totalNudges += 1;
|
|
16152
|
+
await client.session.prompt({
|
|
16153
|
+
path: { id: input.sessionID },
|
|
16154
|
+
body: { noReply: true, parts: [{ type: "text", text: VALIDATION_NUDGE }] },
|
|
16155
|
+
});
|
|
16156
|
+
},
|
|
16157
|
+
};
|
|
16158
|
+
};
|
|
16159
|
+
|
|
16160
|
+
`;
|
|
16161
|
+
}
|
|
16162
|
+
async function writeValidationStatePlugin() {
|
|
16163
|
+
await (0, write_plugin_1.writeGeneratedPlugin)(exports2.VALIDATION_STATE_PLUGIN_FILENAME, buildValidationStateSource());
|
|
16164
|
+
}
|
|
16165
|
+
}
|
|
16166
|
+
});
|
|
16167
|
+
|
|
15770
16168
|
// dist/opencode-integration/apply-patch.js
|
|
15771
16169
|
var require_apply_patch = __commonJS({
|
|
15772
16170
|
"dist/opencode-integration/apply-patch.js"(exports2) {
|
|
@@ -15786,6 +16184,9 @@ var require_parser = __commonJS({
|
|
|
15786
16184
|
"dist/opencode-integration/execution/parser.js"(exports2) {
|
|
15787
16185
|
"use strict";
|
|
15788
16186
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
16187
|
+
exports2.hasValidationPluginLoaded = hasValidationPluginLoaded;
|
|
16188
|
+
exports2.parseLastValidationState = parseLastValidationState;
|
|
16189
|
+
exports2.parseRequiredPermissionsDeclaration = parseRequiredPermissionsDeclaration;
|
|
15789
16190
|
exports2.parseRequiredPermissions = parseRequiredPermissions;
|
|
15790
16191
|
exports2.parseAnswerText = parseAnswerText;
|
|
15791
16192
|
exports2.createEmptyUsageStats = createEmptyUsageStats;
|
|
@@ -15795,9 +16196,26 @@ var require_parser = __commonJS({
|
|
|
15795
16196
|
exports2.summarizeOpenCodeLine = summarizeOpenCodeLine;
|
|
15796
16197
|
var types_1 = require_types4();
|
|
15797
16198
|
var subagent_tool_logger_1 = require_subagent_tool_logger();
|
|
16199
|
+
var validation_state_1 = require_validation_state();
|
|
15798
16200
|
var apply_patch_1 = require_apply_patch();
|
|
15799
|
-
function
|
|
15800
|
-
|
|
16201
|
+
function hasValidationPluginLoaded(output) {
|
|
16202
|
+
return output.split("\n").some((line) => (0, types_1.tryParseJson)(line)?.type === validation_state_1.VALIDATION_LOADED_EVENT_TYPE);
|
|
16203
|
+
}
|
|
16204
|
+
function parseLastValidationState(output) {
|
|
16205
|
+
let validationState;
|
|
16206
|
+
for (const line of output.split("\n")) {
|
|
16207
|
+
if (!line.trim())
|
|
16208
|
+
continue;
|
|
16209
|
+
const event = (0, types_1.tryParseJson)(line);
|
|
16210
|
+
if (event?.type !== validation_state_1.VALIDATION_STATE_EVENT_TYPE || typeof event.sessionID !== "string" || typeof event.clean !== "boolean") {
|
|
16211
|
+
continue;
|
|
16212
|
+
}
|
|
16213
|
+
validationState = event;
|
|
16214
|
+
}
|
|
16215
|
+
return validationState;
|
|
16216
|
+
}
|
|
16217
|
+
function parseRequiredPermissionsDeclaration(output) {
|
|
16218
|
+
let permissions;
|
|
15801
16219
|
const lines = output.split("\n");
|
|
15802
16220
|
for (const line of lines) {
|
|
15803
16221
|
if (!line.trim())
|
|
@@ -15813,6 +16231,9 @@ var require_parser = __commonJS({
|
|
|
15813
16231
|
}
|
|
15814
16232
|
return permissions;
|
|
15815
16233
|
}
|
|
16234
|
+
function parseRequiredPermissions(output) {
|
|
16235
|
+
return parseRequiredPermissionsDeclaration(output) ?? [];
|
|
16236
|
+
}
|
|
15816
16237
|
function parseAnswerText(output) {
|
|
15817
16238
|
const messages = output.split("\n").map((line) => (0, types_1.tryParseJson)(line)).filter((event) => event?.type === "text").map((event) => event.part?.text ?? "");
|
|
15818
16239
|
return (messages[messages.length - 1] ?? "").trim();
|
|
@@ -16181,113 +16602,6 @@ var require_progress_handler = __commonJS({
|
|
|
16181
16602
|
}
|
|
16182
16603
|
});
|
|
16183
16604
|
|
|
16184
|
-
// dist/extension-reporting/detect.js
|
|
16185
|
-
var require_detect = __commonJS({
|
|
16186
|
-
"dist/extension-reporting/detect.js"(exports2) {
|
|
16187
|
-
"use strict";
|
|
16188
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
16189
|
-
exports2.BUILDER_EXTENSION_TYPES = void 0;
|
|
16190
|
-
exports2.isSpiExtension = isSpiExtension;
|
|
16191
|
-
exports2.isExtensionsFile = isExtensionsFile;
|
|
16192
|
-
exports2.detectExtension = detectExtension;
|
|
16193
|
-
exports2.matchQuotedExtensionConfigProperty = matchQuotedExtensionConfigProperty;
|
|
16194
|
-
exports2.extractExtensionDisplayTitle = extractExtensionDisplayTitle;
|
|
16195
|
-
exports2.injectCreatedBy = injectCreatedBy;
|
|
16196
|
-
var CONTAINER_ROOT_PREFIX = /^\/user-code\//;
|
|
16197
|
-
var EXTENSION_FILE_PATTERN = /\/extensions\.ts$|\.extension\.ts$/;
|
|
16198
|
-
var SPI_EXTENSION_TYPES = [
|
|
16199
|
-
"ecomShippingRates",
|
|
16200
|
-
"ecomAdditionalFees",
|
|
16201
|
-
"ecomValidations",
|
|
16202
|
-
"ecomDiscountTriggers",
|
|
16203
|
-
"ecomGiftCards",
|
|
16204
|
-
"ecomPaymentSettings",
|
|
16205
|
-
"bookingsStaffSortingProvider"
|
|
16206
|
-
];
|
|
16207
|
-
exports2.BUILDER_EXTENSION_TYPES = [
|
|
16208
|
-
"dashboardPage",
|
|
16209
|
-
"dashboardModal",
|
|
16210
|
-
"dashboardPlugin",
|
|
16211
|
-
"dashboardMenuPlugin",
|
|
16212
|
-
"embeddedScript",
|
|
16213
|
-
"event",
|
|
16214
|
-
"customElement",
|
|
16215
|
-
"siteComponent",
|
|
16216
|
-
"editorReactComponent",
|
|
16217
|
-
"sitePlugin",
|
|
16218
|
-
...SPI_EXTENSION_TYPES,
|
|
16219
|
-
"contextProvider",
|
|
16220
|
-
"functionLibrary",
|
|
16221
|
-
"dataCollections"
|
|
16222
|
-
];
|
|
16223
|
-
var SPI_EXTENSION_TYPE_SET = new Set(SPI_EXTENSION_TYPES);
|
|
16224
|
-
function isSpiExtension(extensionType) {
|
|
16225
|
-
return SPI_EXTENSION_TYPE_SET.has(extensionType);
|
|
16226
|
-
}
|
|
16227
|
-
function normalizeFilePath(filePath) {
|
|
16228
|
-
return filePath.replace(CONTAINER_ROOT_PREFIX, "");
|
|
16229
|
-
}
|
|
16230
|
-
function isExtensionsFile(filePath) {
|
|
16231
|
-
return EXTENSION_FILE_PATTERN.test(filePath);
|
|
16232
|
-
}
|
|
16233
|
-
function detectExtension(content) {
|
|
16234
|
-
for (const extensionType of exports2.BUILDER_EXTENSION_TYPES) {
|
|
16235
|
-
if (content.includes(`extensions.${extensionType}(`) || content.includes(`experimentalExtensions.${extensionType}(`)) {
|
|
16236
|
-
return extensionType;
|
|
16237
|
-
}
|
|
16238
|
-
}
|
|
16239
|
-
return null;
|
|
16240
|
-
}
|
|
16241
|
-
function toTitleCase(str) {
|
|
16242
|
-
return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
16243
|
-
}
|
|
16244
|
-
function extractExtensionName(filePath) {
|
|
16245
|
-
const parts = normalizeFilePath(filePath).split("/");
|
|
16246
|
-
const folderName = parts[parts.length - 2] || "";
|
|
16247
|
-
return toTitleCase(folderName);
|
|
16248
|
-
}
|
|
16249
|
-
function matchQuotedExtensionConfigProperty(content, propName) {
|
|
16250
|
-
const objectPropertyQuotedStringValuePattern = `\\b${propName}\\s*:\\s*(?:"([^"\\\\]*)"|'([^'\\\\]*)')`;
|
|
16251
|
-
const objectPropertyQuotedStringValueRegex = new RegExp(
|
|
16252
|
-
objectPropertyQuotedStringValuePattern,
|
|
16253
|
-
// `m` = multiline: `^` / `$` match line starts/ends, not only the whole string.
|
|
16254
|
-
"m"
|
|
16255
|
-
);
|
|
16256
|
-
const quotedStringValueMatch = content.match(objectPropertyQuotedStringValueRegex);
|
|
16257
|
-
if (!quotedStringValueMatch)
|
|
16258
|
-
return null;
|
|
16259
|
-
return quotedStringValueMatch[1] ?? quotedStringValueMatch[2] ?? null;
|
|
16260
|
-
}
|
|
16261
|
-
function extractExtensionDisplayTitle(content, filePath) {
|
|
16262
|
-
const title = matchQuotedExtensionConfigProperty(content, "title");
|
|
16263
|
-
if (title)
|
|
16264
|
-
return title;
|
|
16265
|
-
const name = matchQuotedExtensionConfigProperty(content, "name");
|
|
16266
|
-
if (name)
|
|
16267
|
-
return name;
|
|
16268
|
-
const displayName = matchQuotedExtensionConfigProperty(content, "displayName");
|
|
16269
|
-
if (displayName)
|
|
16270
|
-
return displayName;
|
|
16271
|
-
const idSuffix = matchQuotedExtensionConfigProperty(content, "idSuffix");
|
|
16272
|
-
if (idSuffix)
|
|
16273
|
-
return idSuffix;
|
|
16274
|
-
return extractExtensionName(filePath);
|
|
16275
|
-
}
|
|
16276
|
-
function injectCreatedBy(content) {
|
|
16277
|
-
if (content.includes("createdBy"))
|
|
16278
|
-
return content;
|
|
16279
|
-
const isGeneric = content.includes("genericExtension(");
|
|
16280
|
-
const createdByValue = isGeneric ? ' createdBy: "CODE_GEN",' : ' createdBy: {\n author: "CODE_GEN",\n },';
|
|
16281
|
-
return content.replace(/(\S)(\n)(}\))(;?\s*)$/, (_match, preChar, newline, closeBrace, tail) => {
|
|
16282
|
-
const needsComma = preChar !== "," && preChar !== "{";
|
|
16283
|
-
const separator = needsComma ? `${preChar},` : preChar;
|
|
16284
|
-
return `${separator}${newline}${createdByValue}
|
|
16285
|
-
${closeBrace}${tail}`;
|
|
16286
|
-
});
|
|
16287
|
-
}
|
|
16288
|
-
}
|
|
16289
|
-
});
|
|
16290
|
-
|
|
16291
16605
|
// dist/opencode-integration/task-tracker/derived-progress.js
|
|
16292
16606
|
var require_derived_progress = __commonJS({
|
|
16293
16607
|
"dist/opencode-integration/task-tracker/derived-progress.js"(exports2) {
|
|
@@ -17005,12 +17319,150 @@ var require_process_handlers = __commonJS({
|
|
|
17005
17319
|
}
|
|
17006
17320
|
});
|
|
17007
17321
|
|
|
17322
|
+
// dist/validation/editor-components.js
|
|
17323
|
+
var require_editor_components = __commonJS({
|
|
17324
|
+
"dist/validation/editor-components.js"(exports2) {
|
|
17325
|
+
"use strict";
|
|
17326
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
17327
|
+
exports2.containsTypeScriptFile = containsTypeScriptFile;
|
|
17328
|
+
var promises_1 = require("fs/promises");
|
|
17329
|
+
var path_12 = require("path");
|
|
17330
|
+
async function containsTypeScriptFile(directory) {
|
|
17331
|
+
const entries = await (0, promises_1.readdir)(directory, { withFileTypes: true }).catch((error) => {
|
|
17332
|
+
if (error.code === "ENOENT")
|
|
17333
|
+
return [];
|
|
17334
|
+
throw error;
|
|
17335
|
+
});
|
|
17336
|
+
for (const entry of entries) {
|
|
17337
|
+
if (entry.isFile() && /\.tsx?$/.test(entry.name))
|
|
17338
|
+
return true;
|
|
17339
|
+
if (entry.isDirectory() && await containsTypeScriptFile((0, path_12.join)(directory, entry.name)))
|
|
17340
|
+
return true;
|
|
17341
|
+
}
|
|
17342
|
+
return false;
|
|
17343
|
+
}
|
|
17344
|
+
}
|
|
17345
|
+
});
|
|
17346
|
+
|
|
17347
|
+
// dist/validation/host-validation.js
|
|
17348
|
+
var require_host_validation = __commonJS({
|
|
17349
|
+
"dist/validation/host-validation.js"(exports2) {
|
|
17350
|
+
"use strict";
|
|
17351
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
17352
|
+
exports2.HostValidationError = exports2.HOST_VALIDATION_STAGE_TIMEOUT_MS = void 0;
|
|
17353
|
+
exports2.runHostValidation = runHostValidation;
|
|
17354
|
+
var child_process_1 = require("child_process");
|
|
17355
|
+
var util_1 = require("util");
|
|
17356
|
+
var ditto_codegen_types_12 = require_dist4();
|
|
17357
|
+
var logger_12 = require_logger();
|
|
17358
|
+
var path_12 = require("path");
|
|
17359
|
+
var editor_components_1 = require_editor_components();
|
|
17360
|
+
var execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
17361
|
+
var MAX_OUTPUT_BUFFER_BYTES = 10 * 1024 * 1024;
|
|
17362
|
+
var MAX_DIAGNOSTIC_CHARS = 2e4;
|
|
17363
|
+
var MAX_DIAGNOSTIC_SUMMARY_CHARS = 2e3;
|
|
17364
|
+
exports2.HOST_VALIDATION_STAGE_TIMEOUT_MS = 5 * 6e4;
|
|
17365
|
+
var VALIDATION_COMMANDS = [
|
|
17366
|
+
{
|
|
17367
|
+
stage: "typescript",
|
|
17368
|
+
executable: "npx",
|
|
17369
|
+
args: ["tsc", "--noEmit", "-p", "."]
|
|
17370
|
+
},
|
|
17371
|
+
{
|
|
17372
|
+
stage: "wix build",
|
|
17373
|
+
executable: "npx",
|
|
17374
|
+
args: ["wix", "build"]
|
|
17375
|
+
},
|
|
17376
|
+
{
|
|
17377
|
+
stage: "wix generate manifest",
|
|
17378
|
+
executable: "npx",
|
|
17379
|
+
args: ["wix", "generate", "manifest"]
|
|
17380
|
+
}
|
|
17381
|
+
];
|
|
17382
|
+
var HostValidationError = class extends ditto_codegen_types_12.HostValidationError {
|
|
17383
|
+
constructor(stage, command, options) {
|
|
17384
|
+
const diagnostics = [options.stdout, options.stderr].filter((output) => Boolean(output?.trim())).join("\n").trim();
|
|
17385
|
+
const exit = options.timedOut ? `timed out after ${options.timeoutMs}ms` : options.exitCode === void 0 ? "could not start" : `exited ${options.exitCode}`;
|
|
17386
|
+
super(`Project validation failed at ${stage}: ${command} ${exit}`, {
|
|
17387
|
+
stage,
|
|
17388
|
+
command,
|
|
17389
|
+
exitCode: options.exitCode,
|
|
17390
|
+
timedOut: options.timedOut ?? false,
|
|
17391
|
+
diagnosticSummary: outputAsString(diagnostics, MAX_DIAGNOSTIC_SUMMARY_CHARS)
|
|
17392
|
+
});
|
|
17393
|
+
this.stage = stage;
|
|
17394
|
+
this.validationType = stage;
|
|
17395
|
+
this.command = command;
|
|
17396
|
+
this.timedOut = options.timedOut ?? false;
|
|
17397
|
+
Object.defineProperties(this, {
|
|
17398
|
+
stdout: { value: options.stdout, enumerable: false },
|
|
17399
|
+
stderr: { value: options.stderr, enumerable: false },
|
|
17400
|
+
cause: { value: options.cause, enumerable: false }
|
|
17401
|
+
});
|
|
17402
|
+
}
|
|
17403
|
+
};
|
|
17404
|
+
exports2.HostValidationError = HostValidationError;
|
|
17405
|
+
var executeValidationCommand = async (executable, args, cwd, timeoutMs) => {
|
|
17406
|
+
return execFileAsync(executable, args, {
|
|
17407
|
+
cwd,
|
|
17408
|
+
killSignal: "SIGTERM",
|
|
17409
|
+
maxBuffer: MAX_OUTPUT_BUFFER_BYTES,
|
|
17410
|
+
timeout: timeoutMs
|
|
17411
|
+
});
|
|
17412
|
+
};
|
|
17413
|
+
function outputAsString(output, maxChars = MAX_DIAGNOSTIC_CHARS) {
|
|
17414
|
+
const text = typeof output === "string" ? output : output?.toString() ?? "";
|
|
17415
|
+
if (text.length <= maxChars)
|
|
17416
|
+
return text;
|
|
17417
|
+
const omitted = text.length - maxChars;
|
|
17418
|
+
return `[truncated ${omitted} leading characters]
|
|
17419
|
+
${text.slice(-maxChars)}`;
|
|
17420
|
+
}
|
|
17421
|
+
function numericExitCode(error) {
|
|
17422
|
+
return typeof error.code === "number" ? error.code : void 0;
|
|
17423
|
+
}
|
|
17424
|
+
async function runHostValidation(cwd, execute = executeValidationCommand) {
|
|
17425
|
+
for (const command of VALIDATION_COMMANDS) {
|
|
17426
|
+
if (command.stage === "wix generate manifest" && !await (0, editor_components_1.containsTypeScriptFile)((0, path_12.join)(cwd, "src/extensions/site/components")))
|
|
17427
|
+
continue;
|
|
17428
|
+
const displayCommand = [command.executable, ...command.args].join(" ");
|
|
17429
|
+
const startTime = Date.now();
|
|
17430
|
+
logger_12.logger.info("[Host Validation] Starting stage", {
|
|
17431
|
+
stage: command.stage,
|
|
17432
|
+
command: displayCommand
|
|
17433
|
+
});
|
|
17434
|
+
try {
|
|
17435
|
+
await execute(command.executable, command.args, cwd, exports2.HOST_VALIDATION_STAGE_TIMEOUT_MS);
|
|
17436
|
+
logger_12.logger.info("[Host Validation] Stage passed", {
|
|
17437
|
+
stage: command.stage,
|
|
17438
|
+
durationMs: Date.now() - startTime
|
|
17439
|
+
});
|
|
17440
|
+
} catch (error) {
|
|
17441
|
+
const failure = error instanceof Error ? error : new Error(String(error));
|
|
17442
|
+
const timedOut = failure.killed === true && failure.signal === "SIGTERM";
|
|
17443
|
+
const stderr = outputAsString(failure.stderr) || (timedOut ? `Command timed out after ${exports2.HOST_VALIDATION_STAGE_TIMEOUT_MS}ms` : failure.message);
|
|
17444
|
+
throw new HostValidationError(command.stage, displayCommand, {
|
|
17445
|
+
exitCode: numericExitCode(failure),
|
|
17446
|
+
stdout: outputAsString(failure.stdout),
|
|
17447
|
+
stderr,
|
|
17448
|
+
timedOut,
|
|
17449
|
+
timeoutMs: exports2.HOST_VALIDATION_STAGE_TIMEOUT_MS
|
|
17450
|
+
});
|
|
17451
|
+
}
|
|
17452
|
+
}
|
|
17453
|
+
}
|
|
17454
|
+
}
|
|
17455
|
+
});
|
|
17456
|
+
|
|
17008
17457
|
// dist/opencode-integration/execution/executor.js
|
|
17009
17458
|
var require_executor = __commonJS({
|
|
17010
17459
|
"dist/opencode-integration/execution/executor.js"(exports2) {
|
|
17011
17460
|
"use strict";
|
|
17012
17461
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
17462
|
+
exports2.reserveHostValidationRepairAttempt = reserveHostValidationRepairAttempt;
|
|
17463
|
+
exports2.updateRequiredPermissions = updateRequiredPermissions;
|
|
17013
17464
|
exports2.classifyAttempt = classifyAttempt;
|
|
17465
|
+
exports2.applyPostRunValidation = applyPostRunValidation;
|
|
17014
17466
|
exports2.executeOpenCode = executeOpenCode;
|
|
17015
17467
|
exports2.resolveFinalRunCost = resolveFinalRunCost;
|
|
17016
17468
|
var child_process_1 = require("child_process");
|
|
@@ -17027,11 +17479,16 @@ var require_executor = __commonJS({
|
|
|
17027
17479
|
var process_manager_1 = require_process_manager();
|
|
17028
17480
|
var process_handlers_1 = require_process_handlers();
|
|
17029
17481
|
var logger_12 = require_logger();
|
|
17482
|
+
var host_validation_1 = require_host_validation();
|
|
17030
17483
|
var MAX_RETRIES = 5;
|
|
17484
|
+
var MAX_HOST_VALIDATION_FAILURES = 2;
|
|
17031
17485
|
var MAX_STALL_ATTEMPTS = 2;
|
|
17032
17486
|
function failureReason(result) {
|
|
17033
17487
|
if (result.stalled)
|
|
17034
17488
|
return "stall";
|
|
17489
|
+
if (result.error instanceof host_validation_1.HostValidationError) {
|
|
17490
|
+
return "host validation failure";
|
|
17491
|
+
}
|
|
17035
17492
|
if ((0, parser_1.hasSessionError)(result.stdout))
|
|
17036
17493
|
return "session error";
|
|
17037
17494
|
if (result.error instanceof ditto_codegen_types_12.ProcessExecutionError) {
|
|
@@ -17042,13 +17499,50 @@ var require_executor = __commonJS({
|
|
|
17042
17499
|
}
|
|
17043
17500
|
return null;
|
|
17044
17501
|
}
|
|
17045
|
-
function
|
|
17502
|
+
function reserveHostValidationRepairAttempt(maxAttempts, hostValidationFailures) {
|
|
17503
|
+
return hostValidationFailures === 1 ? maxAttempts + 1 : maxAttempts;
|
|
17504
|
+
}
|
|
17505
|
+
function updateRequiredPermissions(current, result) {
|
|
17506
|
+
if (!result.success || failureReason(result))
|
|
17507
|
+
return current;
|
|
17508
|
+
return (0, parser_1.parseRequiredPermissionsDeclaration)(result.stdout) ?? current;
|
|
17509
|
+
}
|
|
17510
|
+
function classifyAttempt(result, stalls, hostValidationFailures = 0) {
|
|
17046
17511
|
const reason = failureReason(result);
|
|
17047
17512
|
if (!reason)
|
|
17048
17513
|
return { retryable: false, reason: null };
|
|
17514
|
+
if (reason === "host validation failure") {
|
|
17515
|
+
if (result.error instanceof host_validation_1.HostValidationError && result.error.stage === "agent validation state") {
|
|
17516
|
+
return { retryable: false, reason };
|
|
17517
|
+
}
|
|
17518
|
+
return {
|
|
17519
|
+
retryable: hostValidationFailures < MAX_HOST_VALIDATION_FAILURES,
|
|
17520
|
+
reason
|
|
17521
|
+
};
|
|
17522
|
+
}
|
|
17049
17523
|
return { retryable: stalls < MAX_STALL_ATTEMPTS, reason };
|
|
17050
17524
|
}
|
|
17051
|
-
async function
|
|
17525
|
+
async function applyPostRunValidation(result, postRunValidation) {
|
|
17526
|
+
if (!result.success || !postRunValidation)
|
|
17527
|
+
return result;
|
|
17528
|
+
try {
|
|
17529
|
+
await postRunValidation(result.stdout);
|
|
17530
|
+
return result;
|
|
17531
|
+
} catch (error) {
|
|
17532
|
+
const validationError = error instanceof host_validation_1.HostValidationError ? error : new host_validation_1.HostValidationError("project finalization", "project finalization", {
|
|
17533
|
+
stderr: error instanceof Error ? error.message : String(error),
|
|
17534
|
+
cause: error
|
|
17535
|
+
});
|
|
17536
|
+
return {
|
|
17537
|
+
...result,
|
|
17538
|
+
success: false,
|
|
17539
|
+
exitCode: validationError.exitCode ?? null,
|
|
17540
|
+
stderr: validationError.stderr ?? result.stderr,
|
|
17541
|
+
error: validationError
|
|
17542
|
+
};
|
|
17543
|
+
}
|
|
17544
|
+
}
|
|
17545
|
+
async function executeOpenCode(options, executeAttempt = executeOpenCodeOnce) {
|
|
17052
17546
|
let lastResult = null;
|
|
17053
17547
|
let accumulatedUsage = (0, parser_1.createEmptyUsageStats)();
|
|
17054
17548
|
const accumulatedSkills = [];
|
|
@@ -17056,26 +17550,35 @@ var require_executor = __commonJS({
|
|
|
17056
17550
|
let currentPrompt = options.prompt;
|
|
17057
17551
|
let lastFailureReason = null;
|
|
17058
17552
|
let stalls = 0;
|
|
17553
|
+
let hostValidationFailures = 0;
|
|
17554
|
+
let requiredPermissions = [];
|
|
17555
|
+
let maxAttempts = MAX_RETRIES;
|
|
17059
17556
|
const forceFresh = process.env.CODEGEN_FRESH_SESSION === "true";
|
|
17060
17557
|
let continueSession = forceFresh ? false : options.continueSession ?? false;
|
|
17061
17558
|
const env = (0, config_12.getOpenCodeEnv)(options.projectId, job_context_storage_12.jobContextStorage.getStore()?.kind);
|
|
17062
17559
|
const statsBaseline = await (0, cost_tracker_1.fetchOpenCodeStats)(options.outputPath, env);
|
|
17063
17560
|
const baselineCost = statsBaseline ? (0, cost_tracker_1.parseStatsTotalCost)(statsBaseline) : null;
|
|
17064
17561
|
logger_12.logger.debug("[OpenCode] Stats baseline before run", { baselineCost });
|
|
17065
|
-
for (let attempt = 1; attempt <=
|
|
17562
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
17066
17563
|
if (attempt > 1) {
|
|
17067
|
-
const failureDetail = lastResult?.error?.message || lastResult?.stderr || "Process timed out";
|
|
17068
|
-
logger_12.logger.info(`[OpenCode] Retry attempt ${attempt}/${
|
|
17564
|
+
const failureDetail = lastResult?.error instanceof host_validation_1.HostValidationError ? [lastResult.error.message, lastResult.error.stderr].filter((value) => Boolean(value)).join("\n") : lastResult?.error?.message || lastResult?.stderr || "Process timed out";
|
|
17565
|
+
logger_12.logger.info(`[OpenCode] Retry attempt ${attempt}/${maxAttempts} after ${lastFailureReason} - starting fresh session with recovery context`, { reason: lastFailureReason, detail: failureDetail.slice(0, 500) });
|
|
17069
17566
|
const filesChanged = await (0, file_changes_1.collectGitFileChanges)(options.outputPath, options.gitBaseline);
|
|
17070
17567
|
currentPrompt = (0, prompts_1.buildRecoveryPrompt)(options.prompt, filesChanged, failureDetail, lastFailureReason);
|
|
17071
17568
|
continueSession = false;
|
|
17072
17569
|
}
|
|
17073
|
-
|
|
17570
|
+
let result = await executeAttempt({ ...options, prompt: currentPrompt, continueSession }, attempt, maxAttempts, toolUsage);
|
|
17074
17571
|
accumulatedUsage = (0, parser_1.mergeUsageStats)(accumulatedUsage, result.usage);
|
|
17075
17572
|
accumulatedSkills.push(...result.skillsUsed);
|
|
17573
|
+
requiredPermissions = updateRequiredPermissions(requiredPermissions, result);
|
|
17574
|
+
result = await applyPostRunValidation(result, options.postRunValidation);
|
|
17076
17575
|
if (result.stalled)
|
|
17077
17576
|
stalls += 1;
|
|
17078
|
-
|
|
17577
|
+
if (result.error instanceof host_validation_1.HostValidationError && result.error.stage !== "agent validation state") {
|
|
17578
|
+
hostValidationFailures += 1;
|
|
17579
|
+
maxAttempts = reserveHostValidationRepairAttempt(maxAttempts, hostValidationFailures);
|
|
17580
|
+
}
|
|
17581
|
+
const { retryable, reason } = classifyAttempt(result, stalls, hostValidationFailures);
|
|
17079
17582
|
if (!retryable) {
|
|
17080
17583
|
if (reason) {
|
|
17081
17584
|
logger_12.logger.warn(`[OpenCode] Not retrying after ${reason}`, {
|
|
@@ -17087,6 +17590,7 @@ var require_executor = __commonJS({
|
|
|
17087
17590
|
const finalResult2 = {
|
|
17088
17591
|
...result,
|
|
17089
17592
|
agentMessage: (0, parser_1.parseAnswerText)(result.stdout),
|
|
17593
|
+
requiredPermissions,
|
|
17090
17594
|
usage: accumulatedUsage,
|
|
17091
17595
|
skillsUsed: accumulatedSkills,
|
|
17092
17596
|
toolUsage: toolUsage.toSummary()
|
|
@@ -17098,17 +17602,18 @@ var require_executor = __commonJS({
|
|
|
17098
17602
|
lastFailureReason = reason;
|
|
17099
17603
|
logger_12.logger.warn(`[OpenCode] Attempt failed due to ${reason}, will retry`, {
|
|
17100
17604
|
attempt,
|
|
17101
|
-
maxRetries:
|
|
17605
|
+
maxRetries: maxAttempts,
|
|
17102
17606
|
detail: (result.error?.message || result.stderr || "").slice(0, 500)
|
|
17103
17607
|
});
|
|
17104
17608
|
}
|
|
17105
17609
|
logger_12.logger.warn("[OpenCode] All retry attempts exhausted", {
|
|
17106
|
-
maxRetries:
|
|
17610
|
+
maxRetries: maxAttempts
|
|
17107
17611
|
});
|
|
17108
17612
|
accumulatedUsage = await resolveFinalRunCost(accumulatedUsage, options, baselineCost);
|
|
17109
17613
|
const finalResult = {
|
|
17110
17614
|
...lastResult,
|
|
17111
17615
|
agentMessage: (0, parser_1.parseAnswerText)(lastResult.stdout),
|
|
17616
|
+
requiredPermissions,
|
|
17112
17617
|
usage: accumulatedUsage,
|
|
17113
17618
|
skillsUsed: Array.from(accumulatedSkills),
|
|
17114
17619
|
toolUsage: toolUsage.toSummary()
|
|
@@ -17140,7 +17645,7 @@ var require_executor = __commonJS({
|
|
|
17140
17645
|
const sessionArgs = continueSession ? ["--continue"] : [];
|
|
17141
17646
|
return ["run", ...sessionArgs, "--format", "json", prompt];
|
|
17142
17647
|
}
|
|
17143
|
-
async function executeOpenCodeOnce(options, attempt, toolUsage) {
|
|
17648
|
+
async function executeOpenCodeOnce(options, attempt, maxAttempts, toolUsage) {
|
|
17144
17649
|
const { prompt, outputPath, projectId, onStdout, onStderr, continueSession = false } = options;
|
|
17145
17650
|
const startTime = Date.now();
|
|
17146
17651
|
const taskTracker = new task_tracker_1.OpenCodeTaskTracker(outputPath, toolUsage);
|
|
@@ -17179,7 +17684,7 @@ var require_executor = __commonJS({
|
|
|
17179
17684
|
const args = buildArgs(prompt, continueSession);
|
|
17180
17685
|
logger_12.logger.info("[OpenCode] Executing opencode run", {
|
|
17181
17686
|
attempt,
|
|
17182
|
-
maxRetries:
|
|
17687
|
+
maxRetries: maxAttempts,
|
|
17183
17688
|
workingDirectory: outputPath,
|
|
17184
17689
|
continueSession,
|
|
17185
17690
|
model: (0, model_knobs_1.getModel)(),
|
|
@@ -17187,6 +17692,9 @@ var require_executor = __commonJS({
|
|
|
17187
17692
|
});
|
|
17188
17693
|
logger_12.logger.debug("[OpenCode] Full prompt", { prompt });
|
|
17189
17694
|
const env = (0, config_12.getOpenCodeEnv)(projectId, job_context_storage_12.jobContextStorage.getStore()?.kind);
|
|
17695
|
+
env.CODEGEN_VALIDATION_BASELINE = options.gitBaseline;
|
|
17696
|
+
env.CODEGEN_PREPARE_EXTENSION_METADATA = options.prepareExtensionMetadata ? "1" : "0";
|
|
17697
|
+
env.CODEGEN_REQUIRE_VALIDATION = attempt > 1 ? "1" : "0";
|
|
17190
17698
|
ctx.child = (0, child_process_1.spawn)("opencode", args, {
|
|
17191
17699
|
cwd: outputPath,
|
|
17192
17700
|
env,
|
|
@@ -17222,6 +17730,41 @@ var require_executor = __commonJS({
|
|
|
17222
17730
|
}
|
|
17223
17731
|
});
|
|
17224
17732
|
|
|
17733
|
+
// dist/validation/session-validation.js
|
|
17734
|
+
var require_session_validation = __commonJS({
|
|
17735
|
+
"dist/validation/session-validation.js"(exports2) {
|
|
17736
|
+
"use strict";
|
|
17737
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
17738
|
+
exports2.validateSessionOrFallback = validateSessionOrFallback;
|
|
17739
|
+
var parser_1 = require_parser();
|
|
17740
|
+
var prepare_created_by_1 = require_prepare_created_by();
|
|
17741
|
+
var logger_12 = require_logger();
|
|
17742
|
+
var host_validation_1 = require_host_validation();
|
|
17743
|
+
async function validateSessionOrFallback(outputPath, stdout, metadataBaseline) {
|
|
17744
|
+
const validationState = (0, parser_1.parseLastValidationState)(stdout);
|
|
17745
|
+
if (!validationState) {
|
|
17746
|
+
if ((0, parser_1.hasValidationPluginLoaded)(stdout))
|
|
17747
|
+
return;
|
|
17748
|
+
logger_12.logger.info("[Validation State] No plugin state found; running host validation fallback");
|
|
17749
|
+
if (metadataBaseline !== void 0)
|
|
17750
|
+
await (0, prepare_created_by_1.prepareCreatedByForValidation)(outputPath, metadataBaseline);
|
|
17751
|
+
await (0, host_validation_1.runHostValidation)(outputPath);
|
|
17752
|
+
return;
|
|
17753
|
+
}
|
|
17754
|
+
if (validationState.clean) {
|
|
17755
|
+
logger_12.logger.info("[Validation State] Agent session ended clean", {
|
|
17756
|
+
sessionID: validationState.sessionID
|
|
17757
|
+
});
|
|
17758
|
+
return;
|
|
17759
|
+
}
|
|
17760
|
+
throw new host_validation_1.HostValidationError("agent validation state", "validate({ runBuild: true })", {
|
|
17761
|
+
exitCode: 1,
|
|
17762
|
+
stderr: "Project files remain unvalidated after the in-session validation reminders."
|
|
17763
|
+
});
|
|
17764
|
+
}
|
|
17765
|
+
}
|
|
17766
|
+
});
|
|
17767
|
+
|
|
17225
17768
|
// dist/opencode-integration/execution/opencode-runner.js
|
|
17226
17769
|
var require_opencode_runner = __commonJS({
|
|
17227
17770
|
"dist/opencode-integration/execution/opencode-runner.js"(exports2) {
|
|
@@ -17234,6 +17777,7 @@ var require_opencode_runner = __commonJS({
|
|
|
17234
17777
|
var prompts_1 = require_prompts();
|
|
17235
17778
|
var executor_1 = require_executor();
|
|
17236
17779
|
var parser_1 = require_parser();
|
|
17780
|
+
var session_validation_1 = require_session_validation();
|
|
17237
17781
|
async function runOpenCodeInit(options) {
|
|
17238
17782
|
const { blueprint, outputPath, projectId, chatHistory, gitBaseline, onStdout, onStderr } = options;
|
|
17239
17783
|
const prompt = (0, prompts_1.buildInitPrompt)(blueprint, chatHistory);
|
|
@@ -17242,6 +17786,8 @@ var require_opencode_runner = __commonJS({
|
|
|
17242
17786
|
outputPath,
|
|
17243
17787
|
projectId,
|
|
17244
17788
|
gitBaseline,
|
|
17789
|
+
prepareExtensionMetadata: true,
|
|
17790
|
+
postRunValidation: (stdout) => (0, session_validation_1.validateSessionOrFallback)(outputPath, stdout, gitBaseline),
|
|
17245
17791
|
onStdout,
|
|
17246
17792
|
onStderr
|
|
17247
17793
|
});
|
|
@@ -17255,6 +17801,8 @@ var require_opencode_runner = __commonJS({
|
|
|
17255
17801
|
projectId,
|
|
17256
17802
|
continueSession: true,
|
|
17257
17803
|
gitBaseline,
|
|
17804
|
+
prepareExtensionMetadata: true,
|
|
17805
|
+
postRunValidation: (stdout) => (0, session_validation_1.validateSessionOrFallback)(outputPath, stdout, gitBaseline),
|
|
17258
17806
|
onStdout,
|
|
17259
17807
|
onStderr
|
|
17260
17808
|
});
|
|
@@ -17286,6 +17834,7 @@ var require_opencode_runner = __commonJS({
|
|
|
17286
17834
|
outputPath,
|
|
17287
17835
|
projectId,
|
|
17288
17836
|
gitBaseline,
|
|
17837
|
+
postRunValidation: (stdout) => (0, session_validation_1.validateSessionOrFallback)(outputPath, stdout),
|
|
17289
17838
|
onStdout,
|
|
17290
17839
|
onStderr
|
|
17291
17840
|
});
|
|
@@ -17672,39 +18221,6 @@ var require_codegen_flow_helpers = __commonJS({
|
|
|
17672
18221
|
}
|
|
17673
18222
|
});
|
|
17674
18223
|
|
|
17675
|
-
// dist/extension-reporting/inject-created-by.js
|
|
17676
|
-
var require_inject_created_by = __commonJS({
|
|
17677
|
-
"dist/extension-reporting/inject-created-by.js"(exports2) {
|
|
17678
|
-
"use strict";
|
|
17679
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
17680
|
-
exports2.injectCreatedByIntoExtensionFiles = injectCreatedByIntoExtensionFiles;
|
|
17681
|
-
var promises_1 = require("fs/promises");
|
|
17682
|
-
var path_12 = require("path");
|
|
17683
|
-
var logger_12 = require_logger();
|
|
17684
|
-
var detect_1 = require_detect();
|
|
17685
|
-
async function injectCreatedByIntoExtensionFiles(cwd, createdExtensions) {
|
|
17686
|
-
for (const { path: filePath } of createdExtensions) {
|
|
17687
|
-
const absolutePath = (0, path_12.join)(cwd, filePath);
|
|
17688
|
-
try {
|
|
17689
|
-
const original = await (0, promises_1.readFile)(absolutePath, "utf-8");
|
|
17690
|
-
const injected = (0, detect_1.injectCreatedBy)(original);
|
|
17691
|
-
if (injected !== original) {
|
|
17692
|
-
await (0, promises_1.writeFile)(absolutePath, injected, "utf-8");
|
|
17693
|
-
logger_12.logger.info("[OpenCode] Injected createdBy into extension file", {
|
|
17694
|
-
filePath
|
|
17695
|
-
});
|
|
17696
|
-
}
|
|
17697
|
-
} catch (error) {
|
|
17698
|
-
logger_12.logger.error("[OpenCode] Failed to inject createdBy", {
|
|
17699
|
-
filePath,
|
|
17700
|
-
error: error instanceof Error ? error.message : String(error)
|
|
17701
|
-
});
|
|
17702
|
-
}
|
|
17703
|
-
}
|
|
17704
|
-
}
|
|
17705
|
-
}
|
|
17706
|
-
});
|
|
17707
|
-
|
|
17708
18224
|
// ../../node_modules/@wix/bi-logger-dev-tools-data/dist/cjs/v2/index.js
|
|
17709
18225
|
var require_v2 = __commonJS({
|
|
17710
18226
|
"../../node_modules/@wix/bi-logger-dev-tools-data/dist/cjs/v2/index.js"(exports2) {
|
|
@@ -22787,7 +23303,6 @@ var require_opencode_init = __commonJS({
|
|
|
22787
23303
|
var logger_12 = require_logger();
|
|
22788
23304
|
var model_knobs_1 = require_model_knobs();
|
|
22789
23305
|
var file_changes_1 = require_file_changes();
|
|
22790
|
-
var inject_created_by_1 = require_inject_created_by();
|
|
22791
23306
|
var job_payload_1 = require_job_payload2();
|
|
22792
23307
|
var bi_events_1 = require_bi_events();
|
|
22793
23308
|
var expensive_run_1 = require_expensive_run();
|
|
@@ -22853,7 +23368,6 @@ var require_opencode_init = __commonJS({
|
|
|
22853
23368
|
filesChanged = files.length > 0;
|
|
22854
23369
|
const agentOutput = (0, agent_io_1.readAgentOutput)(outputPath);
|
|
22855
23370
|
const extensions = await (0, job_payload_1.buildExtensionsJobPayload)(outputPath, files);
|
|
22856
|
-
await (0, inject_created_by_1.injectCreatedByIntoExtensionFiles)(outputPath, extensions.created);
|
|
22857
23371
|
await (0, codegen_flow_helpers_12.updateJobPayload)(localJobContext, {
|
|
22858
23372
|
requiredPermissions: result.requiredPermissions,
|
|
22859
23373
|
agentMessage: result.agentMessage,
|
|
@@ -23008,7 +23522,6 @@ var require_opencode_iterate = __commonJS({
|
|
|
23008
23522
|
var logger_12 = require_logger();
|
|
23009
23523
|
var model_knobs_1 = require_model_knobs();
|
|
23010
23524
|
var file_changes_1 = require_file_changes();
|
|
23011
|
-
var inject_created_by_1 = require_inject_created_by();
|
|
23012
23525
|
var job_payload_1 = require_job_payload2();
|
|
23013
23526
|
var expensive_run_1 = require_expensive_run();
|
|
23014
23527
|
var bi_events_1 = require_bi_events();
|
|
@@ -23062,7 +23575,6 @@ var require_opencode_iterate = __commonJS({
|
|
|
23062
23575
|
filesChanged = files.length > 0;
|
|
23063
23576
|
const agentOutput = (0, agent_io_1.readAgentOutput)(outputPath);
|
|
23064
23577
|
const extensions = await (0, job_payload_1.buildExtensionsJobPayload)(outputPath, files);
|
|
23065
|
-
await (0, inject_created_by_1.injectCreatedByIntoExtensionFiles)(outputPath, extensions.created);
|
|
23066
23578
|
await (0, codegen_flow_helpers_12.updateJobPayload)(localJobContext, {
|
|
23067
23579
|
requiredPermissions: result.requiredPermissions,
|
|
23068
23580
|
agentMessage: result.agentMessage,
|
|
@@ -23196,6 +23708,42 @@ var require_opencode_ask_orchestrator = __commonJS({
|
|
|
23196
23708
|
}
|
|
23197
23709
|
});
|
|
23198
23710
|
|
|
23711
|
+
// dist/extension-reporting/inject-created-by.js
|
|
23712
|
+
var require_inject_created_by = __commonJS({
|
|
23713
|
+
"dist/extension-reporting/inject-created-by.js"(exports2) {
|
|
23714
|
+
"use strict";
|
|
23715
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
23716
|
+
exports2.injectCreatedByIntoExtensionFiles = injectCreatedByIntoExtensionFiles;
|
|
23717
|
+
var promises_1 = require("fs/promises");
|
|
23718
|
+
var path_12 = require("path");
|
|
23719
|
+
var logger_12 = require_logger();
|
|
23720
|
+
var detect_1 = require_detect();
|
|
23721
|
+
async function injectCreatedByIntoExtensionFiles(cwd, createdExtensions) {
|
|
23722
|
+
let hasWrittenFiles = false;
|
|
23723
|
+
for (const { path: filePath } of createdExtensions) {
|
|
23724
|
+
const absolutePath = (0, path_12.join)(cwd, filePath);
|
|
23725
|
+
try {
|
|
23726
|
+
const original = await (0, promises_1.readFile)(absolutePath, "utf-8");
|
|
23727
|
+
const injected = (0, detect_1.injectCreatedBy)(original);
|
|
23728
|
+
if (injected !== original) {
|
|
23729
|
+
hasWrittenFiles = true;
|
|
23730
|
+
await (0, promises_1.writeFile)(absolutePath, injected, "utf-8");
|
|
23731
|
+
logger_12.logger.info("[OpenCode] Injected createdBy into extension file", {
|
|
23732
|
+
filePath
|
|
23733
|
+
});
|
|
23734
|
+
}
|
|
23735
|
+
} catch (error) {
|
|
23736
|
+
logger_12.logger.error("[OpenCode] Failed to inject createdBy", {
|
|
23737
|
+
filePath,
|
|
23738
|
+
error: error instanceof Error ? error.message : String(error)
|
|
23739
|
+
});
|
|
23740
|
+
}
|
|
23741
|
+
}
|
|
23742
|
+
return hasWrittenFiles;
|
|
23743
|
+
}
|
|
23744
|
+
}
|
|
23745
|
+
});
|
|
23746
|
+
|
|
23199
23747
|
// dist/flows/opencode-ask.js
|
|
23200
23748
|
var require_opencode_ask = __commonJS({
|
|
23201
23749
|
"dist/flows/opencode-ask.js"(exports2) {
|
|
@@ -24345,6 +24893,7 @@ var require_plugins3 = __commonJS({
|
|
|
24345
24893
|
var generated_files_guard_1 = require_generated_files_guard();
|
|
24346
24894
|
var subagent_tool_logger_1 = require_subagent_tool_logger();
|
|
24347
24895
|
var tool_policies_1 = require_tool_policies3();
|
|
24896
|
+
var validation_state_1 = require_validation_state();
|
|
24348
24897
|
var tool_policies_drift_1 = require_tool_policies_drift();
|
|
24349
24898
|
Object.defineProperty(exports2, "validateToolPolicies", { enumerable: true, get: function() {
|
|
24350
24899
|
return tool_policies_drift_1.validateToolPolicies;
|
|
@@ -24354,7 +24903,8 @@ var require_plugins3 = __commonJS({
|
|
|
24354
24903
|
(0, docs_feedback_nudge_1.writeDocsFeedbackNudgePlugin)(),
|
|
24355
24904
|
(0, generated_files_guard_1.writeGeneratedFilesGuardPlugin)(),
|
|
24356
24905
|
(0, subagent_tool_logger_1.writeSubagentToolLoggerPlugin)(),
|
|
24357
|
-
(0, tool_policies_1.writeToolPoliciesPlugin)(toolPolicies)
|
|
24906
|
+
(0, tool_policies_1.writeToolPoliciesPlugin)(toolPolicies),
|
|
24907
|
+
(0, validation_state_1.writeValidationStatePlugin)()
|
|
24358
24908
|
]);
|
|
24359
24909
|
}
|
|
24360
24910
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/ditto-codegen-public",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.474",
|
|
4
4
|
"description": "AI-powered Wix CLI app generator - standalone executable",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "node build.mjs",
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"esbuild": "^0.27.2",
|
|
30
30
|
"vitest": "^4.0.16"
|
|
31
31
|
},
|
|
32
|
-
"falconPackageHash": "
|
|
32
|
+
"falconPackageHash": "8269ada8fd7fe966143942252728a71519b497b91e418c123662b47d"
|
|
33
33
|
}
|