cascade-ai 0.71.0 → 0.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -291781,7 +291781,7 @@ function reconcilePrice(model, live) {
291781
291781
  }
291782
291782
 
291783
291783
  // src/constants.ts
291784
- var CASCADE_VERSION = "0.71.0";
291784
+ var CASCADE_VERSION = "0.72.0";
291785
291785
  var CASCADE_CONFIG_DIR = ".cascade";
291786
291786
  var CASCADE_MD_FILE = "CASCADE.md";
291787
291787
  var CASCADE_IGNORE_FILE = ".cascadeignore";
@@ -323074,6 +323074,22 @@ ${assignment.expectedOutput}`;
323074
323074
  requiresArtifact() {
323075
323075
  return shouldRequireArtifact(this.assignment, this.tools.map((t4) => t4.name));
323076
323076
  }
323077
+ /**
323078
+ * Where a file a tool wrote actually lives.
323079
+ *
323080
+ * This used to be `process.cwd()`, which is only the workspace in a plain
323081
+ * CLI run. The hosted server runs with cwd at the app directory while the
323082
+ * run's workspace is the tenant's scratch dir, and Electron's cwd is the app
323083
+ * bundle rather than the folder the user picked. So the tool wrote
323084
+ * `<workspace>/report.docx`, verification stat'd `<cwd>/report.docx`, found
323085
+ * nothing, and the worker looped and then threw WorkerStallError — surfacing
323086
+ * as "no file was created" on a file that had in fact been created, followed
323087
+ * by a failed node. Asking the registry is exact: it is the same root every
323088
+ * registered tool was configured with (registry.registerDefaults).
323089
+ */
323090
+ artifactRoot() {
323091
+ return this.toolRegistry.getWorkspaceRoot?.() ?? process.cwd();
323092
+ }
323077
323093
  extractArtifactPaths(assignment) {
323078
323094
  const declared = (assignment.files ?? []).map((f4) => f4.trim()).filter((f4) => f4.includes("."));
323079
323095
  const haystack = `${assignment.description}
@@ -323085,11 +323101,11 @@ ${assignment.expectedOutput}`;
323085
323101
  const artifactPaths = this.extractArtifactPaths(assignment);
323086
323102
  if (!artifactPaths.length) return { ok: true, issues: [] };
323087
323103
  const issues = [];
323088
- const { exec: exec2 } = await import('child_process');
323104
+ const { execFile: execFile4 } = await import('child_process');
323089
323105
  const { promisify: promisify5 } = await import('util');
323090
- const execAsync2 = promisify5(exec2);
323106
+ const execFileAsync3 = promisify5(execFile4);
323091
323107
  for (const artifactPath of artifactPaths) {
323092
- const absolutePath = path28__namespace.default.resolve(process.cwd(), artifactPath);
323108
+ const absolutePath = path28__namespace.default.resolve(this.artifactRoot(), artifactPath);
323093
323109
  try {
323094
323110
  const stat3 = await fs9__namespace.default.stat(absolutePath);
323095
323111
  if (!stat3.isFile()) {
@@ -323125,20 +323141,18 @@ ${assignment.expectedOutput}`;
323125
323141
  continue;
323126
323142
  }
323127
323143
  const ext = path28__namespace.default.extname(absolutePath).toLowerCase();
323128
- try {
323129
- if (ext === ".ts" || ext === ".tsx") {
323130
- await execAsync2(`npx tsc --noEmit ${absolutePath}`, { timeout: 1e4 });
323131
- } else if (ext === ".js" || ext === ".jsx") {
323132
- await execAsync2(`node --check ${absolutePath}`, { timeout: 1e4 });
323133
- } else if (ext === ".py") {
323134
- await execAsync2(`python -m py_compile ${absolutePath}`, { timeout: 1e4 });
323144
+ const check2 = ext === ".ts" || ext === ".tsx" ? { cmd: "npx", args: ["tsc", "--noEmit", absolutePath] } : ext === ".js" || ext === ".jsx" ? { cmd: process.execPath, args: ["--check", absolutePath] } : ext === ".py" ? { cmd: "python", args: ["-m", "py_compile", absolutePath] } : null;
323145
+ if (check2) {
323146
+ try {
323147
+ await execFileAsync3(check2.cmd, check2.args, { timeout: 1e4 });
323148
+ } catch (err) {
323149
+ const code = err.code;
323150
+ if (code === "ENOENT" || code === "EINVAL") continue;
323151
+ const e3 = err;
323152
+ issues.push(`Semantic error in ${artifactPath}:
323153
+ ${e3.stderr || String(err)}
323154
+ ${e3.stdout || ""}`);
323135
323155
  }
323136
- } catch (err) {
323137
- const stderr = err?.stderr || String(err);
323138
- const stdout = err?.stdout || "";
323139
- issues.push(`Semantic error in ${artifactPath}:
323140
- ${stderr}
323141
- ${stdout}`);
323142
323156
  }
323143
323157
  } catch {
323144
323158
  issues.push(`Required artifact was not created: ${artifactPath}`);
@@ -323217,7 +323231,7 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : ""),
323217
323231
  async checkAcceptance(assignment) {
323218
323232
  const criteria = assignment.acceptance ?? [];
323219
323233
  if (!criteria.length) return [];
323220
- const resolve2 = (target) => path28__namespace.default.resolve(process.cwd(), target);
323234
+ const resolve2 = (target) => path28__namespace.default.resolve(this.artifactRoot(), target);
323221
323235
  return evaluateAcceptance(criteria, assignment.files ?? [], {
323222
323236
  stat: async (target) => {
323223
323237
  try {
@@ -355694,6 +355708,18 @@ var ToolRegistry = class extends EventEmitter__default.default {
355694
355708
  this.tools.set(tool.name, tool);
355695
355709
  this.emit("tool:added", tool.name);
355696
355710
  }
355711
+ /**
355712
+ * The directory every registered tool resolves relative paths against.
355713
+ *
355714
+ * Exposed so a caller that has to reason about a file a tool WROTE can look
355715
+ * in the same place the tool wrote it. `process.cwd()` is not that place
355716
+ * outside a plain CLI run: the hosted server's cwd is the app directory
355717
+ * while the run's workspace is the tenant's scratch dir, and Electron's cwd
355718
+ * is the app bundle rather than the user's chosen folder.
355719
+ */
355720
+ getWorkspaceRoot() {
355721
+ return this.workspaceRoot;
355722
+ }
355697
355723
  /**
355698
355724
  * Wait until a named tool is registered, resolving immediately if it already exists.
355699
355725
  * T3 workers can call this after encountering a missing-tool error to resume
package/dist/index.cjs CHANGED
@@ -1908,7 +1908,7 @@ function reconcilePrice(model, live) {
1908
1908
  }
1909
1909
 
1910
1910
  // src/constants.ts
1911
- var CASCADE_VERSION = "0.71.0";
1911
+ var CASCADE_VERSION = "0.72.0";
1912
1912
  var CASCADE_CONFIG_DIR = ".cascade";
1913
1913
  var CASCADE_MD_FILE = "CASCADE.md";
1914
1914
  var CASCADE_IGNORE_FILE = ".cascadeignore";
@@ -7298,6 +7298,22 @@ ${assignment.expectedOutput}`;
7298
7298
  requiresArtifact() {
7299
7299
  return shouldRequireArtifact(this.assignment, this.tools.map((t) => t.name));
7300
7300
  }
7301
+ /**
7302
+ * Where a file a tool wrote actually lives.
7303
+ *
7304
+ * This used to be `process.cwd()`, which is only the workspace in a plain
7305
+ * CLI run. The hosted server runs with cwd at the app directory while the
7306
+ * run's workspace is the tenant's scratch dir, and Electron's cwd is the app
7307
+ * bundle rather than the folder the user picked. So the tool wrote
7308
+ * `<workspace>/report.docx`, verification stat'd `<cwd>/report.docx`, found
7309
+ * nothing, and the worker looped and then threw WorkerStallError — surfacing
7310
+ * as "no file was created" on a file that had in fact been created, followed
7311
+ * by a failed node. Asking the registry is exact: it is the same root every
7312
+ * registered tool was configured with (registry.registerDefaults).
7313
+ */
7314
+ artifactRoot() {
7315
+ return this.toolRegistry.getWorkspaceRoot?.() ?? process.cwd();
7316
+ }
7301
7317
  extractArtifactPaths(assignment) {
7302
7318
  const declared = (assignment.files ?? []).map((f) => f.trim()).filter((f) => f.includes("."));
7303
7319
  const haystack = `${assignment.description}
@@ -7309,11 +7325,11 @@ ${assignment.expectedOutput}`;
7309
7325
  const artifactPaths = this.extractArtifactPaths(assignment);
7310
7326
  if (!artifactPaths.length) return { ok: true, issues: [] };
7311
7327
  const issues = [];
7312
- const { exec: exec2 } = await import('child_process');
7328
+ const { execFile: execFile4 } = await import('child_process');
7313
7329
  const { promisify: promisify4 } = await import('util');
7314
- const execAsync2 = promisify4(exec2);
7330
+ const execFileAsync3 = promisify4(execFile4);
7315
7331
  for (const artifactPath of artifactPaths) {
7316
- const absolutePath = path26__default.default.resolve(process.cwd(), artifactPath);
7332
+ const absolutePath = path26__default.default.resolve(this.artifactRoot(), artifactPath);
7317
7333
  try {
7318
7334
  const stat = await fs5__default.default.stat(absolutePath);
7319
7335
  if (!stat.isFile()) {
@@ -7349,20 +7365,18 @@ ${assignment.expectedOutput}`;
7349
7365
  continue;
7350
7366
  }
7351
7367
  const ext = path26__default.default.extname(absolutePath).toLowerCase();
7352
- try {
7353
- if (ext === ".ts" || ext === ".tsx") {
7354
- await execAsync2(`npx tsc --noEmit ${absolutePath}`, { timeout: 1e4 });
7355
- } else if (ext === ".js" || ext === ".jsx") {
7356
- await execAsync2(`node --check ${absolutePath}`, { timeout: 1e4 });
7357
- } else if (ext === ".py") {
7358
- await execAsync2(`python -m py_compile ${absolutePath}`, { timeout: 1e4 });
7368
+ const check = ext === ".ts" || ext === ".tsx" ? { cmd: "npx", args: ["tsc", "--noEmit", absolutePath] } : ext === ".js" || ext === ".jsx" ? { cmd: process.execPath, args: ["--check", absolutePath] } : ext === ".py" ? { cmd: "python", args: ["-m", "py_compile", absolutePath] } : null;
7369
+ if (check) {
7370
+ try {
7371
+ await execFileAsync3(check.cmd, check.args, { timeout: 1e4 });
7372
+ } catch (err) {
7373
+ const code = err.code;
7374
+ if (code === "ENOENT" || code === "EINVAL") continue;
7375
+ const e = err;
7376
+ issues.push(`Semantic error in ${artifactPath}:
7377
+ ${e.stderr || String(err)}
7378
+ ${e.stdout || ""}`);
7359
7379
  }
7360
- } catch (err) {
7361
- const stderr = err?.stderr || String(err);
7362
- const stdout = err?.stdout || "";
7363
- issues.push(`Semantic error in ${artifactPath}:
7364
- ${stderr}
7365
- ${stdout}`);
7366
7380
  }
7367
7381
  } catch {
7368
7382
  issues.push(`Required artifact was not created: ${artifactPath}`);
@@ -7441,7 +7455,7 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : ""),
7441
7455
  async checkAcceptance(assignment) {
7442
7456
  const criteria = assignment.acceptance ?? [];
7443
7457
  if (!criteria.length) return [];
7444
- const resolve2 = (target) => path26__default.default.resolve(process.cwd(), target);
7458
+ const resolve2 = (target) => path26__default.default.resolve(this.artifactRoot(), target);
7445
7459
  return evaluateAcceptance(criteria, assignment.files ?? [], {
7446
7460
  stat: async (target) => {
7447
7461
  try {
@@ -13029,6 +13043,18 @@ var ToolRegistry = class extends EventEmitter__default.default {
13029
13043
  this.tools.set(tool.name, tool);
13030
13044
  this.emit("tool:added", tool.name);
13031
13045
  }
13046
+ /**
13047
+ * The directory every registered tool resolves relative paths against.
13048
+ *
13049
+ * Exposed so a caller that has to reason about a file a tool WROTE can look
13050
+ * in the same place the tool wrote it. `process.cwd()` is not that place
13051
+ * outside a plain CLI run: the hosted server's cwd is the app directory
13052
+ * while the run's workspace is the tenant's scratch dir, and Electron's cwd
13053
+ * is the app bundle rather than the user's chosen folder.
13054
+ */
13055
+ getWorkspaceRoot() {
13056
+ return this.workspaceRoot;
13057
+ }
13032
13058
  /**
13033
13059
  * Wait until a named tool is registered, resolving immediately if it already exists.
13034
13060
  * T3 workers can call this after encountering a missing-tool error to resume