@popcraft/cli 0.33.0 → 0.34.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.
Files changed (2) hide show
  1. package/dist/popcraft.mjs +76 -24
  2. package/package.json +2 -2
package/dist/popcraft.mjs CHANGED
@@ -1196,7 +1196,7 @@ function operations(spec = openapi) {
1196
1196
  }
1197
1197
  async function call(target2, method, path, opts = {}) {
1198
1198
  const qs = new URLSearchParams(opts.query ?? {}).toString();
1199
- const headers = { "user-agent": `popcraft-cli/${"0.33.0"}`, ...opts.headers };
1199
+ const headers = { "user-agent": `popcraft-cli/${"0.34.1"}`, ...opts.headers };
1200
1200
  if (target2.token) headers.authorization = `Bearer ${target2.token}`;
1201
1201
  if (opts.contentType) headers["content-type"] = opts.contentType;
1202
1202
  try {
@@ -32183,6 +32183,23 @@ var init_en2 = __esm({
32183
32183
  "apiTokensDialog.used": "used {date}",
32184
32184
  "appHeader.doubleClickToRename": "Double-click to rename",
32185
32185
  "appHeader.fileName": "File name",
32186
+ "appStoreOffers.buyCredits": "Buy AI credits",
32187
+ "appStoreOffers.creditsAdded": "{credits} AI credits added to {teamName}.",
32188
+ "appStoreOffers.creditsGoTo": "Credits are added to {teamName} and pay for AI. They don't expire.",
32189
+ "appStoreOffers.failed": "The purchase did not go through.",
32190
+ "appStoreOffers.loading": "Loading App Store prices\u2026",
32191
+ "appStoreOffers.manage": "Manage in the App Store",
32192
+ "appStoreOffers.pack": "{credits} credits \xB7 {price}",
32193
+ "appStoreOffers.pending": "Your purchase is waiting for approval. It's added as soon as it goes through.",
32194
+ "appStoreOffers.perMonth": " / month",
32195
+ "appStoreOffers.perYear": " / year",
32196
+ "appStoreOffers.privacy": "Privacy Policy",
32197
+ "appStoreOffers.renewalTerms": "Payment is charged to your Apple Account. The subscription renews automatically at the price shown for each period unless you cancel it at least 24 hours before the period ends. Manage or cancel it in your App Store account settings.",
32198
+ "appStoreOffers.restore": "Restore purchases",
32199
+ "appStoreOffers.restored": "{count, plural, =0 {No purchases to restore.} one {Restored # purchase.} other {Restored # purchases.}}",
32200
+ "appStoreOffers.subscribe": "Subscribe",
32201
+ "appStoreOffers.subscribed": "Subscribed to {plan} \xB7 {teamName}.",
32202
+ "appStoreOffers.terms": "Terms of Use",
32186
32203
  "assetsPanel.components": "Components",
32187
32204
  "assetsPanel.documentColors": "Document colors",
32188
32205
  "assetsPanel.editComponent": "Edit component",
@@ -34946,6 +34963,7 @@ var init_en2 = __esm({
34946
34963
  "planDialog.isOnThePlan": "{teamName} is on the {value} plan.",
34947
34964
  "planDialog.largestUpload": "Largest upload",
34948
34965
  "planDialog.loadingPlans": "Loading plans\u2026",
34966
+ "planDialog.managedInAppStore": "Bought in the App Store. Manage or cancel it in the App Store on your iPad or Mac.",
34949
34967
  "planDialog.mediaStorage": "Storage (media and websites)",
34950
34968
  "planDialog.mo": "mo",
34951
34969
  "planDialog.namedVersionsPerFile": "Named versions per file",
@@ -261324,8 +261342,13 @@ var init_plans = __esm({
261324
261342
  });
261325
261343
 
261326
261344
  // lib/billing/purchases.ts
261345
+ function purchaseChannel() {
261346
+ const store6 = storePlatform();
261347
+ if (store6 === null) return "web";
261348
+ return store6 === "ios" || store6 === "macos" ? "app_store" : null;
261349
+ }
261327
261350
  function purchasesAllowed() {
261328
- return storePlatform() === null;
261351
+ return purchaseChannel() === "web";
261329
261352
  }
261330
261353
  function limitMessageHere(d) {
261331
261354
  return limitMessage(purchasesAllowed() ? d : { ...d, upgradeTo: null });
@@ -310330,7 +310353,6 @@ function downloadBlob(blob, filename) {
310330
310353
  }
310331
310354
  var init_download = __esm({
310332
310355
  "lib/io/download.ts"() {
310333
- "use strict";
310334
310356
  }
310335
310357
  });
310336
310358
 
@@ -310550,7 +310572,6 @@ function creditLine(c2) {
310550
310572
  var MAX_PHOTO_PAGE, MAX_PHOTO_QUERY, UUID, isPhotoId, photoImagePath;
310551
310573
  var init_stock = __esm({
310552
310574
  "lib/photos/stock.ts"() {
310553
- "use strict";
310554
310575
  MAX_PHOTO_PAGE = 12;
310555
310576
  MAX_PHOTO_QUERY = 200;
310556
310577
  UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -316110,7 +316131,6 @@ function videoPixelSize(resolution, aspect) {
316110
316131
  var VIDEO_ASPECTS, VIDEO_RESOLUTIONS, SEEDANCE_ASPECTS, range, VIDEO_MODELS, DEFAULT_VIDEO_MODEL, videoModel, VIDEO_LIMITS;
316111
316132
  var init_video_models = __esm({
316112
316133
  "lib/ai/video-models.ts"() {
316113
- "use strict";
316114
316134
  VIDEO_ASPECTS = ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9"];
316115
316135
  VIDEO_RESOLUTIONS = ["480p", "720p", "1080p"];
316116
316136
  SEEDANCE_ASPECTS = ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9"];
@@ -316476,7 +316496,7 @@ async function renderDocument(doc2, nodeIds, options) {
316476
316496
  if (frame2) doc2 = { ...doc2, nodes: bakeMotion3(doc2.nodes, frame2.id, options.at) };
316477
316497
  }
316478
316498
  }
316479
- return selectionReferenceImages2(doc2, [...nodeIds], { maxEdge: options?.maxEdge, max: 8, format: "WEBP", ...options?.bands ? { bands: options.bands } : {} });
316499
+ return selectionReferenceImages2(doc2, [...nodeIds], { maxEdge: options?.maxEdge, max: 8, format: "JPG", ...options?.bands ? { bands: options.bands } : {} });
316480
316500
  }
316481
316501
  function generateCapability(ctx2) {
316482
316502
  return async (prompt2, options = {}) => {
@@ -326462,7 +326482,7 @@ var init_package = __esm({
326462
326482
  "packages/runtime/package.json"() {
326463
326483
  package_default = {
326464
326484
  name: "@popcraft/runtime",
326465
- version: "0.33.0",
326485
+ version: "0.34.1",
326466
326486
  description: "What code exported from PopCraft shares: the meaning of expressions (operators and functions) and, as it grows, the parts of a design's behaviour that are common code rather than generated React.",
326467
326487
  license: "MIT",
326468
326488
  homepage: "https://popcraft.app/docs/exporting/nextjs",
@@ -351128,7 +351148,6 @@ function exportsOf(source3) {
351128
351148
  var CODE_LIMITS, packageOf;
351129
351149
  var init_source2 = __esm({
351130
351150
  "lib/code/source.ts"() {
351131
- "use strict";
351132
351151
  CODE_LIMITS = { modules: 100, sourceLength: 2e5, packages: 12 };
351133
351152
  packageOf = (spec) => spec.split("/").slice(0, spec.startsWith("@") ? 2 : 1).join("/");
351134
351153
  }
@@ -351171,7 +351190,6 @@ function compileModule(module2) {
351171
351190
  var import_sucrase, BUILT_IN, memo4;
351172
351191
  var init_compile2 = __esm({
351173
351192
  "lib/code/compile.ts"() {
351174
- "use strict";
351175
351193
  import_sucrase = __toESM(require_dist2());
351176
351194
  init_source2();
351177
351195
  init_source2();
@@ -363345,27 +363363,35 @@ async function authHeaders2() {
363345
363363
  };
363346
363364
  }
363347
363365
  async function streamChat(opts, handlers = {}, signal) {
363366
+ const body = JSON.stringify({
363367
+ model: opts.model,
363368
+ messages: opts.messages,
363369
+ stream: true,
363370
+ max_tokens: opts.maxTokens ?? (opts.tools?.length ? 16384 : 4096),
363371
+ ...opts.temperature !== void 0 ? { temperature: opts.temperature } : {},
363372
+ ...opts.tools?.length ? { tools: opts.tools, tool_choice: opts.toolChoice ?? "auto" } : {}
363373
+ });
363374
+ if (body.length > MAX_REQUEST_BYTES) {
363375
+ throw new StreamError(
363376
+ `This message is too large to send (${(body.length / 1e6).toFixed(1)} MB with its images). Attach fewer or smaller images.`,
363377
+ "too_large",
363378
+ 413
363379
+ );
363380
+ }
363348
363381
  const res = await fetch(`${HYPERY_GATEWAY_URL}/api/v1/chat/completions`, {
363349
363382
  method: "POST",
363350
363383
  headers: await authHeaders2(),
363351
363384
  signal,
363352
- body: JSON.stringify({
363353
- model: opts.model,
363354
- messages: opts.messages,
363355
- stream: true,
363356
- max_tokens: opts.maxTokens ?? (opts.tools?.length ? 16384 : 4096),
363357
- ...opts.temperature !== void 0 ? { temperature: opts.temperature } : {},
363358
- ...opts.tools?.length ? { tools: opts.tools, tool_choice: opts.toolChoice ?? "auto" } : {}
363359
- })
363385
+ body
363360
363386
  }).catch((err2) => {
363361
363387
  if (err2.name === "AbortError") throw err2;
363362
363388
  throw new StreamError("Could not reach Hypery. Check your connection.", "network", 0);
363363
363389
  });
363364
363390
  if (!res.ok || !res.body) {
363365
- const body = await res.text().catch(() => "");
363366
- let payload = body;
363391
+ const body2 = await res.text().catch(() => "");
363392
+ let payload = body2;
363367
363393
  try {
363368
- payload = JSON.parse(body);
363394
+ payload = JSON.parse(body2);
363369
363395
  } catch {
363370
363396
  }
363371
363397
  throw new StreamError(streamErrorMessage(payload, `The AI request failed (${res.status}).`), errorCodeFor(res.status, payload), res.status);
@@ -363414,7 +363440,7 @@ function errorCodeFor(status3, payload) {
363414
363440
  if (status3 === 429) return "ai_rate_limited";
363415
363441
  return "ai_upstream";
363416
363442
  }
363417
- var IDLE_TIMEOUT_MS;
363443
+ var IDLE_TIMEOUT_MS, MAX_REQUEST_BYTES;
363418
363444
  var init_gateway = __esm({
363419
363445
  "lib/agent/gateway.ts"() {
363420
363446
  "use strict";
@@ -363424,6 +363450,7 @@ var init_gateway = __esm({
363424
363450
  init_shared();
363425
363451
  init_stream_parse();
363426
363452
  IDLE_TIMEOUT_MS = 18e4;
363453
+ MAX_REQUEST_BYTES = 44e5;
363427
363454
  }
363428
363455
  });
363429
363456
 
@@ -363455,6 +363482,28 @@ function pruneOldImages(messages, keep = KEEP_IMAGE_TURNS) {
363455
363482
  messages[i2] = { ...m, content: `${text} [${images === 1 ? "image" : `${images} images`} omitted: superseded by a later render \u2014 render again if you need to look.]`.trim() };
363456
363483
  }
363457
363484
  }
363485
+ function fitImagesToBudget(messages, budget) {
363486
+ if (sizeOf2(messages) <= budget) return;
363487
+ const renderTurns = messages.map((m, i2) => ({ m, i: i2 })).filter(({ m }) => m.role === "user" && Array.isArray(m.content) && m.content[0]?.type === "text" && !!m.content[0].text?.startsWith(RENDER_TURN_PREFIX)).map(({ i: i2 }) => i2);
363488
+ for (const i2 of renderTurns) {
363489
+ if (sizeOf2(messages) <= budget) return;
363490
+ const m = messages[i2];
363491
+ if (!Array.isArray(m.content)) continue;
363492
+ const parts = [...m.content];
363493
+ let dropped = 0;
363494
+ for (let j = parts.length - 1; j >= 0 && sizeOf2(messages) > budget; j--) {
363495
+ if (parts[j].type !== "image_url") continue;
363496
+ parts.splice(j, 1);
363497
+ dropped++;
363498
+ messages[i2] = { ...m, content: [...parts] };
363499
+ }
363500
+ if (dropped) {
363501
+ const note2 = `[${dropped === 1 ? "1 image" : `${dropped} images`} omitted to keep the request under the size limit \u2014 look at fewer layers at once, or pass a smaller maxEdge.]`;
363502
+ const rest = messages[i2].content;
363503
+ messages[i2] = { ...m, content: rest.some((p2) => p2.type === "image_url") ? [...rest, { type: "text", text: note2 }] : `${rest.flatMap((p2) => p2.type === "text" ? [p2.text] : []).join(" ")} ${note2}`.trim() };
363504
+ }
363505
+ }
363506
+ }
363458
363507
  async function runAgentLoop(opts) {
363459
363508
  const maxRounds = opts.maxRounds ?? DEFAULT_MAX_ROUNDS;
363460
363509
  const maxResultChars = opts.maxResultChars ?? 8e3;
@@ -363466,6 +363515,7 @@ async function runAgentLoop(opts) {
363466
363515
  if (opts.stopped?.()) return { messages, text, rounds, exhausted: false, stopped: true };
363467
363516
  for (const note2 of opts.drainNotifications?.() ?? []) messages.push({ role: "user", content: note2 });
363468
363517
  pruneOldImages(messages);
363518
+ fitImagesToBudget(messages, MAX_REQUEST_BYTES - JSON.stringify(specs).length - REQUEST_MARGIN_BYTES);
363469
363519
  opts.hooks?.onAssistantStart?.(rounds);
363470
363520
  const turn = await opts.callModel(messages, specs, {
363471
363521
  onTextDelta: opts.hooks?.onTextDelta,
@@ -363524,14 +363574,17 @@ async function runAgentLoop(opts) {
363524
363574
  messages.push({ role: "assistant", content: final.text });
363525
363575
  return { messages, text: final.text, rounds, exhausted: true, stopped: false };
363526
363576
  }
363527
- var DEFAULT_MAX_ROUNDS, DEFAULT_MAX_PARALLEL, KEEP_IMAGE_TURNS, RENDER_TURN_PREFIX;
363577
+ var DEFAULT_MAX_ROUNDS, DEFAULT_MAX_PARALLEL, KEEP_IMAGE_TURNS, RENDER_TURN_PREFIX, REQUEST_MARGIN_BYTES, sizeOf2;
363528
363578
  var init_loop = __esm({
363529
363579
  "lib/agent/loop.ts"() {
363530
363580
  "use strict";
363581
+ init_gateway();
363531
363582
  DEFAULT_MAX_ROUNDS = 12;
363532
363583
  DEFAULT_MAX_PARALLEL = 4;
363533
363584
  KEEP_IMAGE_TURNS = 2;
363534
363585
  RENDER_TURN_PREFIX = "Result of ";
363586
+ REQUEST_MARGIN_BYTES = 64e3;
363587
+ sizeOf2 = (messages) => JSON.stringify(messages).length;
363535
363588
  }
363536
363589
  });
363537
363590
 
@@ -397116,7 +397169,6 @@ function record(source, namespaces, globals, limits) {
397116
397169
  var HELPER_NAMES;
397117
397170
  var init_helper_names = __esm({
397118
397171
  "lib/agent/design-script/helper-names.ts"() {
397119
- "use strict";
397120
397172
  HELPER_NAMES = ["draw", "marks", "fit", "motion", "captions", "overlays", "texture", "pointer", "windows", "devices", "type", "beat", "web", "social", "video", "site", "effects"];
397121
397173
  }
397122
397174
  });
@@ -409875,7 +409927,7 @@ init_resources();
409875
409927
  init_desktop();
409876
409928
  init_hypery();
409877
409929
  import { createInterface } from "node:readline";
409878
- var VERSION2 = "0.33.0";
409930
+ var VERSION2 = "0.34.1";
409879
409931
  var HELP = `popcraft ${VERSION2} \u2014 the PopCraft command line
409880
409932
 
409881
409933
  Files (headless, on .popcraft files):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@popcraft/cli",
3
- "version": "0.33.0",
3
+ "version": "0.34.1",
4
4
  "description": "The PopCraft command line: edit .popcraft files headlessly, call the REST API, publish to the marketplace and manage the desktop app's local plugins, themes, fonts, skills and agents.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://popcraft.app/docs/api/cli",
@@ -34,7 +34,7 @@
34
34
  "esbuild": "0.28.2"
35
35
  },
36
36
  "dependencies": {
37
- "@popcraft/kit": "0.33.0"
37
+ "@popcraft/kit": "0.34.1"
38
38
  },
39
39
  "scripts": {
40
40
  "build": "node build.mjs",