openmates 0.29.0-alpha.9 → 0.31.0-alpha.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 (36) hide show
  1. package/CHANGELOG.md +77 -1
  2. package/README.md +30 -14
  3. package/dist/{chunk-QRCAXXAL.js → chunk-2RBBM2P4.js} +39 -3
  4. package/dist/{chunk-BYYH2YTS.js → chunk-BTHEBTVQ.js} +1 -1
  5. package/dist/{chunk-IXAKWPUK.js → chunk-CRYWZG4N.js} +4103 -3159
  6. package/dist/{chunk-67U3XD2B.js → chunk-F5GPD6LA.js} +1 -5
  7. package/dist/chunk-UZPZHMQK.js +46 -0
  8. package/dist/{chunk-QVCMMBD4.js → chunk-YN6FF7D4.js} +3200 -2212
  9. package/dist/cli-internal-client.d.ts +6 -0
  10. package/dist/cli-internal-client.js +132 -0
  11. package/dist/cli.d.ts +1 -1
  12. package/dist/cli.js +5 -5
  13. package/dist/{client-CCQdkE5S.d.ts → client-Cf2BFZoY.d.ts} +28 -77
  14. package/dist/index.d.ts +29 -15
  15. package/dist/index.js +16 -32
  16. package/dist/{privacyScan-DJCR2FTA.js → privacyScan-BX4MPHS4.js} +1 -1
  17. package/dist/ruleDocuments-7IWMOMA6.js +160 -0
  18. package/dist/sdk-entry.d.ts +62 -4
  19. package/dist/sdk-entry.js +85 -3
  20. package/dist/sdk-session-v1-entry.d.ts +1 -1
  21. package/dist/{sdkApiKeyRust-BW-c6ZkZ.d.ts → sdkApiKeyRust-C2glWiFL.d.ts} +1 -1
  22. package/dist/{sdkTaskOrder-CJPmq9yh.d.ts → sdkTaskOrder-R9Az-Dab.d.ts} +981 -148
  23. package/dist/{tasksCli-V2INK4CH.js → tasksCli-PSN2EWIU.js} +1 -1
  24. package/fixtures/privacy-runtime/linux-arm64/libggml-base.so +0 -0
  25. package/fixtures/privacy-runtime/linux-arm64/libggml-base.so.0 +0 -0
  26. package/fixtures/privacy-runtime/linux-arm64/libggml-base.so.0.15.1 +0 -0
  27. package/fixtures/privacy-runtime/linux-arm64/libggml-cpu.so +0 -0
  28. package/fixtures/privacy-runtime/linux-arm64/libggml-cpu.so.0 +0 -0
  29. package/fixtures/privacy-runtime/linux-arm64/libggml-cpu.so.0.15.1 +0 -0
  30. package/fixtures/privacy-runtime/linux-arm64/libggml.so +0 -0
  31. package/fixtures/privacy-runtime/linux-arm64/libggml.so.0 +0 -0
  32. package/fixtures/privacy-runtime/linux-arm64/libggml.so.0.15.1 +0 -0
  33. package/fixtures/privacy-runtime/linux-arm64/manifest.json +9 -9
  34. package/package.json +4 -4
  35. package/templates/core/docker-compose.selfhost.yml +69 -0
  36. package/dist/ruleDocuments-6VMP2CV5.js +0 -91
package/CHANGELOG.md CHANGED
@@ -1,7 +1,83 @@
1
1
  # Changelog — `openmates` npm package (CLI and SDK)
2
2
 
3
3
  Only SDK-relevant compatibility notes are recorded here. Release versions follow
4
- the product line (`0.29.x` alpha prereleases from `dev`, stable from `main`).
4
+ the product line (`0.29.x` prereleases from `dev`, stable from `main`).
5
+
6
+ ## Unreleased
7
+
8
+ ### Breaking
9
+
10
+ - Rust SDK: `Memories::create`, `update` and `types`, `MemoryInput`,
11
+ `hash_item_key` and `memory_plaintext` are removed, matching npm and Python
12
+ (removed 2026-11-07; the backend answers 410). `IdeaBucket::save_settings` now
13
+ returns the same refusal as npm/Python. `sdk.memories` is implemented in all
14
+ three SDKs.
15
+
16
+ ### Changed
17
+
18
+ - `billing.downloadInvoice`, `billing.downloadCreditNote` and
19
+ `billing.usageExport` now declare the exported `RawDownload` type
20
+ (`contentType`, optional `filename`, `data: ArrayBuffer`); the runtime shape is
21
+ unchanged. `filename` is now always the last path component of the
22
+ `Content-Disposition` name, and is omitted for `.`/`..` names or a malformed
23
+ `filename*` encoding (previously such a header threw a `URIError`). Rust and
24
+ Python follow the same filename contract.
25
+
26
+ Cross-language SDK alignment (npm, Python and Rust now behave the same; each case
27
+ is a shared conformance vector):
28
+
29
+ - **Malformed document slugs are refused locally.** `docs.show()` and
30
+ `docs.download()` throw the new `OpenMatesInvalidInputError`
31
+ (code `OPENMATES_SDK_INVALID_INPUT`) before any request for an empty slug,
32
+ `..`, a leading or trailing `/`, an empty or `.` segment, `\`, `:`, NUL or other
33
+ control characters, or a slug over 4096 bytes. Previously these reached the
34
+ server. Python raises the same error class, which is a `ValueError`.
35
+ - **An empty Wikipedia `language` means English.** `wikipedia.search()`,
36
+ `summary()`, `learning()` and `article()` send `language=en` for `""`, the same
37
+ as an omitted language. Previously npm sent `language=` and the backend
38
+ rejected the request.
39
+ - **Draft preview fallback counts Unicode characters.** When a draft has no saved
40
+ preview, `drafts.get()`/`list()` use the first 160 Unicode characters of the
41
+ markdown instead of 160 UTF-16 code units, so the preview never ends in half an
42
+ emoji. A saved but empty or undecryptable `encryptedDraftPreview` now gives
43
+ `preview: null` instead of falling back to the markdown.
44
+
45
+ ### Added (Python)
46
+
47
+ - `OpenMatesClient(api_key=...)` mirrors the npm root client: a missing or blank
48
+ key raises `OpenMatesApiKeyRequiredError` (code `OPENMATES_SDK_API_KEY_REQUIRED`,
49
+ a subclass of `OpenMatesConfigError`) at construction, it never reads
50
+ `OPENMATES_API_KEY`, and it refuses the legacy `session`/`load_stored_session`
51
+ options. `OpenMates()` is unchanged.
52
+ - Python `embeds.add_to_project()`/`remove_from_project()` resolve a Project
53
+ slug, name or id prefix before routing, as npm does.
54
+
55
+ ## 0.30.0
56
+
57
+ ### Breaking
58
+
59
+ - **The SDK is API-key only and separate from the CLI login.** The root
60
+ `OpenMatesClient` export no longer loads the stored CLI login (the 0.29.x
61
+ `OPENMATES_SDK_CLI_SESSION` deprecation is complete). It is now the API-key
62
+ client: `new OpenMatesClient({ apiKey })`. Constructing it (or calling
63
+ `OpenMatesClient.load()`) without an `apiKey` throws
64
+ `OpenMatesApiKeyRequiredError` (code `OPENMATES_SDK_API_KEY_REQUIRED`), and the
65
+ `session` / `loadStoredSession` options are rejected. No SDK entrypoint reads
66
+ CLI state files or the keychain, so an SDK script can use a different account
67
+ from the logged-in CLI. `SDK_CLI_SESSION_DEPRECATION_CODE` is removed.
68
+
69
+ **Migration:** create an API key in Settings → Developers and pass it
70
+ explicitly (`new OpenMatesClient({ apiKey })` or `new OpenMates({ apiKey })`).
71
+ The key decrypts your chats locally with its own wrapped account key; nothing
72
+ else is needed. The `openmates` command line keeps its own login and is
73
+ unaffected.
74
+
75
+ ### Deprecated
76
+
77
+ - `SessionClient.loginPassword()` / `importSession()` in `openmates/sdk/v1`. Public
78
+ SDKs are API-key only; these login modes are removed once every capability they
79
+ offer is available through API-key authentication (open work tracked in
80
+ `config/sdk-capabilities.json`).
5
81
 
6
82
  ## 0.29.x
7
83
 
package/README.md CHANGED
@@ -62,7 +62,7 @@ openmates whoami --json
62
62
  The CLI displays a QR code or pair PIN. Approve it in the OpenMates web app.
63
63
  During login, the CLI never asks for your account password.
64
64
 
65
- Switch to a dev account using an isolated profile; upgrading to an alpha release
65
+ Switch to a dev account using an isolated profile; upgrading to a prerelease
66
66
  preserves your existing login and does not change the API server:
67
67
 
68
68
  ```bash
@@ -157,6 +157,8 @@ openmates settings --help
157
157
  openmates settings account export data --json
158
158
  openmates settings memories list --json
159
159
  openmates learning-mode status --json
160
+ openmates learning-mode enable --age-group 16_18 --passcode <passcode> --no-collaborative-build
161
+ openmates learning-mode collaborative on --passcode <passcode>
160
162
  openmates docs search "API keys"
161
163
  ```
162
164
 
@@ -375,23 +377,37 @@ Use `chats.send()` for anonymous AI chat with automatic routing; `apps.ai.ask()`
375
377
  requires an account. With an API key, use `saveToAccount: true` when you want the
376
378
  chat saved to the OpenMates account.
377
379
 
378
- ### Deprecated: implicit CLI login in the root `OpenMatesClient`
380
+ ### API keys only, never the CLI login
379
381
 
380
- `new OpenMatesClient()` / `OpenMatesClient.load()` from the root `openmates`
381
- export still load the stored CLI login when no `session` is passed, but this is
382
- deprecated: SDK credentials must be explicit. It emits one `DeprecationWarning`
383
- with code `OPENMATES_SDK_CLI_SESSION` per process. Pass `session` explicitly,
384
- set `loadStoredSession: false`, or use `SessionClient` from `openmates/sdk/v1`.
385
- A later minor release will require explicit credentials (see `CHANGELOG.md`).
386
- The `openmates` command line is unaffected.
382
+ The SDK authenticates only with an API key you pass explicitly (or configure via
383
+ `OPENMATES_API_KEY`). It is completely separate from the `openmates` command
384
+ line: it never reads the CLI's `~/.openmates/session.json`, its state directory
385
+ or the OS keychain, so a script can use a different account than the one logged
386
+ in to the CLI. Create an API key in Settings → Developers. Each key carries its
387
+ own wrapped copy of your account key, so the SDK decrypts your chats locally,
388
+ in memory, with only that key.
389
+
390
+ Since 0.31.0 the root `OpenMatesClient` is the API-key client and requires
391
+ `apiKey`; constructing it without one throws `OpenMatesApiKeyRequiredError`
392
+ (code `OPENMATES_SDK_API_KEY_REQUIRED`). The former `session` and
393
+ `loadStoredSession` options are rejected.
394
+
395
+ ```typescript
396
+ import { OpenMatesClient } from "openmates";
397
+
398
+ const om = new OpenMatesClient({ apiKey: process.env.MY_OPENMATES_KEY! });
399
+ ```
387
400
 
388
401
  ### Native session SDK (preview)
389
402
 
390
403
  `openmates/sdk/v1` exports `SessionClient`, `RustApiKeyClient` and related
391
404
  types. Every operation runs in the shared OpenMates Rust core through a native
392
405
  Node-API module loaded from `native/<platform>-<arch>.node`; the SDK never
393
- launches the CLI and never reads CLI login state. Credentials are explicit:
394
- log in with `loginPassword()` or import a caller-owned session. If the native
406
+ launches the CLI and never reads CLI login state. Its password/imported-session
407
+ login modes (`loginPassword()`, `importSession()`) are deprecated: public SDKs
408
+ are API-key only, and these modes are removed once every capability they offer
409
+ is available through API-key authentication (tracked in
410
+ `config/sdk-capabilities.json`). Use an API key for new integrations. If the native
395
411
  module for your platform is missing or incompatible, construction throws
396
412
  `SessionClientError` with code `native_binding_unavailable` (no TypeScript
397
413
  fallback). The SDK is moving to one portable WebAssembly build of the core
@@ -402,12 +418,12 @@ artifacts are not yet published; from a source checkout run
402
418
 
403
419
  ## Versioning
404
420
 
405
- OpenMates shows the short product line, for example `v0.29`, in the web app.
421
+ OpenMates shows the short product line, for example `v0.31`, in the web app.
406
422
  The npm package uses exact artifact versions:
407
423
 
408
- - `0.29.0-alpha.N` is a prerelease from the `dev` branch published under the
424
+ - `0.31.0-alpha.N` is a prerelease from the `dev` branch published under the
409
425
  `alpha` npm tag.
410
- - `0.29.0` is a stable release from `main` published under the `latest` npm tag.
426
+ - `0.31.0` is a stable release from `main` published under the `latest` npm tag.
411
427
 
412
428
  Install stable releases with `npm install -g openmates`. Install prereleases with
413
429
  `npm install -g openmates@alpha`.
@@ -18,6 +18,39 @@ function codingIdentifierRanges(text) {
18
18
  return ranges;
19
19
  }
20
20
 
21
+ // ../secret-scanner/src/embedReferenceRanges.ts
22
+ var EMBED_LINK_TARGET = /\(embed:[^\s)]+\)/g;
23
+ var JSON_FENCE_OPEN = "```json\n";
24
+ var JSON_BLOCK = /```json\n([\s\S]*?)\n```/g;
25
+ var EMBED_ID_MEMBER = /"embed_id"\s*:\s*"(?:\\.|[^"\\])*"|"embed_ids"\s*:\s*\[(?:\s*"(?:\\.|[^"\\])*"\s*,?)*\s*\]/g;
26
+ function isEmbedReferenceJson(body) {
27
+ let parsed;
28
+ try {
29
+ parsed = JSON.parse(body.trim());
30
+ } catch {
31
+ return false;
32
+ }
33
+ return typeof parsed === "object" && parsed !== null && ("embed_id" in parsed || "embed_ids" in parsed);
34
+ }
35
+ function embedReferenceRanges(text) {
36
+ if (!text.includes("embed")) return [];
37
+ const ranges = [];
38
+ for (const match of Array.from(text.matchAll(EMBED_LINK_TARGET))) {
39
+ ranges.push({ start: match.index, end: match.index + match[0].length });
40
+ }
41
+ for (const match of Array.from(text.matchAll(JSON_BLOCK))) {
42
+ if (!isEmbedReferenceJson(match[1])) continue;
43
+ const bodyStart = match.index + JSON_FENCE_OPEN.length;
44
+ for (const member of Array.from(match[1].matchAll(EMBED_ID_MEMBER))) {
45
+ ranges.push({ start: bodyStart + member.index, end: bodyStart + member.index + member[0].length });
46
+ }
47
+ }
48
+ return ranges.sort((a, b) => a.start - b.start);
49
+ }
50
+ function overlapsAnyRange(start, end, ranges) {
51
+ return ranges.some((range) => start < range.end && end > range.start);
52
+ }
53
+
21
54
  // ../ui/src/components/enter_message/services/piiDetectionService.ts
22
55
  function luhnCheck(cardNumber) {
23
56
  const digits = cardNumber.replace(/\D/g, "");
@@ -519,6 +552,7 @@ function detectPII(text, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
519
552
  });
520
553
  }
521
554
  const hasUrlExclusions = urlExclusionZones.length > 0;
555
+ const embedZones = embedReferenceRanges(text);
522
556
  if (text.length >= MIN_PII_TEXT_LENGTH) {
523
557
  for (const pattern of PII_PATTERNS) {
524
558
  if (hasDisabledCategories) {
@@ -532,6 +566,7 @@ function detectPII(text, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
532
566
  const startIndex = regexMatch.index;
533
567
  const endIndex = startIndex + matchText.length;
534
568
  if (pattern.type === "PHONE" && identifierRanges.some((range) => startIndex < range.end && endIndex > range.start)) continue;
569
+ if (overlapsAnyRange(startIndex, endIndex, embedZones)) continue;
535
570
  if (hasUrlExclusions) {
536
571
  const insideUrl = urlExclusionZones.some(
537
572
  (zone) => startIndex >= zone.start && endIndex <= zone.end
@@ -584,7 +619,7 @@ function detectPII(text, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
584
619
  const overlaps = coveredRanges.some(
585
620
  (range) => startIndex >= range.start && startIndex < range.end || endIndex > range.start && endIndex <= range.end || startIndex <= range.start && endIndex >= range.end
586
621
  );
587
- if (!overlaps) {
622
+ if (!overlaps && !overlapsAnyRange(startIndex, endIndex, embedZones)) {
588
623
  const matchText = text.substring(startIndex, endIndex);
589
624
  const matchId = `pii-PERSONAL_DATA-${entry.id}-${startIndex}`;
590
625
  if (!hasExclusions || !excludedIds.has(matchId)) {
@@ -732,7 +767,8 @@ var ProjectFilePrivacy = class {
732
767
  const literal = text.slice(range.start, range.end);
733
768
  if (!(this.options.preserveMappedTokens && this.values.has(literal)) && (this.values.has(literal) || GENERATED_TOKEN.test(literal) || legacyToken(literal))) ranges.push(range);
734
769
  }
735
- const overlaps = (start, end) => [...tokens, ...ranges].some((r) => start < r.end && end > r.start);
770
+ const shields = [...tokens, ...embedReferenceRanges(text)];
771
+ const overlaps = (start, end) => [...shields, ...ranges].some((r) => start < r.end && end > r.start);
736
772
  for (const mapping of Array.from(this.values.values()).sort((a, b) => b.original.length - a.original.length)) {
737
773
  let start = text.indexOf(mapping.original);
738
774
  while (start !== -1) {
@@ -748,7 +784,7 @@ var ProjectFilePrivacy = class {
748
784
  for (const range of enhanced) {
749
785
  if (!Number.isInteger(range.start) || !Number.isInteger(range.end) || range.start < 0 || range.end <= range.start || range.end > text.length) fail("pii_invalid_semantic_range");
750
786
  let fragments = [{ ...range }];
751
- for (const shield of [...tokens, ...ranges]) fragments = fragments.flatMap((part) => {
787
+ for (const shield of [...shields, ...ranges]) fragments = fragments.flatMap((part) => {
752
788
  if (part.start >= shield.end || part.end <= shield.start) return [part];
753
789
  return [
754
790
  part.start < shield.start ? { ...part, end: shield.start } : null,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  loadSdkWasm
3
- } from "./chunk-QVCMMBD4.js";
3
+ } from "./chunk-YN6FF7D4.js";
4
4
  import {
5
5
  SessionClientError
6
6
  } from "./chunk-6AR2CP7K.js";