@chipmobilesdk/rn-ai 0.4.0 → 0.5.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 (88) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/README.md +5 -2
  3. package/lib/commonjs/config/behaviorConfig.js +283 -0
  4. package/lib/commonjs/config/behaviorConfig.js.map +1 -0
  5. package/lib/commonjs/contract/gateway.js +60 -0
  6. package/lib/commonjs/contract/gateway.js.map +1 -0
  7. package/lib/commonjs/core/aiClient.js +330 -0
  8. package/lib/commonjs/core/aiClient.js.map +1 -0
  9. package/lib/commonjs/core/quotaRequest.js +105 -0
  10. package/lib/commonjs/core/quotaRequest.js.map +1 -0
  11. package/lib/commonjs/diagnostics/errors.js +108 -0
  12. package/lib/commonjs/diagnostics/errors.js.map +1 -0
  13. package/lib/commonjs/diagnostics/messageKeys.js +68 -0
  14. package/lib/commonjs/diagnostics/messageKeys.js.map +1 -0
  15. package/lib/commonjs/index.js +102 -0
  16. package/lib/commonjs/index.js.map +1 -0
  17. package/lib/commonjs/package.json +1 -0
  18. package/lib/commonjs/react/hooks.js +170 -0
  19. package/lib/commonjs/react/hooks.js.map +1 -0
  20. package/lib/commonjs/transport/sseClient.js +151 -0
  21. package/lib/commonjs/transport/sseClient.js.map +1 -0
  22. package/lib/commonjs/transport/timeouts.js +46 -0
  23. package/lib/commonjs/transport/timeouts.js.map +1 -0
  24. package/lib/module/config/behaviorConfig.js +275 -0
  25. package/lib/module/config/behaviorConfig.js.map +1 -0
  26. package/lib/module/contract/gateway.js +56 -0
  27. package/lib/module/contract/gateway.js.map +1 -0
  28. package/lib/module/core/aiClient.js +327 -0
  29. package/lib/module/core/aiClient.js.map +1 -0
  30. package/lib/module/core/quotaRequest.js +102 -0
  31. package/lib/module/core/quotaRequest.js.map +1 -0
  32. package/lib/module/diagnostics/errors.js +99 -0
  33. package/lib/module/diagnostics/errors.js.map +1 -0
  34. package/lib/module/diagnostics/messageKeys.js +61 -0
  35. package/lib/module/diagnostics/messageKeys.js.map +1 -0
  36. package/lib/module/index.js +19 -0
  37. package/lib/module/index.js.map +1 -0
  38. package/lib/module/package.json +1 -0
  39. package/lib/module/react/hooks.js +164 -0
  40. package/lib/module/react/hooks.js.map +1 -0
  41. package/lib/module/transport/sseClient.js +146 -0
  42. package/lib/module/transport/sseClient.js.map +1 -0
  43. package/lib/module/transport/timeouts.js +41 -0
  44. package/lib/module/transport/timeouts.js.map +1 -0
  45. package/lib/typescript/commonjs/config/behaviorConfig.d.ts +119 -0
  46. package/lib/typescript/commonjs/config/behaviorConfig.d.ts.map +1 -0
  47. package/lib/typescript/commonjs/contract/gateway.d.ts +64 -0
  48. package/lib/typescript/commonjs/contract/gateway.d.ts.map +1 -0
  49. package/lib/typescript/commonjs/core/aiClient.d.ts +104 -0
  50. package/lib/typescript/commonjs/core/aiClient.d.ts.map +1 -0
  51. package/lib/typescript/commonjs/core/quotaRequest.d.ts +45 -0
  52. package/lib/typescript/commonjs/core/quotaRequest.d.ts.map +1 -0
  53. package/lib/typescript/commonjs/diagnostics/errors.d.ts +38 -0
  54. package/lib/typescript/commonjs/diagnostics/errors.d.ts.map +1 -0
  55. package/lib/typescript/commonjs/diagnostics/messageKeys.d.ts +46 -0
  56. package/lib/typescript/commonjs/diagnostics/messageKeys.d.ts.map +1 -0
  57. package/lib/typescript/commonjs/index.d.ts +21 -0
  58. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  59. package/lib/typescript/commonjs/package.json +1 -0
  60. package/lib/typescript/commonjs/react/hooks.d.ts +37 -0
  61. package/lib/typescript/commonjs/react/hooks.d.ts.map +1 -0
  62. package/lib/typescript/commonjs/transport/sseClient.d.ts +57 -0
  63. package/lib/typescript/commonjs/transport/sseClient.d.ts.map +1 -0
  64. package/lib/typescript/commonjs/transport/timeouts.d.ts +28 -0
  65. package/lib/typescript/commonjs/transport/timeouts.d.ts.map +1 -0
  66. package/lib/typescript/module/config/behaviorConfig.d.ts +119 -0
  67. package/lib/typescript/module/config/behaviorConfig.d.ts.map +1 -0
  68. package/lib/typescript/module/contract/gateway.d.ts +64 -0
  69. package/lib/typescript/module/contract/gateway.d.ts.map +1 -0
  70. package/lib/typescript/module/core/aiClient.d.ts +104 -0
  71. package/lib/typescript/module/core/aiClient.d.ts.map +1 -0
  72. package/lib/typescript/module/core/quotaRequest.d.ts +45 -0
  73. package/lib/typescript/module/core/quotaRequest.d.ts.map +1 -0
  74. package/lib/typescript/module/diagnostics/errors.d.ts +38 -0
  75. package/lib/typescript/module/diagnostics/errors.d.ts.map +1 -0
  76. package/lib/typescript/module/diagnostics/messageKeys.d.ts +46 -0
  77. package/lib/typescript/module/diagnostics/messageKeys.d.ts.map +1 -0
  78. package/lib/typescript/module/index.d.ts +21 -0
  79. package/lib/typescript/module/index.d.ts.map +1 -0
  80. package/lib/typescript/module/package.json +1 -0
  81. package/lib/typescript/module/react/hooks.d.ts +37 -0
  82. package/lib/typescript/module/react/hooks.d.ts.map +1 -0
  83. package/lib/typescript/module/transport/sseClient.d.ts +57 -0
  84. package/lib/typescript/module/transport/sseClient.d.ts.map +1 -0
  85. package/lib/typescript/module/transport/timeouts.d.ts +28 -0
  86. package/lib/typescript/module/transport/timeouts.d.ts.map +1 -0
  87. package/package.json +40 -12
  88. package/skills/sdk-rn-ai/SKILL.md +8 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,125 @@
1
1
  # @chipmobilesdk/rn-ai
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Every peer range has an upper bound, and no package declares a peer it does not use. ([#21](https://github.com/operationd8979/chip-mobile-sdk/pull/21))
8
+
9
+ A peer range is now a caret, a tilde or an explicit `<`, except for `react` and
10
+ `react-native`: an app brings exactly one of each, so a floor is the only useful thing
11
+ to say about them. Every other peer is a library the app installs beside us, and an
12
+ open `>=` was a promise about versions nobody had run — mmkv 3→4 lost entitlements and
13
+ pending purchases exactly that way.
14
+
15
+ **Four of the new ceilings exclude a version that is already published**, so an app
16
+ that took the open range at its word may now see a peer warning. The new bound is the
17
+ major this release is tested against, which is the thing the old range failed to say:
18
+
19
+ | Peer | Was | Now | Published above the ceiling |
20
+ |---|---|---|---|
21
+ | `react-native-app-auth` (rn-auth) | `>=8` | `^8.0.0` | 9.0.0 |
22
+ | `react-native-keychain` (rn-auth) | `>=10` | `^10.0.0` | 11.0.0 |
23
+ | `@op-engineering/op-sqlite` (rn-local-db) | `>=17.1.0` | `^17.1.0` | 18.x, 19.x |
24
+ | `@react-native-firebase/messaging` (rn-notification) | `>=26.0.0` | `^26.0.0` | 27.x |
25
+
26
+ The others — `react-native-vision-camera` `^5.1.1`, `react-native-svg` `^15.15.0`,
27
+ `react-native-unistyles` `^3.2.0`, `@dr.pogodin/react-native-fs` `^2.39.2`,
28
+ `react-native-quick-crypto` `^1.0.0`, `react-native-notify-kit` `^10.5.0`,
29
+ `react-native-localize` `^3.7.0`, `react-native-mmkv` `^4.0.0` — exclude nothing that
30
+ exists today. rn-payment's mmkv range was already bounded (`>=4.0.0 <5`) and is now
31
+ written as the caret that means the same thing.
32
+
33
+ Peers nothing imports are gone. `rn-theme`, `rn-local-db` and `rn-notification` asked
34
+ for `react` without having a component or a hook between them; `rn-auth`, `rn-ai` and
35
+ `rn-i18n` asked for `react-native` without touching a React Native API (rn-auth reaches
36
+ both native modules through `lazyPeer`, rn-i18n formats on `Intl`); `rn-notification`
37
+ asked for `@react-native-firebase/app`, which messaging declares itself. `rn-ai` no
38
+ longer peers on `@chipmobilesdk/rn-auth` at all — it asks for a `TokenProvider`, a
39
+ two-method interface rn-auth's `auth` satisfies, so an app with its own token source
40
+ installs nothing extra. An app that enables push or signs in through rn-auth installs
41
+ the same packages as before; it is the manifest that stopped overstating.
42
+
43
+ `react-native-localize` is declared optional, which is what the code already did: the
44
+ time-zone reader goes through `lazyPeer` and falls back to `Intl` without it. The
45
+ `peerDependenciesMeta` entries that said `optional: false` are gone — that is npm's
46
+ default, and writing it down only invited the question of which peers were undecided.
47
+
48
+ `npm run check:manifests` now fails on an unbounded peer range, a peer nothing in
49
+ `src/` imports, and a `peerDependenciesMeta` entry for either, so the policy holds
50
+ without anyone remembering it.
51
+
52
+ - Every package now ships built JavaScript with declaration files, instead of asking the
53
+ app to compile its TypeScript. ([#22](https://github.com/operationd8979/chip-mobile-sdk/pull/22))
54
+
55
+ Each tarball carries `lib/commonjs`, `lib/module` and `lib/typescript` (built with
56
+ `react-native-builder-bob`), and `src/` alongside them. What that changes for a
57
+ consumer:
58
+
59
+ - **Nothing to add to `transformIgnorePatterns`.** `require` resolves to the CommonJS
60
+ build, so an app's Jest loads this package without being told to transform it. That
61
+ was the one thing every consuming app had to know about us (DEP-04).
62
+ - **Typechecking reads our `.d.ts`** rather than compiling our source under our
63
+ `tsconfig`. A consumer's stricter — or looser — settings no longer meet our code.
64
+ - **`import` resolves to ESM**, so a bundler can tree-shake what it does not use.
65
+
66
+ No exported name changed, and no subpath moved: `.`, `./testing`, `./push`,
67
+ `./advanced`, `./app-auth`, `./keychain` and rn-core's twelve subpaths resolve exactly
68
+ as before, each now with its own declarations for both module systems. publint and
69
+ `attw --profile node16` pass on all twelve packages, which they could not before.
70
+
71
+ Inside the monorepo nothing changed either, and that is deliberate: every subpath also
72
+ declares a private `chipmobilesdk-source` condition pointing at its TypeScript, and
73
+ Metro, Jest and `tsc` here ask for that condition first. The demo app bundles 371
74
+ modules straight from `packages/*/src`, so editing a package still changes the app with
75
+ no build step, and coverage is still measured on the source. The condition is named for
76
+ this organization rather than using the conventional `source` because third-party
77
+ packages declare that one too — `@dr.pogodin/react-native-fs` does — and asking for it
78
+ pulled their sources into our stricter compile.
79
+
80
+ `npm run build:packages` builds everything, `prepack` rebuilds before any `npm pack`,
81
+ and `lib/` is git-ignored: the published bytes are produced by the release, never
82
+ committed. `npm run check:manifests` now fails a package whose `main`, `module`,
83
+ `types`, `source` condition, `files`, build script or `prepack` do not match this shape.
84
+
85
+ ### Patch Changes
86
+
87
+ - The token source is documented as the interface it has always been. `createAiClient`
88
+ takes `auth: TokenProvider` — `requestAccessToken(resourceKey, { forceRefresh })` and
89
+ nothing else — which rn-auth's controller satisfies structurally, so passing `auth`
90
+ straight in keeps working. rn-auth stopped being a peer of this package in the same
91
+ release; an app with its own token source implements two methods' worth of interface
92
+ and installs nothing extra. The skill says so where it used to leave rn-auth implied,
93
+ and the demo app carries the assignment as a compile-time assertion, so a rename on
94
+ either side now fails `tsc` instead of surfacing at runtime. ([#21](https://github.com/operationd8979/chip-mobile-sdk/pull/21))
95
+
96
+ - Each package's public API and its weight are now recorded in the repository, so a change
97
+ to either is reviewed rather than discovered. ([#23](https://github.com/operationd8979/chip-mobile-sdk/pull/23))
98
+
99
+ `packages/<pkg>/etc/*.api.md` is an api-extractor report per entrypoint — twenty-seven
100
+ of them, generated from the declarations the package publishes and committed. A renamed
101
+ type, a widened union, one more optional field: all of it shows up in a pull request's
102
+ diff. `npm run check:api` fails when a report is out of date and `npm run api:update`
103
+ rewrites them.
104
+
105
+ A report that moves now needs a **minor or major** changeset for that package.
106
+ `check:changesets` enforces it, because the report is generated from what the package
107
+ publishes, and a patch release that moves the public surface is how a consumer's build
108
+ breaks on `npm update`. A report added for the first time is a baseline, not a change.
109
+ `./testing` deliberately has no report: test doubles are not a surface a release is
110
+ gated on.
111
+
112
+ `npm run check:size` holds every entrypoint to a budget in `.size-limit.json`, measured
113
+ on the ESM build with peers and rn-core treated as external — they are what an app
114
+ installs beside us, not our weight. Each budget started at today's measurement plus five
115
+ per cent, so growth becomes a decision someone makes instead of a drift nobody sees. The
116
+ current figures run from 500 B (`rn-core/lazy`) to 19 kB (rn-notification).
117
+
118
+ No behaviour or API changed in this release; the entry is here so the changelog records
119
+ when the reports and the budgets began.
120
+ - Updated dependencies ([#22](https://github.com/operationd8979/chip-mobile-sdk/pull/22), [#23](https://github.com/operationd8979/chip-mobile-sdk/pull/23)):
121
+ - @chipmobilesdk/rn-core@0.2.0
122
+
3
123
  ## 0.4.0
4
124
 
5
125
  ### Minor Changes
package/README.md CHANGED
@@ -22,10 +22,13 @@ OpenAI directly and hold no AI credentials.
22
22
  ## Install
23
23
 
24
24
  ```bash
25
- npm install @chipmobilesdk/rn-ai @chipmobilesdk/rn-auth
25
+ npm install @chipmobilesdk/rn-ai
26
26
  ```
27
27
 
28
- Peers: `react >=19`, `react-native >=0.85`, `@chipmobilesdk/rn-auth >=0.2.0`.
28
+ The one peer is `react >=19`. `@chipmobilesdk/rn-auth` is no longer a peer: this
29
+ package asks for a `TokenProvider`, a two-method interface rn-auth's `auth`
30
+ happens to satisfy, so an app with its own token source installs nothing extra.
31
+ Install rn-auth as well if you want it to be the token source.
29
32
  **Zero runtime dependencies**; streaming uses React Native's standard
30
33
  `XMLHttpRequest` (no native code, Hermes-compatible, iOS + Android).
31
34
 
@@ -0,0 +1,283 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.SUPPORTED_SCHEMA_VERSION = exports.MemoryConfigCache = exports.BehaviorConfigManager = void 0;
7
+ exports.configCacheFromKeyValue = configCacheFromKeyValue;
8
+ exports.isTrustedUrl = isTrustedUrl;
9
+ exports.parseBehaviorConfig = parseBehaviorConfig;
10
+ var _rnCore = require("@chipmobilesdk/rn-core");
11
+ var _errors = require("../diagnostics/errors.js");
12
+ var _timeouts = require("../transport/timeouts.js");
13
+ /** App behavior configuration (contracts/app-behavior-config.md). */
14
+
15
+ /** Persistence port; default is in-memory (inject a durable store for offline launch). */
16
+
17
+ class MemoryConfigCache {
18
+ map = new Map();
19
+ async get(key) {
20
+ return this.map.get(key) ?? null;
21
+ }
22
+ async set(key, value) {
23
+ this.map.set(key, value);
24
+ }
25
+ }
26
+
27
+ /**
28
+ * An `AiConfigCache` over rn-core's synchronous `KeyValuePort` (AI-10).
29
+ *
30
+ * Without a durable cache every launch waits for the network before the first
31
+ * chat, which is exactly what the cache-first design exists to avoid. Open the
32
+ * port the way the app opens its other durable state, for example
33
+ * `openDurable(() => createMMKV({ id: 'app' }))`.
34
+ */
35
+ exports.MemoryConfigCache = MemoryConfigCache;
36
+ function configCacheFromKeyValue(port) {
37
+ return {
38
+ async get(key) {
39
+ return port.getString(key) ?? null;
40
+ },
41
+ async set(key, value) {
42
+ port.set(key, value);
43
+ }
44
+ };
45
+ }
46
+ /** The newest document layout this release understands. */
47
+ const SUPPORTED_SCHEMA_VERSION = exports.SUPPORTED_SCHEMA_VERSION = 1;
48
+
49
+ /** Bounds on the remote-configured recovery, so a bad document cannot stall a chat. */
50
+ const MAX_SILENT_RETRIES = 5;
51
+ const MIN_REFRESH_TTL_SECONDS = 30;
52
+ const DEFAULT_REFRESH_TTL_SECONDS = 21_600;
53
+ const numbers = value => Array.isArray(value) ? value.filter(n => Number.isFinite(n)) : undefined;
54
+ const positiveInt = (value, fallback) => typeof value === 'number' && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
55
+ function invalid(reason) {
56
+ throw new _errors.AiError('config-unavailable', `behavior config ${reason}`);
57
+ }
58
+
59
+ /** https, or http on a development machine: a bearer token travels to this host. */
60
+ function isTrustedUrl(url) {
61
+ if (/^https:\/\//i.test(url)) {
62
+ return true;
63
+ }
64
+ return /^http:\/\/(localhost|127\.0\.0\.1|\[::1\])(:\d+)?(\/|$)/i.test(url);
65
+ }
66
+ function hostOf(url) {
67
+ return url.replace(/^[a-z]+:\/\//i, '').split(/[/:?#]/)[0].toLowerCase();
68
+ }
69
+ /**
70
+ * Parse + validate; unknown fields ignored (forward compatibility).
71
+ *
72
+ * Every field this package acts on is checked here, because the document is
73
+ * remote and the alternative is a TypeError inside an XHR callback, a revalidate
74
+ * on every single request, or a bearer token sent to a host nobody vetted
75
+ * (AI-06, AI-07).
76
+ */
77
+ function parseBehaviorConfig(json, options = {}) {
78
+ let raw;
79
+ try {
80
+ raw = JSON.parse(json);
81
+ } catch {
82
+ invalid('is not valid JSON');
83
+ }
84
+ const api = raw.api;
85
+ if (typeof raw.appId !== 'string' || typeof api?.baseUrl !== 'string' || !Array.isArray(api.scopes)) {
86
+ invalid('is missing required fields');
87
+ }
88
+ const schemaVersion = positiveInt(raw.schemaVersion, 1);
89
+ if (schemaVersion > SUPPORTED_SCHEMA_VERSION) {
90
+ // A newer layout may mean something different by the same field names.
91
+ invalid(`declares schema version ${schemaVersion}, newer than ${SUPPORTED_SCHEMA_VERSION}`);
92
+ }
93
+ if (options.expectedAppId !== undefined && raw.appId !== options.expectedAppId) {
94
+ // The cache key and the request path carry the app id; a document for
95
+ // another app would send this app's traffic somewhere else entirely.
96
+ invalid(`is for another app (${raw.appId})`);
97
+ }
98
+ const baseUrl = api.baseUrl.replace(/\/$/, '');
99
+ if (!isTrustedUrl(baseUrl)) {
100
+ invalid('names a baseUrl that is not https');
101
+ }
102
+ if (options.allowedHosts && !options.allowedHosts.includes(hostOf(baseUrl))) {
103
+ invalid(`names a baseUrl outside the allowed hosts (${hostOf(baseUrl)})`);
104
+ }
105
+ const recovery = raw.recovery ?? {};
106
+ const features = raw.features ?? {};
107
+ return {
108
+ schemaVersion,
109
+ appId: raw.appId,
110
+ configVersion: positiveInt(raw.configVersion, 0),
111
+ // A TTL that was NaN made `isFresh` false forever, so every request
112
+ // revalidated over the network (AI-06).
113
+ refreshTtlSeconds: Math.max(MIN_REFRESH_TTL_SECONDS, positiveInt(raw.refreshTtlSeconds, DEFAULT_REFRESH_TTL_SECONDS)),
114
+ api: {
115
+ baseUrl,
116
+ scopes: api.scopes.filter(s => typeof s === 'string'),
117
+ supportsStreaming: api.supportsStreaming !== false
118
+ },
119
+ limitsDisplay: raw.limitsDisplay,
120
+ // Typed here, once: a remote document with `reloadOnHttpStatus: "404"` used to
121
+ // throw a TypeError inside the XHR error callback, where nothing caught it.
122
+ recovery: {
123
+ reloadOnHttpStatus: numbers(recovery.reloadOnHttpStatus) ?? [404, 410],
124
+ maxSilentRetries: Math.min(MAX_SILENT_RETRIES, Number.isFinite(recovery.maxSilentRetries) ? Math.max(0, Number(recovery.maxSilentRetries)) : 1),
125
+ retryBackoffMs: numbers(recovery.retryBackoffMs) ?? [500, 2000]
126
+ },
127
+ features: {
128
+ aiEnabled: features.aiEnabled !== false
129
+ }
130
+ };
131
+ }
132
+ /**
133
+ * Cache-first behavior config (FR-018): launch never blocks on the network;
134
+ * TTL revalidation uses ETag; designated errors force a reload.
135
+ */
136
+ class BehaviorConfigManager {
137
+ /**
138
+ * One cache read and one network fetch at a time (AI-08): a cold start makes a
139
+ * chat and a quota call together, and each used to fetch the config itself.
140
+ */
141
+ cacheRead = (0, _rnCore.createSingleFlight)();
142
+ networkFetch = (0, _rnCore.createSingleFlight)();
143
+ currentState = 'unloaded';
144
+ stateListeners = (0, _rnCore.createListenerSet)();
145
+
146
+ /** Where the config came from, or why there is none. */
147
+ get state() {
148
+ return this.currentState;
149
+ }
150
+
151
+ /** Called whenever `state` changes (AI-09). */
152
+ subscribe(listener) {
153
+ return this.stateListeners.add(listener);
154
+ }
155
+ setState(next) {
156
+ if (next === this.currentState) return;
157
+ this.currentState = next;
158
+ this.stateListeners.notify();
159
+ }
160
+ constructor(deps) {
161
+ this.deps = deps;
162
+ if (!isTrustedUrl(deps.configUrl)) {
163
+ // The document decides where the tokens go, so where it comes from
164
+ // matters as much (AI-07).
165
+ throw new _errors.AiError('config-unavailable', 'configUrl must be https');
166
+ }
167
+ this.cacheKey = `rn-ai:config:${deps.appId}`;
168
+ this.cache = deps.cache ?? new MemoryConfigCache();
169
+ this.fetchFn = deps.fetchFn ?? fetch;
170
+ this.now = deps.now ?? Date.now;
171
+ }
172
+ parse(json) {
173
+ return parseBehaviorConfig(json, {
174
+ expectedAppId: this.deps.appId,
175
+ ...(this.deps.allowedHosts ? {
176
+ allowedHosts: this.deps.allowedHosts
177
+ } : {})
178
+ });
179
+ }
180
+ isFresh(envelope, config) {
181
+ return this.now() - envelope.fetchedAt < config.refreshTtlSeconds * 1000;
182
+ }
183
+ loadFromCache() {
184
+ return this.current ? Promise.resolve() : this.cacheRead.run(() => this.readCache());
185
+ }
186
+ async readCache() {
187
+ if (this.current) return;
188
+ const stored = await this.cache.get(this.cacheKey).catch(() => null);
189
+ if (!stored) return;
190
+ try {
191
+ const envelope = JSON.parse(stored);
192
+ this.current = {
193
+ config: this.parse(envelope.configJson),
194
+ envelope
195
+ };
196
+ this.setState('ready-cache');
197
+ } catch {
198
+ // corrupted cache entries are ignored, not fatal
199
+ }
200
+ }
201
+ fetchNetwork() {
202
+ return this.networkFetch.run(() => this.fetchFromNetwork());
203
+ }
204
+
205
+ /** One attempt; `conditional` sends the stored ETag when there is one. */
206
+ async fetchOnce(conditional) {
207
+ const headers = {};
208
+ const etag = this.current?.envelope.etag;
209
+ if (conditional && etag) {
210
+ headers['If-None-Match'] = etag;
211
+ }
212
+ // Bounded: with no cache, a hung fetch used to block every chat and quota call.
213
+ return (0, _timeouts.withTimeout)(this.deps.timeoutMs ?? _timeouts.DEFAULT_AI_TIMEOUTS.configMs, async signal => {
214
+ const response = await this.fetchFn(this.deps.configUrl, {
215
+ headers,
216
+ signal
217
+ });
218
+ return {
219
+ status: response.status,
220
+ text: response.ok && response.status !== 304 ? await response.text() : '',
221
+ etag: response.headers.get('etag') ?? undefined
222
+ };
223
+ }, () => new _errors.AiError('config-unavailable', 'config fetch timed out'));
224
+ }
225
+ async fetchFromNetwork() {
226
+ let result = await this.fetchOnce(true);
227
+ if (result.status === 304) {
228
+ if (this.current) {
229
+ this.current.envelope.fetchedAt = this.now();
230
+ await this.persist(this.current.envelope);
231
+ this.setState('ready-network');
232
+ return this.current.config;
233
+ }
234
+ // Not-modified against a cache that is no longer there (it was cleared,
235
+ // or it failed to parse). Asking again without the ETag is the answer;
236
+ // reporting `config fetch failed: 304` was not (AI-17).
237
+ result = await this.fetchOnce(false);
238
+ }
239
+ if (result.status < 200 || result.status >= 300) {
240
+ throw new _errors.AiError('config-unavailable', `config fetch failed: ${result.status}`);
241
+ }
242
+ const config = this.parse(result.text);
243
+ const envelope = {
244
+ configJson: result.text,
245
+ etag: result.etag,
246
+ fetchedAt: this.now()
247
+ };
248
+ this.current = {
249
+ config,
250
+ envelope
251
+ };
252
+ await this.persist(envelope);
253
+ this.setState('ready-network');
254
+ return config;
255
+ }
256
+ async persist(envelope) {
257
+ await this.cache.set(this.cacheKey, JSON.stringify(envelope)).catch(() => undefined);
258
+ }
259
+
260
+ /**
261
+ * Cache-first read. Fresh cache returns immediately; stale cache returns
262
+ * immediately too while a background revalidation runs; no cache at all
263
+ * falls through to the network (or `config-unavailable`).
264
+ */
265
+ async getConfig(options = {}) {
266
+ await this.loadFromCache();
267
+ if (!options.forceReload && this.current) {
268
+ if (!this.isFresh(this.current.envelope, this.current.config)) {
269
+ this.fetchNetwork().catch(() => undefined); // background revalidate
270
+ }
271
+ return this.current.config;
272
+ }
273
+ try {
274
+ return await this.fetchNetwork();
275
+ } catch (e) {
276
+ if (this.current) return this.current.config; // stale beats broken
277
+ this.setState('unavailable');
278
+ throw e instanceof _errors.AiError ? e : new _errors.AiError('config-unavailable', String(e));
279
+ }
280
+ }
281
+ }
282
+ exports.BehaviorConfigManager = BehaviorConfigManager;
283
+ //# sourceMappingURL=behaviorConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_rnCore","require","_errors","_timeouts","MemoryConfigCache","map","Map","get","key","set","value","exports","configCacheFromKeyValue","port","getString","SUPPORTED_SCHEMA_VERSION","MAX_SILENT_RETRIES","MIN_REFRESH_TTL_SECONDS","DEFAULT_REFRESH_TTL_SECONDS","numbers","Array","isArray","filter","n","Number","isFinite","undefined","positiveInt","fallback","Math","floor","invalid","reason","AiError","isTrustedUrl","url","test","hostOf","replace","split","toLowerCase","parseBehaviorConfig","json","options","raw","JSON","parse","api","appId","baseUrl","scopes","schemaVersion","expectedAppId","allowedHosts","includes","recovery","features","configVersion","refreshTtlSeconds","max","s","supportsStreaming","limitsDisplay","reloadOnHttpStatus","maxSilentRetries","min","retryBackoffMs","aiEnabled","BehaviorConfigManager","cacheRead","createSingleFlight","networkFetch","currentState","stateListeners","createListenerSet","state","subscribe","listener","add","setState","next","notify","constructor","deps","configUrl","cacheKey","cache","fetchFn","fetch","now","Date","isFresh","envelope","config","fetchedAt","loadFromCache","current","Promise","resolve","run","readCache","stored","catch","configJson","fetchNetwork","fetchFromNetwork","fetchOnce","conditional","headers","etag","withTimeout","timeoutMs","DEFAULT_AI_TIMEOUTS","configMs","signal","response","status","text","ok","result","persist","stringify","getConfig","forceReload","e","String"],"sourceRoot":"../../../src","sources":["config/behaviorConfig.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.SSE_DONE_SENTINEL = exports.RETRY_AFTER_HEADER = exports.QUOTA_HEADERS = exports.GATEWAY_ERROR_STATUS = void 0;
7
+ /**
8
+ * The gateway↔client contract: error codes, quota headers, stream events.
9
+ *
10
+ * One definition, imported by both sides (GW-13). The gateway's own codes and
11
+ * the client's map of them were two hand-maintained lists, and they had already
12
+ * drifted: `BAD_REQUEST`, `ENDPOINT_RETIRED` and `INTERNAL` existed on the
13
+ * server and were unknown to the client, which fell back to a guess from the
14
+ * status. Adding a code now fails to compile on whichever side has not handled
15
+ * it.
16
+ *
17
+ * Types and plain constants only, and no import of anything: the gateway runs
18
+ * on Node and imports this file for its types alone.
19
+ */
20
+
21
+ /** Every error the gateway answers with (`error.code` in the body). */
22
+
23
+ /** The HTTP status each code is sent with. */
24
+ const GATEWAY_ERROR_STATUS = exports.GATEWAY_ERROR_STATUS = {
25
+ BAD_REQUEST: 400,
26
+ AUTH_INVALID: 401,
27
+ NOT_ENTITLED: 403,
28
+ USER_BLOCKED: 403,
29
+ APP_UNKNOWN: 404,
30
+ ENDPOINT_RETIRED: 410,
31
+ PAYLOAD_TOO_LARGE: 413,
32
+ MODALITY_NOT_ALLOWED: 415,
33
+ RATE_LIMITED: 429,
34
+ UPSTREAM_BUSY: 429,
35
+ UPSTREAM_ERROR: 500,
36
+ INTERNAL: 500
37
+ };
38
+
39
+ /** The error body. `message` is safe to log; it never carries upstream detail. */
40
+
41
+ /** The quota headers, by name. A rename here breaks both sides' compile. */
42
+ const QUOTA_HEADERS = exports.QUOTA_HEADERS = {
43
+ minuteRemaining: 'X-Quota-Minute-Remaining',
44
+ dayRemaining: 'X-Quota-Day-Remaining',
45
+ dayTokensRemaining: 'X-Quota-Day-Tokens-Remaining'
46
+ };
47
+
48
+ /** The names field by field, so a side declaring its own literals is checked exactly. */
49
+
50
+ /** What is left of an app's allowance, as the gateway reports it. */
51
+
52
+ /** What one answer cost. */
53
+
54
+ /** The `data:` payloads of a chat stream, before the `[DONE]` sentinel. */
55
+
56
+ /** The last `data:` line of a stream that completed. */
57
+ const SSE_DONE_SENTINEL = exports.SSE_DONE_SENTINEL = '[DONE]';
58
+ /** The `Retry-After` header, which a 429 always carries. */
59
+ const RETRY_AFTER_HEADER = exports.RETRY_AFTER_HEADER = 'Retry-After';
60
+ //# sourceMappingURL=gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["GATEWAY_ERROR_STATUS","exports","BAD_REQUEST","AUTH_INVALID","NOT_ENTITLED","USER_BLOCKED","APP_UNKNOWN","ENDPOINT_RETIRED","PAYLOAD_TOO_LARGE","MODALITY_NOT_ALLOWED","RATE_LIMITED","UPSTREAM_BUSY","UPSTREAM_ERROR","INTERNAL","QUOTA_HEADERS","minuteRemaining","dayRemaining","dayTokensRemaining","SSE_DONE_SENTINEL","RETRY_AFTER_HEADER"],"sourceRoot":"../../../src","sources":["contract/gateway.ts"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAeA;AACO,MAAMA,oBAAgE,GAAAC,OAAA,CAAAD,oBAAA,GAAG;EAC/EE,WAAW,EAAE,GAAG;EAChBC,YAAY,EAAE,GAAG;EACjBC,YAAY,EAAE,GAAG;EACjBC,YAAY,EAAE,GAAG;EACjBC,WAAW,EAAE,GAAG;EAChBC,gBAAgB,EAAE,GAAG;EACrBC,iBAAiB,EAAE,GAAG;EACtBC,oBAAoB,EAAE,GAAG;EACzBC,YAAY,EAAE,GAAG;EACjBC,aAAa,EAAE,GAAG;EAClBC,cAAc,EAAE,GAAG;EACnBC,QAAQ,EAAE;AACX,CAAC;;AAED;;AASA;AACO,MAAMC,aAAa,GAAAb,OAAA,CAAAa,aAAA,GAAG;EAC5BC,eAAe,EAAE,0BAA0B;EAC3CC,YAAY,EAAE,uBAAuB;EACrCC,kBAAkB,EAAE;AACrB,CAAU;;AAEV;;AAIA;;AAOA;;AAOA;;AAMA;AACO,MAAMC,iBAAiB,GAAAjB,OAAA,CAAAiB,iBAAA,GAAG,QAAQ;AAGzC;AACO,MAAMC,kBAAkB,GAAAlB,OAAA,CAAAkB,kBAAA,GAAG,aAAa","ignoreList":[]}