@wix/ditto-codegen-public 1.0.355 → 1.0.357

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.
@@ -2,6 +2,20 @@ import { tool } from "@opencode-ai/plugin";
2
2
  import { writeFile, mkdir } from "fs/promises";
3
3
  import { join, dirname, isAbsolute } from "path";
4
4
 
5
+ function unescapeString(str: string): string {
6
+ return str.replace(/\\(n|t|r|"|\\)/g, (_, c: string) => {
7
+ if (c === "n") return "\n";
8
+ if (c === "t") return "\t";
9
+ if (c === "r") return "\r";
10
+ if (c === '"') return '"';
11
+ return "\\";
12
+ });
13
+ }
14
+
15
+ function normalizeToolString(text: string): string {
16
+ return unescapeString(text).replace(/\r\n/g, "\n");
17
+ }
18
+
5
19
  export default tool({
6
20
  description:
7
21
  "Write multiple files at once. Creates directories as needed. " +
@@ -28,7 +42,7 @@ export default tool({
28
42
  await mkdir(dirname(fullPath), { recursive: true });
29
43
  const content =
30
44
  typeof f.content === "string"
31
- ? f.content
45
+ ? normalizeToolString(f.content)
32
46
  : JSON.stringify(f.content, null, 2);
33
47
  await writeFile(fullPath, content, "utf-8");
34
48
  results.push(`OK: ${f.path}`);
@@ -2,6 +2,20 @@ import { tool } from "@opencode-ai/plugin";
2
2
  import { readFile, writeFile } from "fs/promises";
3
3
  import { join, isAbsolute } from "path";
4
4
 
5
+ function unescapeString(str: string): string {
6
+ return str.replace(/\\(n|t|r|"|\\)/g, (_, c: string) => {
7
+ if (c === "n") return "\n";
8
+ if (c === "t") return "\t";
9
+ if (c === "r") return "\r";
10
+ if (c === '"') return '"';
11
+ return "\\";
12
+ });
13
+ }
14
+
15
+ function normalizeToolString(text: string): string {
16
+ return unescapeString(text).replace(/\r\n/g, "\n");
17
+ }
18
+
5
19
  export default tool({
6
20
  description:
7
21
  "Apply multiple find-and-replace edits across one or more files in a single call. " +
@@ -36,7 +50,9 @@ export default tool({
36
50
  : join(context.directory, e.path);
37
51
  try {
38
52
  const content = await readFile(fullPath, "utf-8");
39
- const occurrences = content.split(e.oldString).length - 1;
53
+ const oldString = normalizeToolString(e.oldString);
54
+ const newString = normalizeToolString(e.newString);
55
+ const occurrences = content.split(oldString).length - 1;
40
56
  if (occurrences === 0) {
41
57
  results.push(`FAILED: ${e.path} - oldString not found`);
42
58
  continue;
@@ -48,8 +64,8 @@ export default tool({
48
64
  continue;
49
65
  }
50
66
  const updated = e.replaceAll
51
- ? content.split(e.oldString).join(e.newString)
52
- : content.replace(e.oldString, e.newString);
67
+ ? content.split(oldString).join(newString)
68
+ : content.replace(oldString, newString);
53
69
  await writeFile(fullPath, updated, "utf-8");
54
70
  results.push(`OK: ${e.path}`);
55
71
  } catch (err) {
package/dist/out.js CHANGED
@@ -12175,7 +12175,7 @@ TOOL USAGE:
12175
12175
  - \`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.
12176
12176
  - \`batch-read\` to read N files in one call. NEVER call \`read\` more than once per turn \u2014 use batch-read instead.
12177
12177
  - \`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.
12178
- - In \`write\`/\`batch-write\` (\`content\`) and \`edit\`/\`multi-edit\` (\`newString\`) payloads, use real newlines/tabs/quotes \u2014 NEVER the two-character escape sequences \`\\n\`, \`\\t\`, or \`\\"\`. Those are written literally to disk and break \`tsc\`.
12178
+ - Tool arguments are strict JSON. For multiline strings in \`write\`, \`edit\`, \`batch-write\`, and \`multi-edit\`, use JSON escape sequences (\`\\n\`, \`\\t\`, \`\\"\`) \u2014 do NOT put raw (unescaped) newlines inside JSON string values (that breaks parsing). \`batch-write\` and \`multi-edit\` also normalize literal two-character escape sequences before writing; prefer proper JSON escapes.
12179
12179
  - 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.
12180
12180
  - Before calling MCP tools, check if loaded skills already cover the API. Only use MCP for gaps.
12181
12181
  - 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.
@@ -19497,7 +19497,8 @@ var require_skills_installer = __commonJS({
19497
19497
  "dist/opencode-integration/skills-installer.js"(exports2) {
19498
19498
  "use strict";
19499
19499
  Object.defineProperty(exports2, "__esModule", { value: true });
19500
- exports2.installSkills = installSkills;
19500
+ exports2.applySkillsOverride = applySkillsOverride;
19501
+ exports2.ensureSkillsReady = ensureSkillsReady;
19501
19502
  var fs_1 = require("fs");
19502
19503
  var path_1 = require("path");
19503
19504
  var ditto_codegen_types_12 = require_dist4();
@@ -19505,31 +19506,50 @@ var require_skills_installer = __commonJS({
19505
19506
  function hasSkills(dir) {
19506
19507
  return (0, fs_1.existsSync)(dir) && (0, fs_1.readdirSync)(dir).length > 0;
19507
19508
  }
19508
- async function installSkills(outputPath, log) {
19509
+ var delay2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
19510
+ async function applySkillsOverride(outputPath, log) {
19509
19511
  const skillsOverride = process.env.SKILLS_OVERRIDE_BRANCH;
19512
+ if (!skillsOverride) {
19513
+ return;
19514
+ }
19515
+ try {
19516
+ const overrides = (0, skills_override_1.parseSkillsOverrides)(skillsOverride);
19517
+ await (0, skills_override_1.overrideSkills)(overrides, outputPath, log);
19518
+ } catch (error) {
19519
+ const errorMessage = error instanceof Error ? error.message : String(error);
19520
+ log.error("[Skills] Branch override failed", { error: errorMessage });
19521
+ throw new ditto_codegen_types_12.ProcessExecutionError("Failed to apply SKILLS_OVERRIDE_BRANCH", {
19522
+ processType: ditto_codegen_types_12.ProcessType.INITIALIZATION,
19523
+ cause: error
19524
+ });
19525
+ }
19526
+ }
19527
+ async function ensureSkillsReady(outputPath, log, { timeoutMs = 6e4, intervalMs = 1e3 } = {}) {
19510
19528
  const projectSkillsDir = (0, path_1.join)(outputPath, ".agents", "skills");
19511
- const isPreInstalled = hasSkills(skills_override_1.SKILLS_DIR) || hasSkills(projectSkillsDir);
19512
- if (isPreInstalled && !skillsOverride) {
19513
- log.info("[Skills] Skipping runtime skills installation (pre-installed via Docker image)", { environment: process.env.CODEGEN_ENVIRONMENT });
19529
+ const skillsPresent = () => hasSkills(skills_override_1.SKILLS_DIR) || hasSkills(projectSkillsDir);
19530
+ if (skillsPresent()) {
19514
19531
  return;
19515
19532
  }
19516
- if (skillsOverride) {
19517
- try {
19518
- const overrides = (0, skills_override_1.parseSkillsOverrides)(skillsOverride);
19519
- await (0, skills_override_1.overrideSkills)(overrides, outputPath, log);
19533
+ log.info("[Skills] Not present yet \u2014 waiting for the startup install", {
19534
+ globalSkillsDir: skills_override_1.SKILLS_DIR,
19535
+ projectSkillsDir,
19536
+ timeoutMs
19537
+ });
19538
+ const deadline = Date.now() + timeoutMs;
19539
+ while (Date.now() < deadline) {
19540
+ await delay2(intervalMs);
19541
+ if (skillsPresent()) {
19542
+ log.info("[Skills] Skills became available");
19520
19543
  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
19544
  }
19526
19545
  }
19527
- log.error("[Skills] No skills available \u2014 pre-install missing and no override", {
19546
+ log.error("[Skills] No skills available after waiting", {
19528
19547
  globalSkillsDir: skills_override_1.SKILLS_DIR,
19529
19548
  projectSkillsDir,
19530
- environment: process.env.CODEGEN_ENVIRONMENT
19549
+ environment: process.env.CODEGEN_ENVIRONMENT,
19550
+ timeoutMs
19531
19551
  });
19532
- throw new ditto_codegen_types_12.ProcessExecutionError("Skills not pre-installed and no SKILLS_OVERRIDE_BRANCH set \u2014 verify the Docker image bake-time install ran successfully.", { processType: ditto_codegen_types_12.ProcessType.INITIALIZATION });
19552
+ 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
19553
  }
19534
19554
  }
19535
19555
  });
@@ -19684,7 +19704,7 @@ async function initOpenCode() {
19684
19704
  await Promise.all([
19685
19705
  (0, rules_writer_1.writeRuleFiles)([...envConfig.codegenRules, ...pluginArtifacts.rules]),
19686
19706
  (0, rules_writer_1.writeRuleFiles)(envConfig.askRules),
19687
- (0, skills_installer_1.installSkills)((0, codegen_flow_helpers_1.getOutputPath)(), logger_1.logger),
19707
+ (0, skills_installer_1.applySkillsOverride)((0, codegen_flow_helpers_1.getOutputPath)(), logger_1.logger),
19688
19708
  (0, tools_writer_1.writeToolFiles)(pluginArtifacts.tools)
19689
19709
  ]);
19690
19710
  }
@@ -19765,6 +19785,7 @@ async function processJob(job) {
19765
19785
  keys: Object.keys(agentData)
19766
19786
  });
19767
19787
  }
19788
+ await (0, skills_installer_1.ensureSkillsReady)((0, codegen_flow_helpers_1.getOutputPath)(), logger_1.logger);
19768
19789
  if (task.kind === CodeGenService_1.TaskKind.ASK_CODEGEN) {
19769
19790
  await (0, opencode_ask_1.runOpencodeAskFlow)(history);
19770
19791
  } 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.355",
3
+ "version": "1.0.357",
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": "dd6728e78e15bfd74a1b9833c183856688581fdb5c38a7c055f003e6"
32
+ "falconPackageHash": "236fead8ed789d2e79367a542151458b9890fc135b057e67784bb6f9"
33
33
  }