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.
package/dist/cli.cjs CHANGED
@@ -1810,7 +1810,7 @@ var CASCADE_VERSION, CASCADE_CONFIG_FILE, CASCADE_DB_FILE, CASCADE_DASHBOARD_SEC
1810
1810
  var init_constants = __esm({
1811
1811
  "src/constants.ts"() {
1812
1812
  init_pricing();
1813
- CASCADE_VERSION = "0.71.0";
1813
+ CASCADE_VERSION = "0.72.0";
1814
1814
  CASCADE_CONFIG_FILE = ".cascade/config.json";
1815
1815
  CASCADE_DB_FILE = ".cascade/memory.db";
1816
1816
  CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
@@ -9874,6 +9874,22 @@ ${assignment.expectedOutput}`;
9874
9874
  requiresArtifact() {
9875
9875
  return shouldRequireArtifact(this.assignment, this.tools.map((t) => t.name));
9876
9876
  }
9877
+ /**
9878
+ * Where a file a tool wrote actually lives.
9879
+ *
9880
+ * This used to be `process.cwd()`, which is only the workspace in a plain
9881
+ * CLI run. The hosted server runs with cwd at the app directory while the
9882
+ * run's workspace is the tenant's scratch dir, and Electron's cwd is the app
9883
+ * bundle rather than the folder the user picked. So the tool wrote
9884
+ * `<workspace>/report.docx`, verification stat'd `<cwd>/report.docx`, found
9885
+ * nothing, and the worker looped and then threw WorkerStallError — surfacing
9886
+ * as "no file was created" on a file that had in fact been created, followed
9887
+ * by a failed node. Asking the registry is exact: it is the same root every
9888
+ * registered tool was configured with (registry.registerDefaults).
9889
+ */
9890
+ artifactRoot() {
9891
+ return this.toolRegistry.getWorkspaceRoot?.() ?? process.cwd();
9892
+ }
9877
9893
  extractArtifactPaths(assignment) {
9878
9894
  const declared = (assignment.files ?? []).map((f) => f.trim()).filter((f) => f.includes("."));
9879
9895
  const haystack = `${assignment.description}
@@ -9885,11 +9901,11 @@ ${assignment.expectedOutput}`;
9885
9901
  const artifactPaths = this.extractArtifactPaths(assignment);
9886
9902
  if (!artifactPaths.length) return { ok: true, issues: [] };
9887
9903
  const issues = [];
9888
- const { exec: exec3 } = await import('child_process');
9904
+ const { execFile: execFile3 } = await import('child_process');
9889
9905
  const { promisify: promisify4 } = await import('util');
9890
- const execAsync3 = promisify4(exec3);
9906
+ const execFileAsync2 = promisify4(execFile3);
9891
9907
  for (const artifactPath of artifactPaths) {
9892
- const absolutePath = path34__default.default.resolve(process.cwd(), artifactPath);
9908
+ const absolutePath = path34__default.default.resolve(this.artifactRoot(), artifactPath);
9893
9909
  try {
9894
9910
  const stat = await fs11__default.default.stat(absolutePath);
9895
9911
  if (!stat.isFile()) {
@@ -9925,20 +9941,18 @@ ${assignment.expectedOutput}`;
9925
9941
  continue;
9926
9942
  }
9927
9943
  const ext = path34__default.default.extname(absolutePath).toLowerCase();
9928
- try {
9929
- if (ext === ".ts" || ext === ".tsx") {
9930
- await execAsync3(`npx tsc --noEmit ${absolutePath}`, { timeout: 1e4 });
9931
- } else if (ext === ".js" || ext === ".jsx") {
9932
- await execAsync3(`node --check ${absolutePath}`, { timeout: 1e4 });
9933
- } else if (ext === ".py") {
9934
- await execAsync3(`python -m py_compile ${absolutePath}`, { timeout: 1e4 });
9944
+ 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;
9945
+ if (check) {
9946
+ try {
9947
+ await execFileAsync2(check.cmd, check.args, { timeout: 1e4 });
9948
+ } catch (err) {
9949
+ const code = err.code;
9950
+ if (code === "ENOENT" || code === "EINVAL") continue;
9951
+ const e = err;
9952
+ issues.push(`Semantic error in ${artifactPath}:
9953
+ ${e.stderr || String(err)}
9954
+ ${e.stdout || ""}`);
9935
9955
  }
9936
- } catch (err) {
9937
- const stderr = err?.stderr || String(err);
9938
- const stdout = err?.stdout || "";
9939
- issues.push(`Semantic error in ${artifactPath}:
9940
- ${stderr}
9941
- ${stdout}`);
9942
9956
  }
9943
9957
  } catch {
9944
9958
  issues.push(`Required artifact was not created: ${artifactPath}`);
@@ -10017,7 +10031,7 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : ""),
10017
10031
  async checkAcceptance(assignment) {
10018
10032
  const criteria = assignment.acceptance ?? [];
10019
10033
  if (!criteria.length) return [];
10020
- const resolve2 = (target) => path34__default.default.resolve(process.cwd(), target);
10034
+ const resolve2 = (target) => path34__default.default.resolve(this.artifactRoot(), target);
10021
10035
  return evaluateAcceptance(criteria, assignment.files ?? [], {
10022
10036
  stat: async (target) => {
10023
10037
  try {
@@ -15433,6 +15447,18 @@ var ToolRegistry = class extends EventEmitter__default.default {
15433
15447
  this.tools.set(tool.name, tool);
15434
15448
  this.emit("tool:added", tool.name);
15435
15449
  }
15450
+ /**
15451
+ * The directory every registered tool resolves relative paths against.
15452
+ *
15453
+ * Exposed so a caller that has to reason about a file a tool WROTE can look
15454
+ * in the same place the tool wrote it. `process.cwd()` is not that place
15455
+ * outside a plain CLI run: the hosted server's cwd is the app directory
15456
+ * while the run's workspace is the tenant's scratch dir, and Electron's cwd
15457
+ * is the app bundle rather than the user's chosen folder.
15458
+ */
15459
+ getWorkspaceRoot() {
15460
+ return this.workspaceRoot;
15461
+ }
15436
15462
  /**
15437
15463
  * Wait until a named tool is registered, resolving immediately if it already exists.
15438
15464
  * T3 workers can call this after encountering a missing-tool error to resume