ccqa 1.2.1 → 1.3.1

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/bin/ccqa.mjs CHANGED
@@ -679,10 +679,10 @@ function bundledVitestConfigPath() {
679
679
  }
680
680
  //#endregion
681
681
  //#region src/runtime/spawn-vitest.ts
682
- const require$1 = createRequire(import.meta.url);
682
+ const require$2 = createRequire(import.meta.url);
683
683
  function resolveVitestBin() {
684
- const pkgPath = require$1.resolve("vitest/package.json");
685
- const pkg = require$1(pkgPath);
684
+ const pkgPath = require$2.resolve("vitest/package.json");
685
+ const pkg = require$2(pkgPath);
686
686
  const binRel = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.vitest;
687
687
  if (!binRel) throw new Error(`vitest package.json has no bin entry (resolved at ${pkgPath})`);
688
688
  return resolve(dirname(pkgPath), binRel);
@@ -1194,6 +1194,50 @@ function opt(key, value) {
1194
1194
  return value ? { [key]: value } : {};
1195
1195
  }
1196
1196
  //#endregion
1197
+ //#region src/claude/native-binary.ts
1198
+ const require$1 = createRequire(import.meta.url);
1199
+ /**
1200
+ * The agent SDK launches Claude through a native `claude` binary that ships in
1201
+ * a per-platform package (`@anthropic-ai/claude-agent-sdk-<platform>-<cpu>`),
1202
+ * declared as an *optional* dependency of the SDK. Optional means a consumer's
1203
+ * lockfile can omit it without any install-time error — and then every Claude
1204
+ * call fails at runtime with a message that never reaches our logs. Resolving
1205
+ * the package up front lets us say so once, in a line that names the fix.
1206
+ *
1207
+ * ccqa's own package.json repeats these packages in `optionalDependencies` for
1208
+ * the same reason: a second declaration gives the resolver another chance to
1209
+ * record them. Keep that list's version range in step with the SDK's.
1210
+ */
1211
+ function nativeBinaryPackage(platform = process.platform, arch = process.arch, musl = isMusl(platform)) {
1212
+ return `@anthropic-ai/claude-agent-sdk-${platform}-${arch === "arm64" ? "arm64" : "x64"}${platform === "linux" && musl ? "-musl" : ""}`;
1213
+ }
1214
+ /**
1215
+ * musl builds (Alpine and friends) need their own binary. Node doesn't expose
1216
+ * the libc flavour directly; the absence of `glibcVersionRuntime` in the
1217
+ * process report is the usual proxy.
1218
+ */
1219
+ function isMusl(platform) {
1220
+ if (platform !== "linux") return false;
1221
+ return !(process.report?.getReport?.())?.header?.glibcVersionRuntime;
1222
+ }
1223
+ /**
1224
+ * Name of the platform package this host needs, or `null` when it resolves.
1225
+ * The per-platform packages have no `exports`, so the manifest is reachable.
1226
+ */
1227
+ function missingNativeBinaryPackage(resolve = require$1.resolve) {
1228
+ const pkg = nativeBinaryPackage();
1229
+ try {
1230
+ resolve(`${pkg}/package.json`);
1231
+ return null;
1232
+ } catch {
1233
+ return pkg;
1234
+ }
1235
+ }
1236
+ /** Advice shown when the binary is absent — the package name plus how to fix it. */
1237
+ function missingNativeBinaryMessage(pkg) {
1238
+ return `${pkg} is not installed. The Claude Agent SDK needs it to start Claude on this platform, so every Claude-backed command (run in live mode, drift, diagnose) will fail. It ships as an optional dependency of the SDK, which a lockfile can drop silently: reinstall without omitting optional dependencies, or add it to your project as a direct dependency pinned to the same version as @anthropic-ai/claude-agent-sdk.`;
1239
+ }
1240
+ //#endregion
1197
1241
  //#region src/claude/invoke.ts
1198
1242
  function resolveModel(explicit) {
1199
1243
  if (explicit) return explicit;
@@ -1230,6 +1274,18 @@ function resolveEndpointEnv() {
1230
1274
  }
1231
1275
  return endpointEnv;
1232
1276
  }
1277
+ let nativeBinaryWarned = false;
1278
+ /**
1279
+ * Warn once per process when the SDK's per-platform native binary is missing:
1280
+ * every Claude call is about to fail, and the opaque per-step errors alone are
1281
+ * expensive to trace back to a lockfile that dropped an optional dependency.
1282
+ */
1283
+ function warnOnceIfNativeBinaryMissing() {
1284
+ if (nativeBinaryWarned) return;
1285
+ nativeBinaryWarned = true;
1286
+ const missing = missingNativeBinaryPackage();
1287
+ if (missing) warn(missingNativeBinaryMessage(missing));
1288
+ }
1233
1289
  async function invokeClaudeStreaming(options, onEvent) {
1234
1290
  const { prompt, systemPrompt, allowedTools, disableBuiltinTools = false, disableThinking = false, maxTurns, env, model, cwd, onAbAction, onAbActionFailed, silenceBashLog = false, relaxAbConstraints = false } = options;
1235
1291
  const resolvedModel = resolveModel(model);
@@ -1312,8 +1368,10 @@ async function invokeClaudeStreaming(options, onEvent) {
1312
1368
  }] }]
1313
1369
  } : void 0
1314
1370
  };
1371
+ warnOnceIfNativeBinaryMissing();
1315
1372
  let result = "";
1316
1373
  let isError = false;
1374
+ let errorDetail = null;
1317
1375
  let cost = {
1318
1376
  totalCostUsd: null,
1319
1377
  durationMs: null,
@@ -1336,18 +1394,24 @@ async function invokeClaudeStreaming(options, onEvent) {
1336
1394
  }
1337
1395
  }
1338
1396
  if (msg.type === "result") {
1339
- result = msg.subtype === "success" ? msg.result : "";
1340
1397
  isError = msg.is_error ?? false;
1398
+ if (msg.subtype === "success") result = msg.result;
1399
+ else {
1400
+ result = "";
1401
+ errorDetail = `SDK reported ${msg.subtype}`;
1402
+ }
1341
1403
  cost = extractInvocationCost(msg);
1342
1404
  }
1343
1405
  }
1344
1406
  } catch (err) {
1345
1407
  isError = true;
1346
- if (!result) result = err instanceof Error ? err.message : String(err);
1408
+ errorDetail = err instanceof Error ? err.message : String(err);
1409
+ if (!result) result = errorDetail;
1347
1410
  }
1348
1411
  return {
1349
1412
  result,
1350
1413
  isError,
1414
+ errorDetail,
1351
1415
  cost
1352
1416
  };
1353
1417
  }
@@ -5101,6 +5165,7 @@ async function runLiveExecutor(input) {
5101
5165
  const transcriptParts = [];
5102
5166
  const commandParts = [];
5103
5167
  let isError = false;
5168
+ let errorDetail = null;
5104
5169
  let cost = emptyStepCost();
5105
5170
  try {
5106
5171
  const result = await invokeClaudeStreaming({
@@ -5120,6 +5185,7 @@ async function runLiveExecutor(input) {
5120
5185
  }
5121
5186
  });
5122
5187
  isError = result.isError;
5188
+ errorDetail = result.errorDetail;
5123
5189
  cost = {
5124
5190
  totalCostUsd: result.cost.totalCostUsd,
5125
5191
  durationApiMs: result.cost.durationApiMs,
@@ -5132,7 +5198,8 @@ async function runLiveExecutor(input) {
5132
5198
  };
5133
5199
  } catch (err) {
5134
5200
  isError = true;
5135
- transcriptParts.push(`[ccqa] invokeClaudeStreaming threw: ${err instanceof Error ? err.message : String(err)}`);
5201
+ errorDetail = err instanceof Error ? err.message : String(err);
5202
+ transcriptParts.push(`[ccqa] invokeClaudeStreaming threw: ${errorDetail}`);
5136
5203
  }
5137
5204
  const transcript = transcriptParts.join("\n");
5138
5205
  const after = takeScreenshot(input.sessionName, paths.afterPng, { fullPage: true });
@@ -5141,6 +5208,7 @@ async function runLiveExecutor(input) {
5141
5208
  const { status, reasoning } = judgeStepOutcome({
5142
5209
  step,
5143
5210
  isError,
5211
+ errorDetail,
5144
5212
  judged: findLastStepResult(transcript)
5145
5213
  });
5146
5214
  return {
@@ -5219,11 +5287,14 @@ function sumStepCosts(steps) {
5219
5287
  * Kept as a pure helper so the executor loop stays readable and the
5220
5288
  * branches are individually testable.
5221
5289
  */
5222
- function judgeStepOutcome({ step, isError, judged }) {
5223
- if (isError) return {
5224
- status: "failed",
5225
- reasoning: judged?.reasoning ? `agent error; last reasoning: ${judged.reasoning}` : "Claude invocation returned an error"
5226
- };
5290
+ function judgeStepOutcome({ step, isError, errorDetail, judged }) {
5291
+ if (isError) {
5292
+ const detail = errorDetail ? `: ${errorDetail}` : "";
5293
+ return {
5294
+ status: "failed",
5295
+ reasoning: judged?.reasoning ? `agent error${detail}; last reasoning: ${judged.reasoning}` : `Claude invocation returned an error${detail}`
5296
+ };
5297
+ }
5227
5298
  if (!judged) return {
5228
5299
  status: "failed",
5229
5300
  reasoning: "STEP_RESULT missing"
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccqa",
3
- "version": "1.2.1",
3
+ "version": "1.3.1",
4
4
  "type": "module",
5
5
  "description": "Browser test recorder powered by Claude Code and agent-browser",
6
6
  "repository": {
@@ -28,11 +28,22 @@
28
28
  "dist/"
29
29
  ],
30
30
  "dependencies": {
31
- "@anthropic-ai/claude-agent-sdk": "^0.2.87",
31
+ "@anthropic-ai/claude-agent-sdk": "^0.3.215",
32
+ "@anthropic-ai/sdk": "^0.112.3",
32
33
  "commander": "^14.0.3",
33
34
  "yaml": "^2.9.0",
34
35
  "zod": "^4.3.6"
35
36
  },
37
+ "optionalDependencies": {
38
+ "@anthropic-ai/claude-agent-sdk-darwin-arm64": "^0.3.215",
39
+ "@anthropic-ai/claude-agent-sdk-darwin-x64": "^0.3.215",
40
+ "@anthropic-ai/claude-agent-sdk-linux-arm64": "^0.3.215",
41
+ "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "^0.3.215",
42
+ "@anthropic-ai/claude-agent-sdk-linux-x64": "^0.3.215",
43
+ "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "^0.3.215",
44
+ "@anthropic-ai/claude-agent-sdk-win32-arm64": "^0.3.215",
45
+ "@anthropic-ai/claude-agent-sdk-win32-x64": "^0.3.215"
46
+ },
36
47
  "peerDependencies": {
37
48
  "agent-browser": "*",
38
49
  "vitest": ">=2.0.0"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccqa",
3
- "version": "1.2.1",
3
+ "version": "1.3.1",
4
4
  "type": "module",
5
5
  "description": "Browser test recorder powered by Claude Code and agent-browser",
6
6
  "repository": {
@@ -28,11 +28,22 @@
28
28
  "dist/"
29
29
  ],
30
30
  "dependencies": {
31
- "@anthropic-ai/claude-agent-sdk": "^0.2.87",
31
+ "@anthropic-ai/claude-agent-sdk": "^0.3.215",
32
+ "@anthropic-ai/sdk": "^0.112.3",
32
33
  "commander": "^14.0.3",
33
34
  "yaml": "^2.9.0",
34
35
  "zod": "^4.3.6"
35
36
  },
37
+ "optionalDependencies": {
38
+ "@anthropic-ai/claude-agent-sdk-darwin-arm64": "^0.3.215",
39
+ "@anthropic-ai/claude-agent-sdk-darwin-x64": "^0.3.215",
40
+ "@anthropic-ai/claude-agent-sdk-linux-arm64": "^0.3.215",
41
+ "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "^0.3.215",
42
+ "@anthropic-ai/claude-agent-sdk-linux-x64": "^0.3.215",
43
+ "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "^0.3.215",
44
+ "@anthropic-ai/claude-agent-sdk-win32-arm64": "^0.3.215",
45
+ "@anthropic-ai/claude-agent-sdk-win32-x64": "^0.3.215"
46
+ },
36
47
  "peerDependencies": {
37
48
  "agent-browser": "*",
38
49
  "vitest": ">=2.0.0"