@hraness/slopcamera 3.3.4 → 3.3.5

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/README.md CHANGED
@@ -44,14 +44,14 @@ the rendered output with source, runtime requirements and reproduction steps.
44
44
 
45
45
  ## Install Slopcamera
46
46
 
47
- Slopcamera v3.3.3 corrects wall openings, arched crowns, and Boolean surfaces, and documents [film integration](docs/how-to/parametric-design.md#integrate-a-design-into-an-existing-film).
47
+ Slopcamera v3.3.4 admits image and video references in directing shots, adds a hosted tool API for agent platforms, and shows reproducible workflows across the site and docs.
48
48
 
49
49
  Install [Bun 1.3.14 or newer](https://bun.sh), then install the verified
50
- [Slopcamera v3.3.3 release](https://github.com/hraness/slopcamera/releases/tag/v3.3.3)
50
+ [Slopcamera v3.3.4 release](https://github.com/hraness/slopcamera/releases/tag/v3.3.4)
51
51
  from its canonical archive:
52
52
 
53
53
  ```sh
54
- bun add --global https://github.com/hraness/slopcamera/releases/download/v3.3.3/hraness-slopcamera-3.3.3.tgz
54
+ bun add --global https://github.com/hraness/slopcamera/releases/download/v3.3.4/hraness-slopcamera-3.3.4.tgz
55
55
  slopcamera skill install --target agents
56
56
  ```
57
57
 
@@ -219,6 +219,13 @@ the Vercel CLI is optional. Generate images from text and references, add a voic
219
219
  transcribe sound, or create video shots using the selected model's supported
220
220
  inputs. Availability and pricing come from the live catalog.
221
221
 
222
+ Without a Gateway credential, prepaid Hraness Credits run prompt-only image
223
+ generation through the hosted API: `slopcamera credits topup` prints a hosted
224
+ checkout, `slopcamera credits wait` installs the returned device token, and
225
+ `slopcamera ai image generate --hosted` bills that wallet instead of your own
226
+ Gateway key. A stored token also routes `ai image generate` to the hosted API
227
+ automatically when no Gateway credential is configured.
228
+
222
229
  The released CLI also provides `direct` shot recipes: retain a film
223
230
  budget across attempts, review each take before accepting it, and use an accepted
224
231
  clip's last decoded frame as the next shot's reference. Changed predecessors
@@ -307,7 +314,10 @@ declarative graphs, approvals, and resuming work.
307
314
  There is no Slopcamera account, hosted project database, or browser generation service.
308
315
  Ordinary editing and rendering remain local. Gateway generation and selected
309
316
  cloud analysis use credentials from the local process and request explicit
310
- acknowledgement before uploading named media. This website never accepts a
317
+ acknowledgement before uploading named media. The optional hosted API runs each
318
+ paid image call in an ephemeral workspace against a Hraness Credits device token
319
+ and keeps no credentials or projects; the device token lives in owner-only files
320
+ under the CLI state root and never reaches argv or receipts. This website never accepts a
311
321
  Gateway credential. Native Python requires separate authorization. Custom Bun
312
322
  workflow modules execute when loaded, including during check and plan; review
313
323
  their source first. Both have the current user's access, including potential
@@ -4,7 +4,7 @@ import type { z } from "zod";
4
4
 
5
5
  import type { ApplicationContext } from "./context";
6
6
 
7
- export const SLOPCAMERA_APPLICATION_TOOL_VERSION = "slopcamera-3.3.4" as const;
7
+ export const SLOPCAMERA_APPLICATION_TOOL_VERSION = "slopcamera-3.3.5" as const;
8
8
 
9
9
  export const OPERATION_KINDS = [
10
10
  "scene.audit",
@@ -217,6 +217,7 @@ export type CliCommand =
217
217
  readonly allowCloudUpload: boolean;
218
218
  readonly aspectRatio: string | undefined;
219
219
  readonly count: number;
220
+ readonly hosted: boolean;
220
221
  readonly images: readonly string[];
221
222
  readonly kind: "ai-image-generate";
222
223
  readonly mask: string | undefined;
@@ -334,6 +335,14 @@ export type CliCommand =
334
335
  } & JsonOption)
335
336
  | ({ readonly kind: "menubar"; readonly action: "run" | "install" | "uninstall" | "status"; readonly mode: "foreground" | "background" } & JsonOption)
336
337
  | ({ readonly kind: "outputs" } & JsonOption)
338
+ | ({ readonly kind: "credits-status" } & JsonOption)
339
+ | ({
340
+ readonly email: string | undefined;
341
+ readonly kind: "credits-topup";
342
+ readonly pack: string | undefined;
343
+ } & JsonOption)
344
+ | ({ readonly kind: "credits-wait"; readonly timeout: string } & JsonOption)
345
+ | ({ readonly kind: "credits-forget" } & JsonOption)
337
346
  | ({ readonly kind: "recordings-list"; readonly limit: number } & JsonOption)
338
347
  | ({ readonly kind: "projects-list"; readonly limit: number } & JsonOption)
339
348
  | ({
@@ -997,6 +1006,7 @@ function parseAiImage(argv: readonly string[]): CliCommand {
997
1006
  "--allow-cloud-upload": "flag",
998
1007
  "--aspect-ratio": "value",
999
1008
  "--count": "value",
1009
+ "--hosted": "flag",
1000
1010
  "--image": "repeat",
1001
1011
  "--mask": "value",
1002
1012
  "--max-per-call": "value",
@@ -1031,6 +1041,7 @@ function parseAiImage(argv: readonly string[]): CliCommand {
1031
1041
  allowCloudUpload: optionFlag(parsed, "--allow-cloud-upload"),
1032
1042
  aspectRatio: optionString(parsed, "--aspect-ratio"),
1033
1043
  count,
1044
+ hosted: optionFlag(parsed, "--hosted"),
1034
1045
  images,
1035
1046
  json: optionFlag(parsed, "--json"),
1036
1047
  kind: "ai-image-generate",
@@ -1345,6 +1356,55 @@ function parseAiTranscribe(argv: readonly string[]): CliCommand {
1345
1356
  };
1346
1357
  }
1347
1358
 
1359
+ function parseCredits(argv: readonly string[]): CliCommand {
1360
+ const action = argv[0];
1361
+ if (action === "status") {
1362
+ const parsed = parseOptions(argv.slice(1), JSON_SPEC);
1363
+ exactPositionals(parsed, 0, "slopcamera credits status [--json]");
1364
+ return { kind: "credits-status", json: optionFlag(parsed, "--json") };
1365
+ }
1366
+ if (action === "topup") {
1367
+ const parsed = parseOptions(argv.slice(1), {
1368
+ ...JSON_SPEC,
1369
+ "--email": "value",
1370
+ "--pack": "value",
1371
+ });
1372
+ exactPositionals(parsed, 0, "slopcamera credits topup [--pack <id>] [--email <address>] [--json]");
1373
+ const email = optionString(parsed, "--email");
1374
+ if (email !== undefined && (email.length > 320 || /[\s\u0000-\u001f\u007f]/u.test(email))) {
1375
+ fail("--email must be a nonempty email address without whitespace or control characters.");
1376
+ }
1377
+ const pack = optionString(parsed, "--pack");
1378
+ if (pack !== undefined && !/^[a-z0-9][a-z0-9_-]{0,63}$/u.test(pack)) {
1379
+ fail("--pack must be a pack id such as p10, p25, p50, or p100.");
1380
+ }
1381
+ return {
1382
+ email,
1383
+ json: optionFlag(parsed, "--json"),
1384
+ kind: "credits-topup",
1385
+ pack,
1386
+ };
1387
+ }
1388
+ if (action === "wait") {
1389
+ const parsed = parseOptions(argv.slice(1), {
1390
+ ...JSON_SPEC,
1391
+ "--timeout": "value",
1392
+ });
1393
+ exactPositionals(parsed, 0, "slopcamera credits wait [--timeout <time>] [--json]");
1394
+ return {
1395
+ kind: "credits-wait",
1396
+ json: optionFlag(parsed, "--json"),
1397
+ timeout: optionString(parsed, "--timeout") ?? "30m",
1398
+ };
1399
+ }
1400
+ if (action === "forget") {
1401
+ const parsed = parseOptions(argv.slice(1), JSON_SPEC);
1402
+ exactPositionals(parsed, 0, "slopcamera credits forget [--json]");
1403
+ return { kind: "credits-forget", json: optionFlag(parsed, "--json") };
1404
+ }
1405
+ fail("Usage: slopcamera credits <status|topup|wait|forget> [options]");
1406
+ }
1407
+
1348
1408
  function parseAi(argv: readonly string[]): CliCommand {
1349
1409
  switch (argv[0]) {
1350
1410
  case "models": return parseAiModels(argv.slice(1));
@@ -3589,6 +3649,7 @@ export function parseCliArgs(argv: readonly string[]): CliCommand {
3589
3649
  case "runs": return parseRuns(argv.slice(1));
3590
3650
  case "doctor": return parseDoctor(argv.slice(1));
3591
3651
  case "ai": return parseAi(argv.slice(1));
3652
+ case "credits": return parseCredits(argv.slice(1));
3592
3653
  case "media": return parseMedia(argv.slice(1));
3593
3654
  case "recordings": return parseRecordings(argv.slice(1));
3594
3655
  case "projects": return parseProjects(argv.slice(1));
@@ -110,9 +110,12 @@ const capabilityModules = Object.freeze([
110
110
  { effect: "pure", name: "capabilities" },
111
111
  { effect: "local-read", name: "diagram check" },
112
112
  { effect: "local-derived-write", name: "diagram render" },
113
+ { effect: "local-derived-write", name: "diagram sheets init" },
114
+ { effect: "local-read", name: "diagram sheets check" },
115
+ { effect: "local-derived-write", name: "diagram sheets render" },
113
116
  { effect: "local-derived-write", name: "image vectorize" },
114
117
  ],
115
- description: "Portable diagrams, local vectorization, and the bounded semantic operation projection.",
118
+ description: "Portable diagrams, CLI/SDK drawing sheets, local vectorization, and the bounded semantic operation projection.",
116
119
  moduleId: "slopcamera.capability.diagram-image",
117
120
  operationKeys: diagramImageOperations,
118
121
  profiles: [{
@@ -239,6 +239,13 @@ export function commandHostResourceClaims(
239
239
  case "ai-models-list":
240
240
  case "ai-models-show":
241
241
  return claims(coordinator, ["network"]);
242
+ case "credits-status":
243
+ case "credits-topup":
244
+ case "credits-wait":
245
+ // Bounded hosted-service calls; `wait` polls one claim until payment.
246
+ return claims(coordinator, ["network"]);
247
+ case "credits-forget":
248
+ return [];
242
249
  case "ai-provider-options-inspect":
243
250
  case "align-apply":
244
251
  case "code-init":