@wix/ditto-codegen-public 1.0.326 → 1.0.328
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/multi-edit.ts +62 -0
- package/dist/opencode-tools/validate.ts +22 -3
- package/dist/out.js +59 -17
- package/package.json +2 -2
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin";
|
|
2
|
+
import { readFile, writeFile } from "fs/promises";
|
|
3
|
+
import { join, isAbsolute } from "path";
|
|
4
|
+
|
|
5
|
+
export default tool({
|
|
6
|
+
description:
|
|
7
|
+
"Apply multiple find-and-replace edits across one or more files in a single call. " +
|
|
8
|
+
"Use this instead of calling edit multiple times. Each edit replaces oldString with newString " +
|
|
9
|
+
"in the named file. If oldString appears more than once and replaceAll is false, the edit fails — " +
|
|
10
|
+
"include more context in oldString to make it unique, or set replaceAll: true.",
|
|
11
|
+
args: {
|
|
12
|
+
edits: tool.schema
|
|
13
|
+
.array(
|
|
14
|
+
tool.schema.object({
|
|
15
|
+
path: tool.schema
|
|
16
|
+
.string()
|
|
17
|
+
.describe("File path relative to project root"),
|
|
18
|
+
oldString: tool.schema
|
|
19
|
+
.string()
|
|
20
|
+
.min(1)
|
|
21
|
+
.describe("Exact string to find. Must be unique unless replaceAll is true."),
|
|
22
|
+
newString: tool.schema.string().describe("Replacement string"),
|
|
23
|
+
replaceAll: tool.schema
|
|
24
|
+
.boolean()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("Replace every occurrence (default: false)"),
|
|
27
|
+
}),
|
|
28
|
+
)
|
|
29
|
+
.describe("Array of edits to apply in order"),
|
|
30
|
+
},
|
|
31
|
+
async execute(args, context) {
|
|
32
|
+
const results: string[] = [];
|
|
33
|
+
for (const e of args.edits) {
|
|
34
|
+
const fullPath = isAbsolute(e.path)
|
|
35
|
+
? e.path
|
|
36
|
+
: join(context.directory, e.path);
|
|
37
|
+
try {
|
|
38
|
+
const content = await readFile(fullPath, "utf-8");
|
|
39
|
+
const occurrences = content.split(e.oldString).length - 1;
|
|
40
|
+
if (occurrences === 0) {
|
|
41
|
+
results.push(`FAILED: ${e.path} - oldString not found`);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (occurrences > 1 && !e.replaceAll) {
|
|
45
|
+
results.push(
|
|
46
|
+
`FAILED: ${e.path} - oldString appears ${occurrences} times; pass replaceAll: true or include more surrounding context`,
|
|
47
|
+
);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const updated = e.replaceAll
|
|
51
|
+
? content.split(e.oldString).join(e.newString)
|
|
52
|
+
: content.replace(e.oldString, e.newString);
|
|
53
|
+
await writeFile(fullPath, updated, "utf-8");
|
|
54
|
+
results.push(`OK: ${e.path}`);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
57
|
+
results.push(`FAILED: ${e.path} - ${msg}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return results.join("\n");
|
|
61
|
+
},
|
|
62
|
+
});
|
|
@@ -2,14 +2,25 @@ import { tool } from "@opencode-ai/plugin";
|
|
|
2
2
|
|
|
3
3
|
export default tool({
|
|
4
4
|
description:
|
|
5
|
-
"Run
|
|
5
|
+
"Run project validation: TypeScript check by default, optionally a full build. " +
|
|
6
6
|
"Use this instead of running npm install, tsc, and wix build separately.",
|
|
7
7
|
args: {
|
|
8
8
|
installDeps: tool.schema
|
|
9
9
|
.boolean()
|
|
10
10
|
.optional()
|
|
11
11
|
.describe(
|
|
12
|
-
"
|
|
12
|
+
"Default false. Only set true when package.json changed in this iteration " +
|
|
13
|
+
"(added, removed, or upgraded a dependency). node_modules is pre-populated " +
|
|
14
|
+
"in the image, so installs are unnecessary otherwise.",
|
|
15
|
+
),
|
|
16
|
+
runBuild: tool.schema
|
|
17
|
+
.boolean()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe(
|
|
20
|
+
"Default false. Set true ONLY on the final validation pass after tsc " +
|
|
21
|
+
"succeeds to run `wix build` and verify the project builds end-to-end. " +
|
|
22
|
+
"`wix build` is slow (~20s); omitting it on intermediate iterations keeps " +
|
|
23
|
+
"the edit-validate loop fast.",
|
|
13
24
|
),
|
|
14
25
|
},
|
|
15
26
|
async execute(args, context) {
|
|
@@ -17,7 +28,10 @@ export default tool({
|
|
|
17
28
|
const cwd = context.directory;
|
|
18
29
|
|
|
19
30
|
if (args.installDeps) {
|
|
20
|
-
const install = await Bun.$`npm install
|
|
31
|
+
const install = await Bun.$`npm install --no-audit --no-fund`
|
|
32
|
+
.cwd(cwd)
|
|
33
|
+
.nothrow()
|
|
34
|
+
.quiet();
|
|
21
35
|
if (install.exitCode !== 0) {
|
|
22
36
|
return `FAILED at npm install (exit ${install.exitCode}):\n${install.stderr.toString()}`;
|
|
23
37
|
}
|
|
@@ -35,6 +49,11 @@ export default tool({
|
|
|
35
49
|
}
|
|
36
50
|
steps.push("tsc --noEmit: OK");
|
|
37
51
|
|
|
52
|
+
if (!args.runBuild) {
|
|
53
|
+
steps.push("wix build: skipped (pass runBuild: true to verify build)");
|
|
54
|
+
return steps.join("\n");
|
|
55
|
+
}
|
|
56
|
+
|
|
38
57
|
const build = await Bun.$`npx wix build`.cwd(cwd).nothrow().quiet();
|
|
39
58
|
if (build.exitCode !== 0) {
|
|
40
59
|
return [
|
package/dist/out.js
CHANGED
|
@@ -11701,7 +11701,8 @@ var require_constants5 = __commonJS({
|
|
|
11701
11701
|
exports2.WRITE_TOOLS = /* @__PURE__ */ new Set([
|
|
11702
11702
|
"write",
|
|
11703
11703
|
"edit",
|
|
11704
|
-
"batch-write"
|
|
11704
|
+
"batch-write",
|
|
11705
|
+
"multi-edit"
|
|
11705
11706
|
]);
|
|
11706
11707
|
exports2.BUILDER_TO_EXTENSION_LABEL = {
|
|
11707
11708
|
dashboardPage: "dashboard page",
|
|
@@ -11867,23 +11868,25 @@ MINIMIZE TEXT OUTPUT \u2014 CRITICAL:
|
|
|
11867
11868
|
TOOL USAGE:
|
|
11868
11869
|
- \`validate\` for all validation (tsc + build).
|
|
11869
11870
|
- \`uuid\` to generate UUIDs (supports count param for multiple). Do NOT use bash.
|
|
11870
|
-
-
|
|
11871
|
-
- \`batch-
|
|
11872
|
-
- \`
|
|
11871
|
+
- File operations \u2014 pick the BATCH tool whenever you have 2+ files; the single-file variants are 5\u201310\xD7 slower:
|
|
11872
|
+
- \`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.
|
|
11873
|
+
- \`batch-read\` to read N files in one call. NEVER call \`read\` more than once per turn \u2014 use batch-read instead.
|
|
11874
|
+
- \`multi-edit\` to apply N find-and-replace edits across one or more files in one call. NEVER call \`edit\` more than once per turn \u2014 use multi-edit instead. \`edit\` is reserved for a single edit to one file.
|
|
11875
|
+
- For tools where no batch variant exists (e.g. \`grep\`, \`glob\`), still emit MULTIPLE \`tool_use\` blocks in a SINGLE response when the calls are independent. Sequential turns waste a model round-trip per call.
|
|
11873
11876
|
- Before calling MCP tools, check if loaded skills already cover the API. Only use MCP for gaps.
|
|
11874
11877
|
- When using MCP to look up a Wix SDK method, ALWAYS call \`ReadFullDocsMethodSchema\` (not just \`ReadFullDocsArticle\`). The schema is the source of truth for parameter shapes. Code examples in docs may use incorrect call signatures.
|
|
11875
11878
|
- NEVER run preview, dev, release, or promote commands.
|
|
11876
11879
|
|
|
11877
11880
|
IMPLEMENTATION WORKFLOW:
|
|
11878
11881
|
1. **Plan**: Determine extension types using the \`wix-app\` skill. Generate ALL UUIDs upfront.
|
|
11879
|
-
2. **Build**: Create
|
|
11882
|
+
2. **Build**: Create every extension file in a SINGLE \`batch-write\` call. Build all extensions before registering.
|
|
11880
11883
|
3. **Register**: Register all extensions in \`src/extensions.ts\`.
|
|
11881
|
-
4. **Validate**: Run \`validate\`
|
|
11884
|
+
4. **Validate**: Run \`validate\` (typecheck only). Fix any errors and re-validate until tsc passes. Then run \`validate({ runBuild: true })\` ONCE to verify the build. Pass \`installDeps: true\` ONLY when you added a new dependency to package.json in this iteration; otherwise omit it (node_modules is pre-installed).
|
|
11882
11885
|
5. **Stop**: Once validation passes, STOP. Do NOT refactor, clean up, or verify.
|
|
11883
11886
|
|
|
11884
11887
|
EFFICIENCY:
|
|
11885
|
-
-
|
|
11886
|
-
-
|
|
11888
|
+
- Always prefer the BATCH variant: \`batch-write\` over multiple \`write\`s, \`batch-read\` over multiple \`read\`s, \`multi-edit\` over multiple \`edit\`s.
|
|
11889
|
+
- When fixing type errors across N files, use ONE \`multi-edit\` call with all N edits.
|
|
11887
11890
|
|
|
11888
11891
|
FILE CREATION:
|
|
11889
11892
|
- NEVER rewrite the same file twice. Once written, move on.
|
|
@@ -13027,6 +13030,10 @@ var require_config = __commonJS({
|
|
|
13027
13030
|
"batch-write"
|
|
13028
13031
|
/* OpenCodeTool.BatchWrite */
|
|
13029
13032
|
]: "deny",
|
|
13033
|
+
[
|
|
13034
|
+
"multi-edit"
|
|
13035
|
+
/* OpenCodeTool.MultiEdit */
|
|
13036
|
+
]: "deny",
|
|
13030
13037
|
[
|
|
13031
13038
|
"validate"
|
|
13032
13039
|
/* OpenCodeTool.Validate */
|
|
@@ -13148,6 +13155,16 @@ var require_parser = __commonJS({
|
|
|
13148
13155
|
}
|
|
13149
13156
|
const tool = event.part.tool;
|
|
13150
13157
|
const metadata = event.part.state.metadata;
|
|
13158
|
+
if (tool === "batch-write") {
|
|
13159
|
+
for (const f of event.part.state.input?.files ?? []) {
|
|
13160
|
+
addFileChange(f.path, ditto_codegen_types_12.ExtensionGenerationOperation.INSERT);
|
|
13161
|
+
}
|
|
13162
|
+
}
|
|
13163
|
+
if (tool === "multi-edit") {
|
|
13164
|
+
for (const e of event.part.state.input?.edits ?? []) {
|
|
13165
|
+
addFileChange(e.path, ditto_codegen_types_12.ExtensionGenerationOperation.EDIT);
|
|
13166
|
+
}
|
|
13167
|
+
}
|
|
13151
13168
|
const operation = (0, constants_1.resolveFileOperation)(tool, metadata);
|
|
13152
13169
|
if (operation) {
|
|
13153
13170
|
const filePath = event.part.state.input?.filePath;
|
|
@@ -13259,6 +13276,9 @@ var require_parser = __commonJS({
|
|
|
13259
13276
|
if (input.files) {
|
|
13260
13277
|
return { files: input.files.map(({ path }) => ({ path })) };
|
|
13261
13278
|
}
|
|
13279
|
+
if (input.edits) {
|
|
13280
|
+
return { edits: input.edits.map(({ path }) => ({ path })) };
|
|
13281
|
+
}
|
|
13262
13282
|
if (input.filePath)
|
|
13263
13283
|
return { filePath: input.filePath };
|
|
13264
13284
|
return {
|
|
@@ -13675,9 +13695,8 @@ var require_task_tracker = __commonJS({
|
|
|
13675
13695
|
}
|
|
13676
13696
|
async handleWriteEvent(tool, state) {
|
|
13677
13697
|
const isCompleted = state.status === "completed";
|
|
13678
|
-
const
|
|
13679
|
-
const
|
|
13680
|
-
for (const fileState of fileStates) {
|
|
13698
|
+
const expanded = this.expandWriteEvent(tool, state);
|
|
13699
|
+
for (const { state: fileState, effectiveTool } of expanded) {
|
|
13681
13700
|
if (isCompleted) {
|
|
13682
13701
|
this.trackFileChange(effectiveTool, fileState);
|
|
13683
13702
|
}
|
|
@@ -13685,12 +13704,35 @@ var require_task_tracker = __commonJS({
|
|
|
13685
13704
|
await this.extensionHandler.handle(effectiveTool, fileState, ctx);
|
|
13686
13705
|
}
|
|
13687
13706
|
}
|
|
13688
|
-
|
|
13689
|
-
|
|
13690
|
-
|
|
13691
|
-
|
|
13692
|
-
|
|
13693
|
-
|
|
13707
|
+
/**
|
|
13708
|
+
* Expands a write-family tool event into per-file synthetic states so the
|
|
13709
|
+
* downstream extension/file-change collectors can stay tool-agnostic:
|
|
13710
|
+
* batch-write → N synthetic Write states (INSERT, exists=false)
|
|
13711
|
+
* multi-edit → N synthetic Edit states (EDIT)
|
|
13712
|
+
* write/edit → passed through unchanged
|
|
13713
|
+
*/
|
|
13714
|
+
expandWriteEvent(tool, state) {
|
|
13715
|
+
if (tool === "batch-write") {
|
|
13716
|
+
return (state.input?.files ?? []).map((f) => ({
|
|
13717
|
+
state: {
|
|
13718
|
+
status: state.status,
|
|
13719
|
+
input: { filePath: f.path, content: f.content },
|
|
13720
|
+
metadata: { exists: false }
|
|
13721
|
+
},
|
|
13722
|
+
effectiveTool: "write"
|
|
13723
|
+
}));
|
|
13724
|
+
}
|
|
13725
|
+
if (tool === "multi-edit") {
|
|
13726
|
+
return (state.input?.edits ?? []).map((e) => ({
|
|
13727
|
+
state: {
|
|
13728
|
+
status: state.status,
|
|
13729
|
+
input: { filePath: e.path, new_string: e.newString },
|
|
13730
|
+
metadata: { exists: true }
|
|
13731
|
+
},
|
|
13732
|
+
effectiveTool: "edit"
|
|
13733
|
+
}));
|
|
13734
|
+
}
|
|
13735
|
+
return [{ state, effectiveTool: tool }];
|
|
13694
13736
|
}
|
|
13695
13737
|
trackFileChange(tool, state) {
|
|
13696
13738
|
const filePath = state.input?.filePath || state.title;
|
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.328",
|
|
4
4
|
"description": "AI-powered Wix CLI app generator - standalone executable",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "node build.mjs",
|
|
@@ -28,5 +28,5 @@
|
|
|
28
28
|
"esbuild": "^0.27.2",
|
|
29
29
|
"vitest": "^4.0.16"
|
|
30
30
|
},
|
|
31
|
-
"falconPackageHash": "
|
|
31
|
+
"falconPackageHash": "ed409314fc563dc19a80a0ebec8e4d38b6300689696888f753f8e26d"
|
|
32
32
|
}
|