@koda-sl/baker-cli 0.197.0-dev.6d2f498f5 → 0.199.0-dev.6d2f498f5

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.
Files changed (28) hide show
  1. package/README.md +2 -0
  2. package/dist/{chunk-F6OHDJIX.js → chunk-6B5RAIAC.js} +1 -1
  3. package/dist/chunk-6B5RAIAC.js.map +1 -0
  4. package/dist/{chunk-G3O4HRYR.js → chunk-CVIGWKG2.js} +3 -3
  5. package/dist/{chunk-SSDYBIZB.js → chunk-MMP7BRV7.js} +73 -5
  6. package/dist/chunk-MMP7BRV7.js.map +1 -0
  7. package/dist/{chunk-YUTDQ4PV.js → chunk-PGPHKRK4.js} +2 -2
  8. package/dist/{chunk-34J26VIJ.js → chunk-VFRDAUQH.js} +4 -4
  9. package/dist/{chunk-OB26WXHZ.js → chunk-ZS6BR7CU.js} +3 -3
  10. package/dist/cli.js +97 -38
  11. package/dist/cli.js.map +1 -1
  12. package/dist/client-BBH4AYOK.js +15 -0
  13. package/dist/engine/index.js +3 -3
  14. package/dist/{env-GV4VDT5W.js → env-S4LMU6EN.js} +2 -2
  15. package/dist/{output-PXTEFDVX.js → output-VCUZ4EBX.js} +5 -5
  16. package/dist/{shared-AR6VAAIE.js → shared-WG5FCIHH.js} +6 -6
  17. package/package.json +1 -1
  18. package/dist/chunk-F6OHDJIX.js.map +0 -1
  19. package/dist/chunk-SSDYBIZB.js.map +0 -1
  20. package/dist/client-LTDQPQ7T.js +0 -15
  21. /package/dist/{chunk-G3O4HRYR.js.map → chunk-CVIGWKG2.js.map} +0 -0
  22. /package/dist/{chunk-YUTDQ4PV.js.map → chunk-PGPHKRK4.js.map} +0 -0
  23. /package/dist/{chunk-34J26VIJ.js.map → chunk-VFRDAUQH.js.map} +0 -0
  24. /package/dist/{chunk-OB26WXHZ.js.map → chunk-ZS6BR7CU.js.map} +0 -0
  25. /package/dist/{client-LTDQPQ7T.js.map → client-BBH4AYOK.js.map} +0 -0
  26. /package/dist/{env-GV4VDT5W.js.map → env-S4LMU6EN.js.map} +0 -0
  27. /package/dist/{output-PXTEFDVX.js.map → output-VCUZ4EBX.js.map} +0 -0
  28. /package/dist/{shared-AR6VAAIE.js.map → shared-WG5FCIHH.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  debugLogSetting
3
- } from "./chunk-F6OHDJIX.js";
3
+ } from "./chunk-6B5RAIAC.js";
4
4
 
5
5
  // src/debugLog.ts
6
6
  import { appendFileSync, mkdirSync, renameSync, statSync } from "fs";
@@ -150,4 +150,4 @@ export {
150
150
  readBodyForLog,
151
151
  installStreamTaps
152
152
  };
153
- //# sourceMappingURL=chunk-YUTDQ4PV.js.map
153
+ //# sourceMappingURL=chunk-PGPHKRK4.js.map
@@ -2,13 +2,13 @@ import {
2
2
  handleConnectionError,
3
3
  needsConnectionFix,
4
4
  writeAdsJson
5
- } from "./chunk-G3O4HRYR.js";
5
+ } from "./chunk-CVIGWKG2.js";
6
6
  import {
7
7
  ApiError
8
- } from "./chunk-OB26WXHZ.js";
8
+ } from "./chunk-ZS6BR7CU.js";
9
9
  import {
10
10
  getEnv
11
- } from "./chunk-F6OHDJIX.js";
11
+ } from "./chunk-6B5RAIAC.js";
12
12
 
13
13
  // src/commands/ads/meta/shared.ts
14
14
  var DAY_MS = 864e5;
@@ -108,4 +108,4 @@ export {
108
108
  csvOrJson,
109
109
  resolveEffectiveStatus
110
110
  };
111
- //# sourceMappingURL=chunk-34J26VIJ.js.map
111
+ //# sourceMappingURL=chunk-VFRDAUQH.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  debugLogHttp,
3
3
  readBodyForLog
4
- } from "./chunk-YUTDQ4PV.js";
4
+ } from "./chunk-PGPHKRK4.js";
5
5
  import {
6
6
  getEnv
7
- } from "./chunk-F6OHDJIX.js";
7
+ } from "./chunk-6B5RAIAC.js";
8
8
 
9
9
  // src/client.ts
10
10
  var MAX_RATE_LIMIT_RETRIES = 3;
@@ -198,4 +198,4 @@ export {
198
198
  apiGet,
199
199
  apiPost
200
200
  };
201
- //# sourceMappingURL=chunk-OB26WXHZ.js.map
201
+ //# sourceMappingURL=chunk-ZS6BR7CU.js.map
package/dist/cli.js CHANGED
@@ -48,7 +48,7 @@ import {
48
48
  toModelSafeImage,
49
49
  ulid,
50
50
  validateCanvasDeep
51
- } from "./chunk-SSDYBIZB.js";
51
+ } from "./chunk-MMP7BRV7.js";
52
52
  import {
53
53
  csvOrJson,
54
54
  daysAgoIso,
@@ -57,7 +57,7 @@ import {
57
57
  resolveAccountIdArg,
58
58
  resolveEffectiveStatus,
59
59
  todayIso
60
- } from "./chunk-34J26VIJ.js";
60
+ } from "./chunk-VFRDAUQH.js";
61
61
  import {
62
62
  buildQueryCacheKey,
63
63
  cacheGet,
@@ -73,17 +73,17 @@ import {
73
73
  writeAdsJson,
74
74
  writeAdsOutput,
75
75
  writeJsonEnvelope
76
- } from "./chunk-G3O4HRYR.js";
76
+ } from "./chunk-CVIGWKG2.js";
77
77
  import {
78
78
  ApiError,
79
79
  apiGet,
80
80
  apiPost,
81
81
  validateConvexId
82
- } from "./chunk-OB26WXHZ.js";
82
+ } from "./chunk-ZS6BR7CU.js";
83
83
  import {
84
84
  installStreamTaps,
85
85
  logInvocation
86
- } from "./chunk-YUTDQ4PV.js";
86
+ } from "./chunk-PGPHKRK4.js";
87
87
  import {
88
88
  captureBudgetMs,
89
89
  captureProxyCredentials,
@@ -94,7 +94,7 @@ import {
94
94
  requireChatId,
95
95
  resolveChatId,
96
96
  shouldEscalate
97
- } from "./chunk-F6OHDJIX.js";
97
+ } from "./chunk-6B5RAIAC.js";
98
98
 
99
99
  // src/cli.ts
100
100
  import { defineCommand as defineCommand212, runMain } from "citty";
@@ -17011,10 +17011,10 @@ function duplicateCommand2(entity, label) {
17011
17011
  replace: { type: "boolean", description: "Pause the original once the copy publishes" }
17012
17012
  },
17013
17013
  run: async ({ args }) => {
17014
- const { apiPost: apiPost2 } = await import("./client-LTDQPQ7T.js");
17015
- const { requireChatId: requireChatId2 } = await import("./env-GV4VDT5W.js");
17016
- const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-PXTEFDVX.js");
17017
- const { handleMetaError: handleMetaError2 } = await import("./shared-AR6VAAIE.js");
17014
+ const { apiPost: apiPost2 } = await import("./client-BBH4AYOK.js");
17015
+ const { requireChatId: requireChatId2 } = await import("./env-S4LMU6EN.js");
17016
+ const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-VCUZ4EBX.js");
17017
+ const { handleMetaError: handleMetaError2 } = await import("./shared-WG5FCIHH.js");
17018
17018
  try {
17019
17019
  const accountId = bareAccountId2(args);
17020
17020
  const chatId = requireChatId2();
@@ -35032,6 +35032,46 @@ function classifyCaptureFailure(error) {
35032
35032
  import { mkdir as mkdir11, writeFile as writeFile15 } from "fs/promises";
35033
35033
  import path31 from "path";
35034
35034
 
35035
+ // ../proxy/src/preflight.ts
35036
+ import http from "http";
35037
+ function classifyPreflightStatus(status) {
35038
+ if (status === 200) return { usable: true };
35039
+ if (status === 407) return { usable: false, problem: "auth" };
35040
+ return { usable: false, problem: "unreachable" };
35041
+ }
35042
+ async function preflightProxyRoute(route, options = {}) {
35043
+ if (route.kind !== "proxy") return { usable: true };
35044
+ const timeoutMs = options.timeoutMs ?? 8e3;
35045
+ const target = options.target ?? "example.com:443";
35046
+ const endpoint = new URL(route.server);
35047
+ const auth = Buffer.from(`${route.username}:${route.password}`).toString("base64");
35048
+ return await new Promise((resolve5) => {
35049
+ const settle = (result) => {
35050
+ request.destroy();
35051
+ resolve5(result);
35052
+ };
35053
+ const request = http.request({
35054
+ host: endpoint.hostname,
35055
+ port: Number(endpoint.port),
35056
+ method: "CONNECT",
35057
+ path: target,
35058
+ headers: { "Proxy-Authorization": `Basic ${auth}`, Host: target },
35059
+ timeout: timeoutMs
35060
+ });
35061
+ request.on("connect", (response, socket) => {
35062
+ socket.destroy();
35063
+ settle(classifyPreflightStatus(response.statusCode));
35064
+ });
35065
+ request.on("response", (response) => {
35066
+ response.destroy();
35067
+ settle(classifyPreflightStatus(response.statusCode));
35068
+ });
35069
+ request.on("timeout", () => settle({ usable: false, problem: "timeout" }));
35070
+ request.on("error", () => settle({ usable: false, problem: "unreachable" }));
35071
+ request.end();
35072
+ });
35073
+ }
35074
+
35035
35075
  // src/engine/landing-library/browser.ts
35036
35076
  import { createRequire } from "module";
35037
35077
  var require_ = createRequire(import.meta.url);
@@ -35396,6 +35436,18 @@ function attemptSignal(outcome) {
35396
35436
  timedOut: code === "SITE_TOO_SLOW"
35397
35437
  };
35398
35438
  }
35439
+ function ambiguousProxyTimeout(outcome) {
35440
+ return outcome.route.kind === "proxy" && outcome.failure.code === "SITE_TOO_SLOW" && outcome.status === null && outcome.netError === null;
35441
+ }
35442
+ function asProxyFailure(outcome, problem) {
35443
+ return {
35444
+ ...outcome,
35445
+ failure: { code: "PROXY_UNAVAILABLE", message: PROXY_UNAVAILABLE_MESSAGE },
35446
+ // Borrowing Chromium's own vocabulary so `isProxyFailure` recognises this
35447
+ // without having to learn a second way of being told the same thing.
35448
+ netError: problem === "auth" ? "ERR_PROXY_AUTH_REQUESTED" : "ERR_PROXY_CONNECTION_FAILED"
35449
+ };
35450
+ }
35399
35451
  function nextRoute(args) {
35400
35452
  const last = args.attempts[args.attempts.length - 1];
35401
35453
  if (!last) return { next: null, reason: "ladder_exhausted" };
@@ -36761,6 +36813,13 @@ function rungReport(outcome) {
36761
36813
  status: outcome.status
36762
36814
  };
36763
36815
  }
36816
+ async function resolveAmbiguousTimeout(outcome, log) {
36817
+ if (!ambiguousProxyTimeout(outcome)) return outcome;
36818
+ const verdict = await preflightProxyRoute(outcome.route).catch(() => null);
36819
+ if (!verdict || verdict.usable) return outcome;
36820
+ log(`that timeout was our own route, not the site (${verdict.problem}) \u2014 carrying on up the ladder`);
36821
+ return asProxyFailure(outcome, verdict.problem);
36822
+ }
36764
36823
  async function openViaLadder(args) {
36765
36824
  const { url, routes, timeoutMs, deadline, log } = args;
36766
36825
  const attempts = [];
@@ -36770,7 +36829,7 @@ async function openViaLadder(args) {
36770
36829
  if (attempt.ok) {
36771
36830
  return { opened: attempt, attempts, tier: route.kind === "proxy" ? route.tier : "direct" };
36772
36831
  }
36773
- attempts.push(attempt.outcome);
36832
+ attempts.push(await resolveAmbiguousTimeout(attempt.outcome, log));
36774
36833
  const decision = nextRoute({
36775
36834
  routes,
36776
36835
  attempts,
@@ -36893,6 +36952,32 @@ async function recordCapture(manifest, outDir) {
36893
36952
  const written = await recordReferences(process.cwd(), references);
36894
36953
  return written ? references.length : 0;
36895
36954
  }
36955
+ function captureHints(args) {
36956
+ const { manifest, outDir, report, recorded } = args;
36957
+ const shots = manifest.sections.filter((section) => section.desktopShot !== null).length;
36958
+ const anyScored = manifest.sections.some((section) => section.fidelity !== null);
36959
+ const hints = [];
36960
+ if (manifest.security.certificateNotes.length > 0) {
36961
+ hints.push(
36962
+ `Captured anyway, but this site's certificate did not check out: ${manifest.security.certificateNotes.join(" ")} Treat the page as a design reference only \u2014 do not repeat its claims, prices or customer names.`
36963
+ );
36964
+ }
36965
+ if (shots === 0) {
36966
+ hints.push(
36967
+ `No section screenshots were produced, so there is nothing to look at in ${outDir}/sections/. Treat this capture as unusable rather than designing from the counts.`
36968
+ );
36969
+ } else {
36970
+ hints.push(
36971
+ report ? `Read ${outDir}/report.html \u2014 every section side by side${anyScored ? " with its fidelity score" : ""}.` : `Read the section screenshots in ${outDir}/sections/*/desktop.png before you design.`,
36972
+ `${shots} of ${manifest.sections.length} sections captured to ${outDir}/sections/ \u2014 look at them, then decide which the client's page actually needs.`
36973
+ );
36974
+ }
36975
+ hints.push(INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt);
36976
+ hints.push(
36977
+ recorded > 0 ? `${recorded} sections are recorded for the originality check \u2014 \`baker landing critique\` will block a publish that ships their copy.` : "Nothing from this capture is recorded for the originality check, so it cannot see this page. Be especially careful not to reuse its copy."
36978
+ );
36979
+ return hints;
36980
+ }
36896
36981
  registerSchema({
36897
36982
  command: "landing.inspiration.scrape",
36898
36983
  description: "Start here when the user points at a specific page and wants it now: capture one landing page into a directory of section screenshots, standalone HTML bundles, a whole-page reproduction and motion filmstrips. Returns when the capture is done, unlike `add`. Read the screenshots. Also records every captured section for the originality check.",
@@ -36955,7 +37040,6 @@ var scrapeCommand = defineCommand148({
36955
37040
  `)
36956
37041
  });
36957
37042
  const scored = manifest.sections.map((section) => section.fidelity).filter((value) => value !== null).sort((a, b) => a - b);
36958
- const shotCount = manifest.sections.filter((section) => section.desktopShot !== null).length;
36959
37043
  const recorded = await recordCapture(manifest, args.out);
36960
37044
  writeJson({
36961
37045
  ok: true,
@@ -36977,32 +37061,7 @@ var scrapeCommand = defineCommand148({
36977
37061
  certificate_verified: false,
36978
37062
  ...manifest.security.certificateNotes.length > 0 ? { certificate_notes: manifest.security.certificateNotes } : {}
36979
37063
  },
36980
- hints: [
36981
- ...manifest.security.certificateNotes.length > 0 ? [
36982
- `Captured anyway, but this site's certificate did not check out: ${manifest.security.certificateNotes.join(" ")} Treat the page as a design reference only \u2014 do not repeat its claims, prices or customer names.`
36983
- ] : [],
36984
- // The command that produces the most and says the least about it. It
36985
- // returns a count and a directory; without this the agent has no
36986
- // instruction to open any of it, and a capture nobody looks at taught
36987
- // nobody anything. A nudge tied to one command's result belongs here,
36988
- // not only in the tool doc the agent may not re-read.
36989
- //
36990
- // Every one of these now reads the manifest rather than the flags the
36991
- // caller passed. The flags say what was *asked for*; a screenshot that
36992
- // failed still leaves `desktopShot` null, and `--no-code` leaves every
36993
- // fidelity score null while the report renders them as "—". Telling an
36994
- // agent to go and read a file that is not there costs it a tool call
36995
- // and costs us its trust in the next hint.
36996
- ...shotCount > 0 ? [
36997
- args.report ? `Read ${args.out}/report.html \u2014 every section side by side${scored.length > 0 ? " with its fidelity score" : ""}.` : `Read the section screenshots in ${args.out}/sections/*/desktop.png before you design.`,
36998
- `${shotCount} of ${manifest.sections.length} sections captured to ${args.out}/sections/ \u2014 look at them, then decide which the client's page actually needs.`
36999
- ] : [
37000
- `No section screenshots were produced, so there is nothing to look at in ${args.out}/sections/. Treat this capture as unusable rather than designing from the counts.`
37001
- ],
37002
- INSPIRATION_HINTS.structureNotCopy,
37003
- INSPIRATION_HINTS.adapt,
37004
- recorded > 0 ? `${recorded} sections are recorded for the originality check \u2014 \`baker landing critique\` will block a publish that ships their copy.` : "Nothing from this capture is recorded for the originality check, so it cannot see this page. Be especially careful not to reuse its copy."
37005
- ]
37064
+ hints: captureHints({ manifest, outDir: args.out, report: args.report, recorded })
37006
37065
  });
37007
37066
  } catch (error) {
37008
37067
  const failure = classifyCaptureFailure(error);