@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.
- package/CHANGELOG.md +120 -0
- package/README.md +5 -2
- package/lib/commonjs/config/behaviorConfig.js +283 -0
- package/lib/commonjs/config/behaviorConfig.js.map +1 -0
- package/lib/commonjs/contract/gateway.js +60 -0
- package/lib/commonjs/contract/gateway.js.map +1 -0
- package/lib/commonjs/core/aiClient.js +330 -0
- package/lib/commonjs/core/aiClient.js.map +1 -0
- package/lib/commonjs/core/quotaRequest.js +105 -0
- package/lib/commonjs/core/quotaRequest.js.map +1 -0
- package/lib/commonjs/diagnostics/errors.js +108 -0
- package/lib/commonjs/diagnostics/errors.js.map +1 -0
- package/lib/commonjs/diagnostics/messageKeys.js +68 -0
- package/lib/commonjs/diagnostics/messageKeys.js.map +1 -0
- package/lib/commonjs/index.js +102 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/react/hooks.js +170 -0
- package/lib/commonjs/react/hooks.js.map +1 -0
- package/lib/commonjs/transport/sseClient.js +151 -0
- package/lib/commonjs/transport/sseClient.js.map +1 -0
- package/lib/commonjs/transport/timeouts.js +46 -0
- package/lib/commonjs/transport/timeouts.js.map +1 -0
- package/lib/module/config/behaviorConfig.js +275 -0
- package/lib/module/config/behaviorConfig.js.map +1 -0
- package/lib/module/contract/gateway.js +56 -0
- package/lib/module/contract/gateway.js.map +1 -0
- package/lib/module/core/aiClient.js +327 -0
- package/lib/module/core/aiClient.js.map +1 -0
- package/lib/module/core/quotaRequest.js +102 -0
- package/lib/module/core/quotaRequest.js.map +1 -0
- package/lib/module/diagnostics/errors.js +99 -0
- package/lib/module/diagnostics/errors.js.map +1 -0
- package/lib/module/diagnostics/messageKeys.js +61 -0
- package/lib/module/diagnostics/messageKeys.js.map +1 -0
- package/lib/module/index.js +19 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/react/hooks.js +164 -0
- package/lib/module/react/hooks.js.map +1 -0
- package/lib/module/transport/sseClient.js +146 -0
- package/lib/module/transport/sseClient.js.map +1 -0
- package/lib/module/transport/timeouts.js +41 -0
- package/lib/module/transport/timeouts.js.map +1 -0
- package/lib/typescript/commonjs/config/behaviorConfig.d.ts +119 -0
- package/lib/typescript/commonjs/config/behaviorConfig.d.ts.map +1 -0
- package/lib/typescript/commonjs/contract/gateway.d.ts +64 -0
- package/lib/typescript/commonjs/contract/gateway.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/aiClient.d.ts +104 -0
- package/lib/typescript/commonjs/core/aiClient.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/quotaRequest.d.ts +45 -0
- package/lib/typescript/commonjs/core/quotaRequest.d.ts.map +1 -0
- package/lib/typescript/commonjs/diagnostics/errors.d.ts +38 -0
- package/lib/typescript/commonjs/diagnostics/errors.d.ts.map +1 -0
- package/lib/typescript/commonjs/diagnostics/messageKeys.d.ts +46 -0
- package/lib/typescript/commonjs/diagnostics/messageKeys.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +21 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/react/hooks.d.ts +37 -0
- package/lib/typescript/commonjs/react/hooks.d.ts.map +1 -0
- package/lib/typescript/commonjs/transport/sseClient.d.ts +57 -0
- package/lib/typescript/commonjs/transport/sseClient.d.ts.map +1 -0
- package/lib/typescript/commonjs/transport/timeouts.d.ts +28 -0
- package/lib/typescript/commonjs/transport/timeouts.d.ts.map +1 -0
- package/lib/typescript/module/config/behaviorConfig.d.ts +119 -0
- package/lib/typescript/module/config/behaviorConfig.d.ts.map +1 -0
- package/lib/typescript/module/contract/gateway.d.ts +64 -0
- package/lib/typescript/module/contract/gateway.d.ts.map +1 -0
- package/lib/typescript/module/core/aiClient.d.ts +104 -0
- package/lib/typescript/module/core/aiClient.d.ts.map +1 -0
- package/lib/typescript/module/core/quotaRequest.d.ts +45 -0
- package/lib/typescript/module/core/quotaRequest.d.ts.map +1 -0
- package/lib/typescript/module/diagnostics/errors.d.ts +38 -0
- package/lib/typescript/module/diagnostics/errors.d.ts.map +1 -0
- package/lib/typescript/module/diagnostics/messageKeys.d.ts +46 -0
- package/lib/typescript/module/diagnostics/messageKeys.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +21 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/react/hooks.d.ts +37 -0
- package/lib/typescript/module/react/hooks.d.ts.map +1 -0
- package/lib/typescript/module/transport/sseClient.d.ts +57 -0
- package/lib/typescript/module/transport/sseClient.d.ts.map +1 -0
- package/lib/typescript/module/transport/timeouts.d.ts +28 -0
- package/lib/typescript/module/transport/timeouts.d.ts.map +1 -0
- package/package.json +40 -12
- 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
|
|
25
|
+
npm install @chipmobilesdk/rn-ai
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
|
|
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":[]}
|