@wix/ditto-codegen-public 1.0.356 → 1.0.358
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/wix-generate.ts +130 -0
- package/dist/out.js +39 -17
- package/package.json +2 -2
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin";
|
|
2
|
+
import { readFile } from "fs/promises";
|
|
3
|
+
import { join, isAbsolute, relative } from "path";
|
|
4
|
+
|
|
5
|
+
// `wix generate --params <json>` prints one JSON line to stdout (`--params` implies
|
|
6
|
+
// `--json`; see wix-cli commands/generate.tsx). We only depend on `newFiles`; any
|
|
7
|
+
// other shape is treated as a failure and surfaced to the agent verbatim.
|
|
8
|
+
interface GenerateResult {
|
|
9
|
+
success: boolean;
|
|
10
|
+
extensionType?: string;
|
|
11
|
+
newFiles?: string[];
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function asResult(raw: string): GenerateResult | null {
|
|
16
|
+
try {
|
|
17
|
+
const parsed = JSON.parse(raw);
|
|
18
|
+
return parsed && typeof parsed === "object" && "success" in parsed
|
|
19
|
+
? (parsed as GenerateResult)
|
|
20
|
+
: null;
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Extract the JSON result object from stdout. The CLI prints the result as a
|
|
27
|
+
// single JSON line, but may surround it with unrelated lines (e.g. an npm
|
|
28
|
+
// "Update available" notice box), so we can't assume the whole output is JSON:
|
|
29
|
+
// try the whole output first, then fall back to scanning individual lines.
|
|
30
|
+
function parseGenerateOutput(stdout: string): GenerateResult | null {
|
|
31
|
+
const whole = asResult(stdout.trim());
|
|
32
|
+
if (whole) return whole;
|
|
33
|
+
|
|
34
|
+
for (const line of stdout.split("\n")) {
|
|
35
|
+
const result = asResult(line.trim());
|
|
36
|
+
if (result) return result;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default tool({
|
|
43
|
+
description:
|
|
44
|
+
"Scaffold one or more Wix extensions non-interactively via `wix generate --params`. " +
|
|
45
|
+
"The Wix CLI writes the boilerplate (extension file, config, and registration) " +
|
|
46
|
+
"deterministically, and this tool returns the full contents of every file it created " +
|
|
47
|
+
"so you can edit them directly WITHOUT reading them back. Strongly prefer this over " +
|
|
48
|
+
"hand-writing extension boilerplate.",
|
|
49
|
+
args: {
|
|
50
|
+
extensions: tool.schema
|
|
51
|
+
.array(
|
|
52
|
+
tool.schema.object({
|
|
53
|
+
params: tool.schema
|
|
54
|
+
.object({
|
|
55
|
+
extensionType: tool.schema
|
|
56
|
+
.string()
|
|
57
|
+
.describe("The extension type to generate."),
|
|
58
|
+
})
|
|
59
|
+
.passthrough()
|
|
60
|
+
.describe(
|
|
61
|
+
"The `wix generate --params` config object: `extensionType` plus the " +
|
|
62
|
+
"type-specific fields (e.g. a DATA_COLLECTION needs `collectionName`, an " +
|
|
63
|
+
"EVENT needs an event identifier). Discover the exact fields for each type " +
|
|
64
|
+
"via the wix-app skill or `wix schema generate`.",
|
|
65
|
+
),
|
|
66
|
+
}),
|
|
67
|
+
)
|
|
68
|
+
.describe(
|
|
69
|
+
"The extensions to scaffold. Each entry runs one `wix generate --params` call; " +
|
|
70
|
+
"pass several to scaffold them in a single tool call.",
|
|
71
|
+
),
|
|
72
|
+
},
|
|
73
|
+
async execute(args, context) {
|
|
74
|
+
const cwd = context.directory;
|
|
75
|
+
const blocks: string[] = [];
|
|
76
|
+
|
|
77
|
+
for (const { params } of args.extensions) {
|
|
78
|
+
const type =
|
|
79
|
+
typeof params.extensionType === "string" ? params.extensionType : "?";
|
|
80
|
+
|
|
81
|
+
const res = await Bun.$`npx wix generate --params ${JSON.stringify(params)}`
|
|
82
|
+
.cwd(cwd)
|
|
83
|
+
.nothrow()
|
|
84
|
+
.quiet();
|
|
85
|
+
|
|
86
|
+
const stdout = res.stdout.toString();
|
|
87
|
+
const result = parseGenerateOutput(stdout);
|
|
88
|
+
|
|
89
|
+
// No recognizable `--json` result line: the CLI's output contract likely
|
|
90
|
+
// changed. A format change breaks every extension equally, so don't emit
|
|
91
|
+
// per-extension FAILED noise — abort the batch with one message telling the
|
|
92
|
+
// agent to fall back to running `wix generate` itself via bash.
|
|
93
|
+
if (!result) {
|
|
94
|
+
return [
|
|
95
|
+
"=== wix-generate could not read `wix generate` output ===",
|
|
96
|
+
"`wix generate --params` did not return its expected JSON result, so this " +
|
|
97
|
+
"tool can't extract the created files (the CLI output format may have " +
|
|
98
|
+
"changed). Fall back to the bash tool: run " +
|
|
99
|
+
"`npx wix generate --params '<params-json>'` for each extension yourself, " +
|
|
100
|
+
"then read the files it creates.",
|
|
101
|
+
"",
|
|
102
|
+
`Raw output (exit ${res.exitCode}):`,
|
|
103
|
+
stdout.trim() || res.stderr.toString().trim() || "(no output)",
|
|
104
|
+
].join("\n");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const newFiles = result.success ? result.newFiles : undefined;
|
|
108
|
+
|
|
109
|
+
if (!newFiles?.length) {
|
|
110
|
+
const detail =
|
|
111
|
+
result.error ||
|
|
112
|
+
res.stderr.toString().trim() ||
|
|
113
|
+
stdout.trim() ||
|
|
114
|
+
"(no output)";
|
|
115
|
+
blocks.push(`=== FAILED: ${type} (exit ${res.exitCode}) ===\n${detail}`);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const files = await Promise.all(
|
|
120
|
+
newFiles.map(async (file) => {
|
|
121
|
+
const abs = isAbsolute(file) ? file : join(cwd, file);
|
|
122
|
+
return `--- ${relative(cwd, abs)} ---\n${await readFile(abs, "utf-8")}`;
|
|
123
|
+
}),
|
|
124
|
+
);
|
|
125
|
+
blocks.push(`=== ${result.extensionType ?? type} ===\n${files.join("\n\n")}`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return blocks.join("\n\n");
|
|
129
|
+
},
|
|
130
|
+
});
|
package/dist/out.js
CHANGED
|
@@ -12170,6 +12170,7 @@ TOOL USAGE:
|
|
|
12170
12170
|
- "Building project"
|
|
12171
12171
|
- \`validate\` for all validation (tsc + build).
|
|
12172
12172
|
- \`uuid\` to generate UUIDs (supports count param for multiple). Do NOT use bash.
|
|
12173
|
+
- \`wix-generate\` to scaffold extensions non-interactively (wraps \`wix generate --params\`). Prefer it over hand-writing extension boilerplate. It RETURNS the full contents of every file the CLI created, so trust that output and do NOT \`read\`/\`batch-read\` those files afterward. If it returns a \`FAILED\` block, fix the params per the error and retry. Pass an array to scaffold several extensions in one call.
|
|
12173
12174
|
- \`required-permissions\` to declare the Wix app permissions the generated code needs. Call it ONCE at the end, and ONLY if permissions are actually needed \u2014 don't call it otherwise (see PERMISSIONS).
|
|
12174
12175
|
- File operations \u2014 pick the BATCH tool whenever you have 2+ files; the single-file variants are 5\u201310\xD7 slower:
|
|
12175
12176
|
- \`batch-write\` to create N new files in one call. NEVER call \`write\` more than once per turn \u2014 use batch-write instead. \`write\` is reserved for single-file creation.
|
|
@@ -19497,7 +19498,8 @@ var require_skills_installer = __commonJS({
|
|
|
19497
19498
|
"dist/opencode-integration/skills-installer.js"(exports2) {
|
|
19498
19499
|
"use strict";
|
|
19499
19500
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
19500
|
-
exports2.
|
|
19501
|
+
exports2.applySkillsOverride = applySkillsOverride;
|
|
19502
|
+
exports2.ensureSkillsReady = ensureSkillsReady;
|
|
19501
19503
|
var fs_1 = require("fs");
|
|
19502
19504
|
var path_1 = require("path");
|
|
19503
19505
|
var ditto_codegen_types_12 = require_dist4();
|
|
@@ -19505,31 +19507,50 @@ var require_skills_installer = __commonJS({
|
|
|
19505
19507
|
function hasSkills(dir) {
|
|
19506
19508
|
return (0, fs_1.existsSync)(dir) && (0, fs_1.readdirSync)(dir).length > 0;
|
|
19507
19509
|
}
|
|
19508
|
-
|
|
19510
|
+
var delay2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
19511
|
+
async function applySkillsOverride(outputPath, log) {
|
|
19509
19512
|
const skillsOverride = process.env.SKILLS_OVERRIDE_BRANCH;
|
|
19513
|
+
if (!skillsOverride) {
|
|
19514
|
+
return;
|
|
19515
|
+
}
|
|
19516
|
+
try {
|
|
19517
|
+
const overrides = (0, skills_override_1.parseSkillsOverrides)(skillsOverride);
|
|
19518
|
+
await (0, skills_override_1.overrideSkills)(overrides, outputPath, log);
|
|
19519
|
+
} catch (error) {
|
|
19520
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
19521
|
+
log.error("[Skills] Branch override failed", { error: errorMessage });
|
|
19522
|
+
throw new ditto_codegen_types_12.ProcessExecutionError("Failed to apply SKILLS_OVERRIDE_BRANCH", {
|
|
19523
|
+
processType: ditto_codegen_types_12.ProcessType.INITIALIZATION,
|
|
19524
|
+
cause: error
|
|
19525
|
+
});
|
|
19526
|
+
}
|
|
19527
|
+
}
|
|
19528
|
+
async function ensureSkillsReady(outputPath, log, { timeoutMs = 6e4, intervalMs = 1e3 } = {}) {
|
|
19510
19529
|
const projectSkillsDir = (0, path_1.join)(outputPath, ".agents", "skills");
|
|
19511
|
-
const
|
|
19512
|
-
if (
|
|
19513
|
-
log.info("[Skills] Skipping runtime skills installation (pre-installed via Docker image)", { environment: process.env.CODEGEN_ENVIRONMENT });
|
|
19530
|
+
const skillsPresent = () => hasSkills(skills_override_1.SKILLS_DIR) || hasSkills(projectSkillsDir);
|
|
19531
|
+
if (skillsPresent()) {
|
|
19514
19532
|
return;
|
|
19515
19533
|
}
|
|
19516
|
-
|
|
19517
|
-
|
|
19518
|
-
|
|
19519
|
-
|
|
19534
|
+
log.info("[Skills] Not present yet \u2014 waiting for the startup install", {
|
|
19535
|
+
globalSkillsDir: skills_override_1.SKILLS_DIR,
|
|
19536
|
+
projectSkillsDir,
|
|
19537
|
+
timeoutMs
|
|
19538
|
+
});
|
|
19539
|
+
const deadline = Date.now() + timeoutMs;
|
|
19540
|
+
while (Date.now() < deadline) {
|
|
19541
|
+
await delay2(intervalMs);
|
|
19542
|
+
if (skillsPresent()) {
|
|
19543
|
+
log.info("[Skills] Skills became available");
|
|
19520
19544
|
return;
|
|
19521
|
-
} catch (error) {
|
|
19522
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
19523
|
-
log.error("[Skills] Branch override failed", { error: errorMessage });
|
|
19524
|
-
throw new ditto_codegen_types_12.ProcessExecutionError(isPreInstalled ? "Failed to override pre-installed skills" : "Skills override failed and no pre-installed skills available", { processType: ditto_codegen_types_12.ProcessType.INITIALIZATION, cause: error });
|
|
19525
19545
|
}
|
|
19526
19546
|
}
|
|
19527
|
-
log.error("[Skills] No skills available
|
|
19547
|
+
log.error("[Skills] No skills available after waiting", {
|
|
19528
19548
|
globalSkillsDir: skills_override_1.SKILLS_DIR,
|
|
19529
19549
|
projectSkillsDir,
|
|
19530
|
-
environment: process.env.CODEGEN_ENVIRONMENT
|
|
19550
|
+
environment: process.env.CODEGEN_ENVIRONMENT,
|
|
19551
|
+
timeoutMs
|
|
19531
19552
|
});
|
|
19532
|
-
throw new ditto_codegen_types_12.ProcessExecutionError("Skills not
|
|
19553
|
+
throw new ditto_codegen_types_12.ProcessExecutionError("Skills not available \u2014 verify the install-skills step (codegen-install --phase startup) ran and populated /root/.agents/skills.", { processType: ditto_codegen_types_12.ProcessType.INITIALIZATION });
|
|
19533
19554
|
}
|
|
19534
19555
|
}
|
|
19535
19556
|
});
|
|
@@ -19684,7 +19705,7 @@ async function initOpenCode() {
|
|
|
19684
19705
|
await Promise.all([
|
|
19685
19706
|
(0, rules_writer_1.writeRuleFiles)([...envConfig.codegenRules, ...pluginArtifacts.rules]),
|
|
19686
19707
|
(0, rules_writer_1.writeRuleFiles)(envConfig.askRules),
|
|
19687
|
-
(0, skills_installer_1.
|
|
19708
|
+
(0, skills_installer_1.applySkillsOverride)((0, codegen_flow_helpers_1.getOutputPath)(), logger_1.logger),
|
|
19688
19709
|
(0, tools_writer_1.writeToolFiles)(pluginArtifacts.tools)
|
|
19689
19710
|
]);
|
|
19690
19711
|
}
|
|
@@ -19765,6 +19786,7 @@ async function processJob(job) {
|
|
|
19765
19786
|
keys: Object.keys(agentData)
|
|
19766
19787
|
});
|
|
19767
19788
|
}
|
|
19789
|
+
await (0, skills_installer_1.ensureSkillsReady)((0, codegen_flow_helpers_1.getOutputPath)(), logger_1.logger);
|
|
19768
19790
|
if (task.kind === CodeGenService_1.TaskKind.ASK_CODEGEN) {
|
|
19769
19791
|
await (0, opencode_ask_1.runOpencodeAskFlow)(history);
|
|
19770
19792
|
} else if (task.kind === CodeGenService_1.TaskKind.ITERATE_CODEGEN) {
|
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.358",
|
|
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": "d71ce4d5b338ba060f5d9cf26324f43ddd3dae5b5120be5e30903e01"
|
|
33
33
|
}
|