@calmlens/sdk 0.17.1 → 0.18.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.
Files changed (60) hide show
  1. package/README.md +46 -37
  2. package/bin/calmlens.js +16016 -0
  3. package/bin/package.json +1 -0
  4. package/{esm/BrowserUpload-uZjVFGfP.d.ts → cjs/BrowserUpload-BT091eOB.d.ts} +2 -2
  5. package/cjs/{BrowserUpload-DZ0Vbmxi.js → BrowserUpload-CQwXEGFv.js} +1 -1
  6. package/cjs/{CalmLensAppClient-DBGmaDlG.js → CalmLensAppClient-CHQGu-Do.js} +2 -2
  7. package/cjs/{CalmLensConnection-K1TAD1Z-.js → CalmLensConnection-B8Bu2j3y.js} +2 -2
  8. package/cjs/{CalmLensServerClient-C-pxiz0C.js → CalmLensServerClient-C5o2A8MW.js} +3 -3
  9. package/cjs/{ModerationContextLimits-Dj1YAl3G.js → ModerationContextLimits-DelWfmiJ.js} +1 -1
  10. package/cjs/{ReactUpload-nZahpmyg.d.ts → ReactUpload-CAyCsyG6.d.ts} +1 -1
  11. package/cjs/{ReactUpload-DxtFMr06.js → ReactUpload-Cfg5JYUq.js} +1 -1
  12. package/cjs/{TestTriggers-DcArt0Nu-CvoaONUB.js → TestTriggers-DTc_iMJF-BjMPq4_3.js} +10 -9
  13. package/cjs/{UploadController-BBkN4Ni6.js → UploadController-BGO1eyzb.js} +2 -2
  14. package/cjs/app.js +2 -2
  15. package/cjs/elements.d.ts +2 -2
  16. package/cjs/elements.js +3 -3
  17. package/cjs/index.js +1 -1
  18. package/cjs/react-native.d.ts +2 -2
  19. package/cjs/react-native.js +3 -3
  20. package/cjs/react.d.ts +2 -2
  21. package/cjs/react.js +4 -4
  22. package/cjs/server.js +2 -2
  23. package/cjs/test-inputs.js +9 -9
  24. package/cjs/testing.d.ts +1 -1
  25. package/cjs/testing.js +8 -8
  26. package/cjs/{ui-KceuoVCM.js → ui-CC1GOoMg.js} +4 -4
  27. package/{esm/ui-CgZpgpNo.d.ts → cjs/ui-wIiMfqMB.d.ts} +3 -3
  28. package/cjs/ui.d.ts +1 -1
  29. package/cjs/ui.js +2 -2
  30. package/cjs/vue.d.ts +2 -2
  31. package/cjs/vue.js +3 -3
  32. package/{cjs/BrowserUpload-uZjVFGfP.d.ts → esm/BrowserUpload-BT091eOB.d.ts} +2 -2
  33. package/esm/{BrowserUpload-D7-zNmc0.js → BrowserUpload-D2xBWqhm.js} +1 -1
  34. package/esm/{CalmLensAppClient-FVMwrHlH.js → CalmLensAppClient-DuFas_dW.js} +2 -2
  35. package/esm/{CalmLensConnection-iyNQHA8L.js → CalmLensConnection-MxwwLXdl.js} +2 -2
  36. package/esm/{CalmLensServerClient-fQEYKLw4.js → CalmLensServerClient-D80_mKpW.js} +3 -3
  37. package/esm/{ModerationContextLimits-D1x_WAtP.js → ModerationContextLimits-BaX2QnU8.js} +1 -1
  38. package/esm/{ReactUpload-nZahpmyg.d.ts → ReactUpload-CAyCsyG6.d.ts} +1 -1
  39. package/esm/{ReactUpload-D6yBCkcw.js → ReactUpload-CL2XC8WS.js} +1 -1
  40. package/esm/{TestTriggers-DcArt0Nu-s0AQZuWE.js → TestTriggers-DTc_iMJF-HfB533Gx.js} +10 -9
  41. package/esm/{UploadController-txp5NuzH.js → UploadController-qjoYGCwx.js} +2 -2
  42. package/esm/app.js +2 -2
  43. package/esm/elements.d.ts +2 -2
  44. package/esm/elements.js +3 -3
  45. package/esm/index.js +1 -1
  46. package/esm/react-native.d.ts +2 -2
  47. package/esm/react-native.js +3 -3
  48. package/esm/react.d.ts +2 -2
  49. package/esm/react.js +4 -4
  50. package/esm/server.js +2 -2
  51. package/esm/test-inputs.js +1 -1
  52. package/esm/testing.d.ts +1 -1
  53. package/esm/testing.js +6 -6
  54. package/esm/{ui-Ca_SpJXf.js → ui-CCY3yXFn.js} +4 -4
  55. package/{cjs/ui-CgZpgpNo.d.ts → esm/ui-wIiMfqMB.d.ts} +3 -3
  56. package/esm/ui.d.ts +1 -1
  57. package/esm/ui.js +2 -2
  58. package/esm/vue.d.ts +2 -2
  59. package/esm/vue.js +3 -3
  60. package/package.json +9 -3
package/README.md CHANGED
@@ -1,23 +1,23 @@
1
- # @calmlens/sdk
1
+ # CalmLens JavaScript SDK
2
2
 
3
- Official JavaScript/TypeScript SDK for CalmLens API
4
-
5
- CalmLens provides content moderation and classification for text, images, documents and websites, plus optional storage and CDN delivery. This SDK makes it easy to integrate CalmLens into your JavaScript/TypeScript applications.
3
+ The official JavaScript and TypeScript SDK for [CalmLens](https://calmlens.com): content moderation and classification for text, images, documents and websites, plus optional storage and CDN delivery.
6
4
 
7
5
  ## Installation
8
6
 
9
7
  ```bash
10
- npm install @calmlens/sdk
8
+ npm install calmlens
11
9
  ```
12
10
 
11
+ The same package is also published as `@calmlens/sdk`, at the same version. Import from the name you installed: `calmlens/server` with `calmlens`, or `@calmlens/sdk/server` with `@calmlens/sdk`.
12
+
13
13
  The package has two clients, each with its own import:
14
14
 
15
- | Import | Client | Runs | Authenticates with |
16
- | ---------------------- | ---------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
17
- | `@calmlens/sdk/server` | `CalmLensServerClient` | On your server: Node.js 22 or later, Bun, Deno, Cloudflare Workers | A project API key |
18
- | `@calmlens/sdk/app` | `CalmLensAppClient` | In browsers and React Native apps | An [upload preset](#browser-and-app-uploads-with-upload-presets), with an optional upload token from your server |
15
+ | Import | Client | Runs | Authenticates with |
16
+ | ----------------- | ---------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
17
+ | `calmlens/server` | `CalmLensServerClient` | On your server: Node.js 22 or later, Bun, Deno, Cloudflare Workers | A project API key |
18
+ | `calmlens/app` | `CalmLensAppClient` | In browsers and React Native apps | An [upload preset](#browser-and-app-uploads-with-upload-presets), with an optional upload token from your server |
19
19
 
20
- `@calmlens/sdk` itself exports the shared types, `CalmLensError`, the error codes and `SDK_VERSION`. The package ships ES modules and CommonJS with type declarations and loads no other packages at runtime: importing only `verifyWebhookSignature` adds about 5 KB (minified) to a bundle, `CalmLensAppClient` about 19 KB and `CalmLensServerClient` about 28 KB.
20
+ `calmlens` itself exports the shared types, `CalmLensError`, the error codes and `SDK_VERSION`. The package ships ES modules and CommonJS with type declarations and loads no other packages at runtime: importing only `verifyWebhookSignature` adds about 5 KB (minified) to a bundle, `CalmLensAppClient` about 19 KB and `CalmLensServerClient` about 28 KB.
21
21
 
22
22
  API keys are secret, so `CalmLensServerClient` refuses to start in a web page or app. Upload from browsers and apps with `CalmLensAppClient`, and serve private content to them with [signed URLs](#assetscreatesignedurloptions).
23
23
 
@@ -28,7 +28,7 @@ Every public SDK operation accepts one options object. This keeps call sites sta
28
28
  Create an API key under **Developer → API Keys** in the CalmLens portal. The same page shows your **Project ID**. Keep both on your server.
29
29
 
30
30
  ```typescript
31
- import { CalmLensServerClient } from "@calmlens/sdk/server";
31
+ import { CalmLensServerClient } from "calmlens/server";
32
32
 
33
33
  const client = new CalmLensServerClient({
34
34
  apiKey: process.env.CALMLENS_API_KEY!,
@@ -72,7 +72,7 @@ See [How CalmLens works](https://calmlens.com/docs/how-it-works) and [Testing yo
72
72
 
73
73
  ### CalmLensServerClient
74
74
 
75
- The client for your server, with every API method. Import it from `@calmlens/sdk/server`.
75
+ The client for your server, with every API method. Import it from `calmlens/server`.
76
76
 
77
77
  #### Constructor
78
78
 
@@ -510,11 +510,11 @@ age-restricted image. It takes no `lens` or `transform`; passing one throws `sdk
510
510
 
511
511
  ##### Building CDN URLs in the browser
512
512
 
513
- `getAssetUrl`, exported from `@calmlens/sdk/app` and `@calmlens/sdk`, builds the same URLs as `cdn.getAssetUrl` from
513
+ `getAssetUrl`, exported from `calmlens/app` and `calmlens`, builds the same URLs as `cdn.getAssetUrl` from
514
514
  the project ID alone. It takes no API key and sends no request.
515
515
 
516
516
  ```typescript
517
- import { getAssetUrl } from "@calmlens/sdk/app";
517
+ import { getAssetUrl } from "calmlens/app";
518
518
 
519
519
  const placeholder = getAssetUrl({ projectId, assetIdentifier: assetId, resource: "placeholder" });
520
520
  const thumbnail = getAssetUrl({ projectId, assetIdentifier: assetId, lens: "thumbnail" });
@@ -607,7 +607,7 @@ It returns `true` only when the `x-calmlens-signature` header contains a `v1=` H
607
607
  `CalmLensAppClient` uploads from a browser or app through an upload preset, without an API key. Create presets in the portal under Developer → Upload presets.
608
608
 
609
609
  ```ts
610
- import { CalmLensAppClient } from "@calmlens/sdk/app";
610
+ import { CalmLensAppClient } from "calmlens/app";
611
611
 
612
612
  // In the browser: no API key
613
613
  const client = new CalmLensAppClient({
@@ -648,20 +648,20 @@ Server uploads can also pass `uploadPresetId` to `assets.create` or `assets.clas
648
648
 
649
649
  Ready-made front-end components for each UI library. They share one core, so they behave the same everywhere:
650
650
 
651
- | Import | Components |
652
- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
653
- | `@calmlens/sdk/react` | `CalmLensUploader`, `CalmLensMedia`, `useCalmLensUpload` (also works in Preact through `preact/compat`) |
654
- | `@calmlens/sdk/vue` | `CalmLensUploader`, `CalmLensMedia`, `useCalmLensUpload` |
655
- | `@calmlens/sdk/svelte` | `CalmLensUploader`, `CalmLensMedia` (Svelte 5) |
656
- | `@calmlens/sdk/elements` | `<calmlens-uploader>`, `<calmlens-media>` for plain HTML, Angular, Solid, Lit and anything else that renders custom elements |
657
- | `@calmlens/sdk/ui` | The framework-free core: `createUploadController`, `getMediaState`, messages and styles |
651
+ | Import | Components |
652
+ | ------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
653
+ | `calmlens/react` | `CalmLensUploader`, `CalmLensMedia`, `useCalmLensUpload` (also works in Preact through `preact/compat`) |
654
+ | `calmlens/vue` | `CalmLensUploader`, `CalmLensMedia`, `useCalmLensUpload` |
655
+ | `calmlens/svelte` | `CalmLensUploader`, `CalmLensMedia` (Svelte 5) |
656
+ | `calmlens/elements` | `<calmlens-uploader>`, `<calmlens-media>` for plain HTML, Angular, Solid, Lit and anything else that renders custom elements |
657
+ | `calmlens/ui` | The framework-free core: `createUploadController`, `getMediaState`, messages and styles |
658
658
 
659
659
  `react`, `vue` and `svelte` are optional peer dependencies: install the one you use.
660
660
 
661
661
  **The uploader** is a drop zone with a file list. It uploads each file through `CalmLensAppClient`, shows byte progress, checks the upload until it has a moderation decision (for about 15 seconds; anything still pending is your webhook's to settle), and shows the decision or a message for each error code.
662
662
 
663
663
  ```tsx
664
- import { CalmLensUploader } from "@calmlens/sdk/react";
664
+ import { CalmLensUploader } from "calmlens/react";
665
665
 
666
666
  <CalmLensUploader
667
667
  uploadPresetId="preset_4Lk8Qw2Xm9Rt5Vb3Nc7P"
@@ -680,7 +680,7 @@ To upload through your own API instead of a preset, pass `upload(file, { signal,
680
680
  **The media component** shows an asset from the CDN's `rendered` resource in a single `<img>`, so the CDN picks the best format the browser accepts. It adds `srcset` widths when you pass `widths` and `sizes`, shows the blurred placeholder while the image loads, and fades the image in. Video and audio play the `original` file, with a rendered poster for video. Age-restricted assets stay behind the placeholder and a notice with a reveal button until you pass `viewerClaims: { ageConfirmed: true }`. Blocked and purged assets, and images that fail to load, show an unavailable notice.
681
681
 
682
682
  ```tsx
683
- import { CalmLensMedia } from "@calmlens/sdk/react";
683
+ import { CalmLensMedia } from "calmlens/react";
684
684
 
685
685
  <CalmLensMedia
686
686
  projectId="proj_8fK2mQx7Lp4NvB3tRz9Y"
@@ -699,7 +699,7 @@ Instead of `projectId` and `assetId`, you can pass an asset from the API as `ass
699
699
 
700
700
  It also takes `type` (`image`, `video` or `audio`), `resource`, `lens`, `transform`, `url` (a signed URL from your server), `placeholderHash` (the asset's `content.image.thumbhash`, drawn in the browser so no placeholder request is needed), `placeholderUrl`, `averageColor`, `fit`, `position`, `lazy`, `fetchPriority` and `controls`.
701
701
 
702
- The React components render their stylesheet with them: React places it in the page's head once, on the server too. With Vue, Svelte or the web components, import `@calmlens/sdk/styles.css` once (or link it). Nothing is added to the page at runtime. Theme the components with `--calmlens-accent`, `--calmlens-radius` and the other `--calmlens-*` properties, which take precedence on any element. To style the `calmlens-*` classes yourself, pass `unstyled` to the React components, or leave out the stylesheet import. All text can be replaced or translated with `messages`, keyed by message name or error code.
702
+ The React components render their stylesheet with them: React places it in the page's head once, on the server too. With Vue, Svelte or the web components, import `calmlens/styles.css` once (or link it). Nothing is added to the page at runtime. Theme the components with `--calmlens-accent`, `--calmlens-radius` and the other `--calmlens-*` properties, which take precedence on any element. To style the `calmlens-*` classes yourself, pass `unstyled` to the React components, or leave out the stylesheet import. All text can be replaced or translated with `messages`, keyed by message name or error code.
703
703
 
704
704
  The [widget playground](https://github.com/CalmLens/sdks/tree/main/examples/widget-playground) runs every component against a mock API.
705
705
 
@@ -748,7 +748,7 @@ See the [classification results guide](https://calmlens.com/docs/guides/classifi
748
748
  Every failure is a `CalmLensError`, whether the API returned an error or the request never completed. Branch on its stable `code`:
749
749
 
750
750
  ```typescript
751
- import { CALMLENS_ERROR_CODES, CalmLensError } from "@calmlens/sdk";
751
+ import { CALMLENS_ERROR_CODES, CalmLensError } from "calmlens";
752
752
 
753
753
  try {
754
754
  await client.assets.retrieve({ assetId });
@@ -810,12 +810,12 @@ The SDK does not validate responses against its types, so fields and values adde
810
810
 
811
811
  ## Testing
812
812
 
813
- `@calmlens/sdk/testing` exports `MockCalmLensServerClient` and `MockCalmLensAppClient`, which run the real clients against an in-memory CalmLens API and CDN, in-memory storage implementations, mock API key helpers, webhook delivery builders and `generateMediaTestCode`, for testing without network requests. `generateMediaTestCode(signal, testInputKey)` asynchronously returns the spoken or on-screen test phrase authenticated with your project's secret test input key, shown under **Assets → Try it → Test inputs** in the portal; a phrase with another project's key is moderated normally.
813
+ `calmlens/testing` exports `MockCalmLensServerClient` and `MockCalmLensAppClient`, which run the real clients against an in-memory CalmLens API and CDN, in-memory storage implementations, mock API key helpers, webhook delivery builders and `generateMediaTestCode`, for testing without network requests. `generateMediaTestCode(signal, testInputKey)` asynchronously returns the spoken or on-screen test phrase authenticated with your project's secret test input key, shown under **Assets → Try it → Test inputs** in the portal; a phrase with another project's key is moderated normally.
814
814
 
815
- The `@calmlens/sdk`, `/server` and `/app` entry points do not load or export testing helpers, to keep production bundles small. Keep `/testing` imports in test files.
815
+ The `calmlens`, `/server` and `/app` entry points do not load or export testing helpers, to keep production bundles small. Keep `/testing` imports in test files.
816
816
 
817
817
  ```typescript
818
- import { MockCalmLensServerClient, createMockApiKey } from "@calmlens/sdk/testing";
818
+ import { MockCalmLensServerClient, createMockApiKey } from "calmlens/testing";
819
819
 
820
820
  const client = new MockCalmLensServerClient({
821
821
  apiKey: createMockApiKey(),
@@ -832,7 +832,7 @@ The in-memory API behaves like CalmLens where tests depend on it: `assets.list`
832
832
  `mockOptions.moderate` decides each asset the mock moderates. It receives the stored `asset`, its `content` (`bytes`, and `text` for a plain-text upload), the `trigger` (`upload`, `retry`, `rerun` or `complete`) and whether the API would `queued` the work, and returns a status (`pending`, `failed`, `allowed`, `limited`, `age-restricted`, `blocked` or `purged`) or a decision built with `mockDecision`. A decision fills the asset's report as CalmLens does: every category (unflagged ones evaluated with score 0), the policy's actions and `flaggedCategories`. Without `moderate`, queued uploads, retries and reruns stay `pending` and everything else is `allowed`. `client.completeProcessing(assetId, decision?)` finishes a pending asset as the pipeline would, with the decision given or the one `moderate` returns for `complete`:
833
833
 
834
834
  ```typescript
835
- import { MockCalmLensServerClient, createMockApiKey, mockDecision } from "@calmlens/sdk/testing";
835
+ import { MockCalmLensServerClient, createMockApiKey, mockDecision } from "calmlens/testing";
836
836
 
837
837
  const client = new MockCalmLensServerClient({
838
838
  apiKey: createMockApiKey(),
@@ -878,7 +878,7 @@ expect(client.callsTo("text.classify").at(-1)).toMatchObject({ body: "hello", st
878
878
  To test a webhook handler, build a signed delivery the way CalmLens sends it:
879
879
 
880
880
  ```typescript
881
- import { createWebhookHeaders, toWebhookEventPayload } from "@calmlens/sdk/testing";
881
+ import { createWebhookHeaders, toWebhookEventPayload } from "calmlens/testing";
882
882
 
883
883
  const event = await client.enqueueEvent({ type: "asset.allowed", assetId: asset.id });
884
884
  const body = JSON.stringify(toWebhookEventPayload(event));
@@ -928,7 +928,7 @@ The result is typed as an extensible `WebhookEventPayload`. Event types and fact
928
928
  **Fetch API** (Next.js route handlers, Remix, Cloudflare Workers, Bun, Deno):
929
929
 
930
930
  ```typescript
931
- import { CalmLensError, parseWebhookEvent } from "@calmlens/sdk/server";
931
+ import { CalmLensError, parseWebhookEvent } from "calmlens/server";
932
932
 
933
933
  export async function POST(request: Request) {
934
934
  let event;
@@ -972,13 +972,20 @@ app.post("/api/webhooks/calmlens", express.raw({ type: "application/json" }), as
972
972
 
973
973
  ## Command-line tool
974
974
 
975
- Install the standalone [CalmLens CLI](https://calmlens.com/docs/guides/local-development) through Homebrew, a platform download or npm. Webhook connectors must use public HTTPS URLs, so during development use it to forward events to a local handler instead. Each event is sent with the same body, headers and signature as a real delivery:
975
+ This package includes the `calmlens` [CLI](https://calmlens.com/docs/guides/local-development). Because the package is named `calmlens`, you can run it without adding a dependency:
976
976
 
977
977
  ```bash
978
978
  npx calmlens listen --forward-to http://localhost:3000/api/webhooks/calmlens --env-file .env.local
979
979
  ```
980
980
 
981
- The CLI reads `CALMLENS_API_KEY`, `CALMLENS_PROJECT_ID` and `CALMLENS_WEBHOOK_SECRET` from the environment or `--env-file`; without a secret it prints a generated one for your app. `npx calmlens trigger [harassment|hate|criminal-activity|clean]` moderates a harmless test input so events appear (one upload each). Run `npx calmlens --help` for all options. To install the command globally, use `npm install -g calmlens`. The CLI is released separately from the SDK.
981
+ Install it globally with `npm install -g calmlens`. In a project that depends on the SDK, `npx calmlens` runs the installed version. Standalone executables for macOS, Linux and Windows, which need no Node.js, are attached to the [CLI releases](https://github.com/CalmLens/sdks/releases?q=cli-v&expanded=true) with a `SHA256SUMS` file, and Homebrew installs them:
982
+
983
+ ```bash
984
+ brew tap calmlens/sdks https://github.com/CalmLens/sdks
985
+ brew install calmlens/sdks/calmlens
986
+ ```
987
+
988
+ Webhook connectors must use public HTTPS URLs, so during development use `listen` to forward events to a local handler instead. Each event is sent with the same body, headers and signature as a real delivery. The CLI reads `CALMLENS_API_KEY`, `CALMLENS_PROJECT_ID` and `CALMLENS_WEBHOOK_SECRET` from the environment or `--env-file`, or uses the key from `calmlens login`; without a secret it prints a generated one for your app. `npx calmlens trigger [harassment|hate|criminal-activity|clean]` moderates a harmless test input so events appear (one upload each). Run `npx calmlens --help` for all options. The CLI's version is the SDK's version.
982
989
 
983
990
  The same feed is available in code with [`events.list`](#events-feed).
984
991
 
@@ -1029,11 +1036,13 @@ Requests send `User-Agent: calmlens-js/<version> (<runtime>/<version>)` from ser
1029
1036
 
1030
1037
  ## Releasing
1031
1038
 
1032
- Stable releases are published automatically from `main` when packed SDK contents differ from npm `latest` and an SDK Changeset is present. Contributors must run `bun run changeset` to choose the release type and write release notes. CI updates and commits this package's `CHANGELOG.md` automatically. See the repository's [.changeset release guide](../../.changeset/README.md).
1039
+ Run `bun run changeset` to choose the release type and write release notes. Merging the Version SDKs pull request releases the version and updates this package's `CHANGELOG.md`. See the repository's [.changeset release guide](../.changeset/README.md).
1040
+
1041
+ Once the release commit's SDK Tests and SDK examples runs pass, `.github/workflows/release-npm.yml` publishes one build to npm with provenance, as `calmlens` and as `@calmlens/sdk`. The CLI's standalone executables and Homebrew formula are released in this repository under `cli-v<version>` by `.github/workflows/release-cli.yml`. `bun run build:cli` builds the npm entry, `bin/calmlens.js` (the package build includes it), and `bun run build:cli:binary` builds a standalone executable in `dist/`; set `CALMLENS_BUILD_TARGET`, such as `bun-linux-x64`, to cross-compile it.
1033
1042
 
1034
1043
  ### Test-input images
1035
1044
 
1036
- The optional `@calmlens/sdk/test-inputs` entry generates and recognises the same
1045
+ The optional `calmlens/test-inputs` entry generates and recognises the same
1037
1046
  project-specific colour grids used by the CalmLens portal:
1038
1047
 
1039
1048
  ```ts
@@ -1042,7 +1051,7 @@ import {
1042
1051
  detectTestImage,
1043
1052
  generateTestTextCode,
1044
1053
  TEST_INPUT_PRESETS,
1045
- } from "@calmlens/sdk/test-inputs";
1054
+ } from "calmlens/test-inputs";
1046
1055
 
1047
1056
  const input = TEST_INPUT_PRESETS.mixed;
1048
1057
  const image = await paintTestImage(input, projectTestInputKey);