@molecule/api-ai-decisions-intern-decision 1.0.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/LICENSE ADDED
@@ -0,0 +1,115 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work.
38
+
39
+ "Derivative Works" shall mean any work, whether in Source or Object
40
+ form, that is based on (or derived from) the Work and for which the
41
+ editorial revisions, annotations, elaborations, or other modifications
42
+ represent, as a whole, an original work of authorship.
43
+
44
+ "Contribution" shall mean any work of authorship, including the
45
+ original version of the Work and any modifications or additions
46
+ to that Work, that is intentionally submitted to the Licensor for
47
+ inclusion in the Work by the copyright owner or by an individual or
48
+ Legal Entity authorized to submit on behalf of the copyright owner.
49
+
50
+ "Contributor" shall mean Licensor and any individual or Legal Entity
51
+ on behalf of whom a Contribution has been received by the Licensor and
52
+ subsequently incorporated within the Work.
53
+
54
+ 2. Grant of Copyright License. Subject to the terms and conditions of
55
+ this License, each Contributor hereby grants to You a perpetual,
56
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
57
+ copyright license to reproduce, prepare Derivative Works of,
58
+ publicly display, publicly perform, sublicense, and distribute the
59
+ Work and such Derivative Works in Source or Object form.
60
+
61
+ 3. Grant of Patent License. Subject to the terms and conditions of
62
+ this License, each Contributor hereby grants to You a perpetual,
63
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
64
+ patent license to make, have made, use, offer to sell, sell, import,
65
+ and otherwise transfer the Work.
66
+
67
+ 4. Redistribution. You may reproduce and distribute copies of the
68
+ Work or Derivative Works thereof in any medium, with or without
69
+ modifications, and in Source or Object form, provided that You
70
+ meet the following conditions:
71
+
72
+ (a) You must give any other recipients of the Work or
73
+ Derivative Works a copy of this License; and
74
+
75
+ (b) You must cause any modified files to carry prominent notices
76
+ stating that You changed the files; and
77
+
78
+ (c) You must retain, in the Source form of any Derivative Works
79
+ that You distribute, all copyright, patent, trademark, and
80
+ attribution notices from the Source form of the Work,
81
+ excluding those notices that do not pertain to any part of
82
+ the Derivative Works; and
83
+
84
+ (d) If the Work includes a "NOTICE" text file as part of its
85
+ distribution, then any Derivative Works that You distribute must
86
+ include a readable copy of the attribution notices contained
87
+ within such NOTICE file.
88
+
89
+ 5. Submission of Contributions.
90
+
91
+ 6. Trademarks. This License does not grant permission to use the trade
92
+ names, trademarks, service marks, or product names of the Licensor.
93
+
94
+ 7. Disclaimer of Warranty. Unless required by applicable law or
95
+ agreed to in writing, Licensor provides the Work on an "AS IS" BASIS,
96
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND.
97
+
98
+ 8. Limitation of Liability. In no event and under no legal theory shall
99
+ any Contributor be liable to You for damages.
100
+
101
+ 9. Accepting Warranty or Additional Liability.
102
+
103
+ Copyright 2026 Molecule Dev, Inc.
104
+
105
+ Licensed under the Apache License, Version 2.0 (the "License");
106
+ you may not use this file except in compliance with the License.
107
+ You may obtain a copy of the License at
108
+
109
+ http://www.apache.org/licenses/LICENSE-2.0
110
+
111
+ Unless required by applicable law or agreed to in writing, software
112
+ distributed under the License is distributed on an "AS IS" BASIS,
113
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
114
+ See the License for the specific language governing permissions and
115
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,366 @@
1
+ <!--
2
+ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
+ Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
+ Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
+ To change this document, edit the module-level JSDoc in src/index.ts.
6
+ Generated: 2026-09-29T13:48:35.262Z
7
+ -->
8
+
9
+ # @molecule/api-ai-decisions-intern-decision
10
+
11
+ > **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
12
+ > It is written to be read by coding agents as much as by people, and is generated from this
13
+ > package's source — edit `src/index.ts` JSDoc, not this file.
14
+
15
+ Intern-Decision decisions provider for molecule.dev — typed decisions about
16
+ text AND images from the open-weights Intern-Decision models on a server
17
+ you run.
18
+
19
+ Intern-Decision (github.com/internlm/Intern-Decision, from InternLM) is a
20
+ family of Qwen3.5 fine-tunes — 0.8B, 2B and 4B — that answer `choice`,
21
+ `score` and yes/no questions with a probability per option, and can read up
22
+ to 8 images alongside the text (a screenshot, a photo, a scanned form). Its
23
+ maker reports 90.0% average accuracy for the 4B (44 ms/request) and 84.7%
24
+ for the 2B (33 ms on an RTX 4090). This bond speaks the service's
25
+ `POST /v1/decisions` route; the question and answer shapes match the Jev /
26
+ Laya / Jeff bonds, so swapping is a one-line change.
27
+
28
+ ## Quick Start
29
+
30
+ ```bash
31
+ # Run the service on a GPU host (it binds 127.0.0.1:7860 and has NO auth)
32
+ git clone https://github.com/internlm/Intern-Decision && cd Intern-Decision
33
+ python -m venv .venv && . .venv/bin/activate
34
+ pip install -r requirements-inference.txt
35
+ MODEL_CHECKPOINT=/models/Intern-Decision-2B bash scripts/demo.sh
36
+ ```
37
+
38
+ ```typescript
39
+ import { readFileSync } from 'node:fs'
40
+
41
+ import { setProvider, requireProvider } from '@molecule/api-ai-decisions'
42
+ import { provider } from '@molecule/api-ai-decisions-intern-decision'
43
+
44
+ setProvider(provider) // reads INTERN_DECISION_URL (+ INTERN_DECISION_API_KEY for a proxy) on first use
45
+
46
+ const { answers } = await requireProvider().decide({
47
+ state: 'A screenshot of the app preview after deploy.',
48
+ images: [{ mimeType: 'image/png', data: readFileSync('preview.png').toString('base64') }],
49
+ questions: {
50
+ blank: { type: 'yesNo', instructions: 'The page is blank or shows only an error.' },
51
+ layout: {
52
+ type: 'choice',
53
+ instructions: 'What does the page show?',
54
+ criteria: { landing: 'a marketing page', app: 'an app screen', error: 'an error page' },
55
+ },
56
+ },
57
+ })
58
+ answers.blank.probability // 0.04
59
+ answers.layout.choice // 'landing'
60
+ ```
61
+
62
+ ## Type
63
+
64
+ `provider`
65
+
66
+ ## Installation
67
+
68
+ ```bash
69
+ npm install @molecule/api-ai-decisions-intern-decision @molecule/api-ai-decisions @molecule/api-secrets
70
+ ```
71
+
72
+ ## API
73
+
74
+ ### Interfaces
75
+
76
+ #### `InternDecisionConfig`
77
+
78
+ Configuration for the Intern-Decision decisions provider.
79
+
80
+ ```typescript
81
+ interface InternDecisionConfig {
82
+ /**
83
+ * Base URL of the Intern-Decision service (or of an authenticating proxy in
84
+ * front of it). Defaults to `INTERN_DECISION_URL`, then `http://127.0.0.1:7860`.
85
+ */
86
+ baseUrl?: string
87
+ /**
88
+ * Bearer token for a proxy in front of the service. The service itself has
89
+ * no authentication. Defaults to the `INTERN_DECISION_API_KEY` env var.
90
+ */
91
+ apiKey?: string
92
+ }
93
+ ```
94
+
95
+ #### `PostOptions`
96
+
97
+ Options for {@link postDecisions}.
98
+
99
+ ```typescript
100
+ interface PostOptions {
101
+ /** Full endpoint URL. */
102
+ url: string
103
+ /** Bearer token, if any. */
104
+ apiKey?: string
105
+ /** Request body. */
106
+ body: Record<string, unknown>
107
+ /** Abort signal. */
108
+ signal?: AbortSignal
109
+ /** Label for error messages (`'Intern-Decision'`). */
110
+ label: string
111
+ /** Max retries on a retryable status (default 3). */
112
+ maxRetries?: number
113
+ }
114
+ ```
115
+
116
+ #### `WireAnswer`
117
+
118
+ One answer as received on the wire (only the fields we read).
119
+
120
+ ```typescript
121
+ interface WireAnswer {
122
+ type?: string
123
+ choice?: string
124
+ score?: number
125
+ noul?: number
126
+ probabilities?: Record<string, number>
127
+ }
128
+ ```
129
+
130
+ #### `WireQuestion`
131
+
132
+ One question as sent on the wire.
133
+
134
+ ```typescript
135
+ interface WireQuestion {
136
+ type: 'choice' | 'score' | 'noul'
137
+ instructions: string
138
+ criteria?: Record<string, string> | string[]
139
+ }
140
+ ```
141
+
142
+ #### `WireResponse`
143
+
144
+ The response body (only the fields we read).
145
+
146
+ ```typescript
147
+ interface WireResponse {
148
+ model?: string
149
+ answers?: Record<string, WireAnswer>
150
+ usage?: { input_tokens?: number; output_tokens?: number }
151
+ }
152
+ ```
153
+
154
+ ### Functions
155
+
156
+ #### `createProvider(config)`
157
+
158
+ Creates an Intern-Decision decisions provider.
159
+
160
+ ```typescript
161
+ function createProvider(config?: InternDecisionConfig): AIDecisionsProvider
162
+ ```
163
+
164
+ - `config` — Base URL and optional proxy API key.
165
+
166
+ **Returns:** An `AIDecisionsProvider` backed by an Intern-Decision service.
167
+
168
+ #### `fromWireAnswer(id, question, wire, minConfidence)`
169
+
170
+ Converts one wire answer into the core's answer for `question`.
171
+
172
+ ```typescript
173
+ function fromWireAnswer(
174
+ id: string,
175
+ question: DecisionQuestion,
176
+ wire: WireAnswer | undefined,
177
+ minConfidence?: number,
178
+ ): DecisionAnswer
179
+ ```
180
+
181
+ - `id` — The question id (for error messages).
182
+ - `question` — The question that was asked.
183
+ - `wire` — The wire answer.
184
+ - `minConfidence` — Optional low-confidence threshold.
185
+
186
+ **Returns:** The typed answer.
187
+
188
+ #### `fromWireResponse(questions, body, minConfidence)`
189
+
190
+ Converts a whole wire response into the core's result.
191
+
192
+ ```typescript
193
+ function fromWireResponse(questions: Q, body: WireResponse, minConfidence?: number): DecideResult<Q>
194
+ ```
195
+
196
+ - `questions` — The questions that were asked.
197
+ - `body` — The parsed response body.
198
+ - `minConfidence` — Optional low-confidence threshold.
199
+
200
+ **Returns:** The typed result.
201
+
202
+ #### `postDecisions(opts)`
203
+
204
+ POSTs a decision request with retry on 429/5xx-busy, honouring
205
+ `Retry-After`. Throws an Error carrying `status` on a non-2xx response.
206
+
207
+ ```typescript
208
+ function postDecisions(opts: PostOptions): Promise<WireResponse>
209
+ ```
210
+
211
+ - `opts` — Request options.
212
+
213
+ **Returns:** The parsed response body.
214
+
215
+ #### `toWireQuestions(questions)`
216
+
217
+ Converts the core's questions into wire questions (`yesNo` → `noul`).
218
+
219
+ ```typescript
220
+ function toWireQuestions(questions: Record<string, DecisionQuestion>): Record<string, WireQuestion>
221
+ ```
222
+
223
+ - `questions` — The questions keyed by id.
224
+
225
+ **Returns:** The wire `questions` object.
226
+
227
+ ### Constants
228
+
229
+ #### `aiDecisionsInternDecisionSecretDefinitions`
230
+
231
+ Secret definitions used by the Intern-Decision decisions bond.
232
+
233
+ ```typescript
234
+ const aiDecisionsInternDecisionSecretDefinitions: SecretDefinition[]
235
+ ```
236
+
237
+ #### `DEFAULT_INTERN_DECISION_URL`
238
+
239
+ The service's default bind (`scripts/demo.sh`: `DEMO_HOST` 127.0.0.1, `DEMO_PORT` 7860).
240
+
241
+ ```typescript
242
+ const DEFAULT_INTERN_DECISION_URL: 'http://127.0.0.1:7860'
243
+ ```
244
+
245
+ #### `INTERN_DECISION_IMAGE_TYPES`
246
+
247
+ Image media types the service decodes (GIFs must be still).
248
+
249
+ ```typescript
250
+ const INTERN_DECISION_IMAGE_TYPES: readonly string[]
251
+ ```
252
+
253
+ #### `INTERN_DECISION_LIMITS`
254
+
255
+ The service's request limits (`src/inference/pipeline.py`, `src/service/uploads.py`).
256
+
257
+ ```typescript
258
+ const INTERN_DECISION_LIMITS: {
259
+ readonly maxQuestions: 16
260
+ readonly maxOptions: 62
261
+ readonly maxImages: 8
262
+ readonly maxImageBytes: number
263
+ readonly maxTotalImageBytes: number
264
+ }
265
+ ```
266
+
267
+ #### `provider`
268
+
269
+ The provider implementation — lazy, so env vars are read on first use.
270
+
271
+ ```typescript
272
+ const provider: AIDecisionsProvider
273
+ ```
274
+
275
+ ## Core Interface
276
+
277
+ Implements `@molecule/api-ai-decisions` interface.
278
+
279
+ ## Bond Wiring
280
+
281
+ Setup function to register this provider with the core interface:
282
+
283
+ ```typescript
284
+ import { setProvider } from '@molecule/api-ai-decisions'
285
+ import { provider } from '@molecule/api-ai-decisions-intern-decision'
286
+
287
+ export function setupAiDecisionsInternDecision(): void {
288
+ setProvider(provider)
289
+ }
290
+ ```
291
+
292
+ ## Injection Notes
293
+
294
+ ### Requirements
295
+
296
+ Peer dependencies:
297
+
298
+ - `@molecule/api-ai-decisions` ^1.1.0
299
+ - `@molecule/api-secrets` ^1.0.1
300
+
301
+ ### Environment Variables
302
+
303
+ - `INTERN_DECISION_URL` _(optional)_ — Intern-Decision server URL
304
+ - Setup: The base URL of your Intern-Decision service (clone github.com/internlm/Intern-Decision, pip install -r requirements-inference.txt, set MODEL_CHECKPOINT, then bash scripts/demo.sh), or of an authenticating proxy in front of it. Defaults to http://127.0.0.1:7860.
305
+ - Get it here: [https://github.com/internlm/Intern-Decision#readme](https://github.com/internlm/Intern-Decision#readme)
306
+ - Example: `http://127.0.0.1:7860`
307
+ - `INTERN_DECISION_API_KEY` _(optional)_ — Intern-Decision proxy API key
308
+ - Setup: The bearer token your authenticating proxy in front of the Intern-Decision service requires. The service itself has no authentication.
309
+ - Get it here: [https://github.com/internlm/Intern-Decision#readme](https://github.com/internlm/Intern-Decision#readme)
310
+ - Example: `a-long-random-string`
311
+
312
+ ### Runtime Dependencies
313
+
314
+ - `@molecule/api-ai-decisions`
315
+ - `@molecule/api-secrets`
316
+
317
+ - **The service has NO authentication** and binds `127.0.0.1` by default.
318
+ Never publish its port: reach it over a private network, or put an
319
+ authenticating reverse proxy in front and set `INTERN_DECISION_API_KEY`
320
+ (sent as `Authorization: Bearer …` — the service itself ignores it).
321
+ - **Default port is 7860**, not 8000: `INTERN_DECISION_URL` defaults to
322
+ `http://127.0.0.1:7860`.
323
+ - **One checkpoint per server; `model` is ignored.** The service answers with
324
+ whatever `MODEL_CHECKPOINT` it loaded (`result.model` is always
325
+ `'intern-decision'`). Run a second server for a second size.
326
+ - **Limits (checked here before sending, else a 422):** 1–16 questions per
327
+ request, 1–62 options per `choice` or levels per `score`, up to 8 images of
328
+ PNG / JPEG / WebP / still GIF, each ≤12 MB decoded and ≤32 MB total (and
329
+ ≤16 million pixels — checked by the server only). `images[].data` is raw
330
+ base64 — no `data:` prefix.
331
+ - **Input is capped at 8,192 tokens** by default (`MAX_INPUT_LENGTH` on the
332
+ server). Put the decisive text first.
333
+ - **Requests are serialized** on the server (one model lock); concurrent
334
+ calls queue rather than fail. A loading server answers 503; this bond
335
+ retries 429/502/503/504/529 up to 3 times. Errors carry the HTTP `status`.
336
+ - **Calibration:** each checkpoint ships a fitted temperature (2B: 2.1),
337
+ applied only when the server is configured with its calibration file —
338
+ and the HF and XTuner backends give slightly different probabilities.
339
+ Calibrate on labelled samples of your inputs and gate on `minConfidence`.
340
+ - **Not a chat model and does not reason.** It picks among the options you
341
+ describe; the service's optional "thinking" handoff to an external LLM is
342
+ not used by this bond.
343
+ - **License:** the code is Apache-2.0; the weights' Hugging Face cards say
344
+ Apache-2.0 while the repo README says Qwen model terms apply — check
345
+ LICENSE-QWEN before offering it to third parties.
346
+ - Use the core's `setProvider`, not `bond('ai-decisions', …)` directly.
347
+
348
+ ## E2E Tests
349
+
350
+ Integration checklist — drive the real UI (live preview, no mocks), adapt
351
+ each item to this app's actual screens/flows, and check every box off one
352
+ by one. A box you can't check is an integration bug to fix — not a skip:
353
+
354
+ - [ ] Each flow that makes a decision (routing, triage, moderation, a
355
+ guardrail) runs it from the real UI, and the answer DRIVES what happens
356
+ next (the item lands in the chosen queue, the badge shows, the action is
357
+ blocked) — not just printed.
358
+ - [ ] Both directions: a clearly-billing input routes to billing AND a
359
+ clearly-technical one routes elsewhere. One label for every input is a
360
+ broken integration.
361
+ - [ ] A low-confidence answer takes the app's fallback path (human review,
362
+ "unsure" state) instead of being acted on.
363
+ - [ ] Provider errors (service down, bad key) show a visible, recoverable
364
+ state — never a blank screen or an unhandled rejection.
365
+ - [ ] The call runs server-side: no provider request or key in the browser's
366
+ Network tab.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=browser-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-guard.d.ts","sourceRoot":"","sources":["../src/browser-guard.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,CAAA"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Browser guard — `@molecule/api-ai-decisions-intern-decision` is SERVER-ONLY.
3
+ *
4
+ * Generated by scripts/gen-browser-guards.mjs (workspace root) — edit THAT, not this.
5
+ * Evaluating a server package in a browser bundle is always an import-graph mistake
6
+ * (node APIs, secrets); without this guard it surfaces as a cryptic downstream crash
7
+ * ("Buffer is not defined") far from the culprit. Throwing here names the package and
8
+ * the fix at the exact moment the client bundle evaluates it. jsdom tests and SSR are
9
+ * unaffected: the throw requires browser globals AND the absence of a node runtime.
10
+ */
11
+ const g = globalThis;
12
+ if (g.window !== undefined && g.document !== undefined && !g.process?.versions?.node) {
13
+ throw new Error('@molecule/api-ai-decisions-intern-decision is SERVER-ONLY: it was bundled into browser/client code. Import it only ' +
14
+ 'from server code (a server route/function or your API), or dynamic-import it inside ' +
15
+ 'the server handler — never from components or shared client modules, and never ' +
16
+ 'polyfill Buffer/process to silence this.');
17
+ }
18
+ export {};
19
+ //# sourceMappingURL=browser-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-guard.js","sourceRoot":"","sources":["../src/browser-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,GAAG,UAIT,CAAA;AACD,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACrF,MAAM,IAAI,KAAK,CACb,qHAAqH;QACnH,sFAAsF;QACtF,iFAAiF;QACjF,0CAA0C,CAC7C,CAAA;AACH,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Intern-Decision decisions provider for molecule.dev — typed decisions about
3
+ * text AND images from the open-weights Intern-Decision models on a server
4
+ * you run.
5
+ *
6
+ * Intern-Decision (github.com/internlm/Intern-Decision, from InternLM) is a
7
+ * family of Qwen3.5 fine-tunes — 0.8B, 2B and 4B — that answer `choice`,
8
+ * `score` and yes/no questions with a probability per option, and can read up
9
+ * to 8 images alongside the text (a screenshot, a photo, a scanned form). Its
10
+ * maker reports 90.0% average accuracy for the 4B (44 ms/request) and 84.7%
11
+ * for the 2B (33 ms on an RTX 4090). This bond speaks the service's
12
+ * `POST /v1/decisions` route; the question and answer shapes match the Jev /
13
+ * Laya / Jeff bonds, so swapping is a one-line change.
14
+ *
15
+ * @example
16
+ * ```bash
17
+ * # Run the service on a GPU host (it binds 127.0.0.1:7860 and has NO auth)
18
+ * git clone https://github.com/internlm/Intern-Decision && cd Intern-Decision
19
+ * python -m venv .venv && . .venv/bin/activate
20
+ * pip install -r requirements-inference.txt
21
+ * MODEL_CHECKPOINT=/models/Intern-Decision-2B bash scripts/demo.sh
22
+ * ```
23
+ *
24
+ * ```typescript
25
+ * import { readFileSync } from 'node:fs'
26
+ *
27
+ * import { setProvider, requireProvider } from '@molecule/api-ai-decisions'
28
+ * import { provider } from '@molecule/api-ai-decisions-intern-decision'
29
+ *
30
+ * setProvider(provider) // reads INTERN_DECISION_URL (+ INTERN_DECISION_API_KEY for a proxy) on first use
31
+ *
32
+ * const { answers } = await requireProvider().decide({
33
+ * state: 'A screenshot of the app preview after deploy.',
34
+ * images: [{ mimeType: 'image/png', data: readFileSync('preview.png').toString('base64') }],
35
+ * questions: {
36
+ * blank: { type: 'yesNo', instructions: 'The page is blank or shows only an error.' },
37
+ * layout: { type: 'choice', instructions: 'What does the page show?', criteria: { landing: 'a marketing page', app: 'an app screen', error: 'an error page' } },
38
+ * },
39
+ * })
40
+ * answers.blank.probability // 0.04
41
+ * answers.layout.choice // 'landing'
42
+ * ```
43
+ *
44
+ * @remarks
45
+ * - **The service has NO authentication** and binds `127.0.0.1` by default.
46
+ * Never publish its port: reach it over a private network, or put an
47
+ * authenticating reverse proxy in front and set `INTERN_DECISION_API_KEY`
48
+ * (sent as `Authorization: Bearer …` — the service itself ignores it).
49
+ * - **Default port is 7860**, not 8000: `INTERN_DECISION_URL` defaults to
50
+ * `http://127.0.0.1:7860`.
51
+ * - **One checkpoint per server; `model` is ignored.** The service answers with
52
+ * whatever `MODEL_CHECKPOINT` it loaded (`result.model` is always
53
+ * `'intern-decision'`). Run a second server for a second size.
54
+ * - **Limits (checked here before sending, else a 422):** 1–16 questions per
55
+ * request, 1–62 options per `choice` or levels per `score`, up to 8 images of
56
+ * PNG / JPEG / WebP / still GIF, each ≤12 MB decoded and ≤32 MB total (and
57
+ * ≤16 million pixels — checked by the server only). `images[].data` is raw
58
+ * base64 — no `data:` prefix.
59
+ * - **Input is capped at 8,192 tokens** by default (`MAX_INPUT_LENGTH` on the
60
+ * server). Put the decisive text first.
61
+ * - **Requests are serialized** on the server (one model lock); concurrent
62
+ * calls queue rather than fail. A loading server answers 503; this bond
63
+ * retries 429/502/503/504/529 up to 3 times. Errors carry the HTTP `status`.
64
+ * - **Calibration:** each checkpoint ships a fitted temperature (2B: 2.1),
65
+ * applied only when the server is configured with its calibration file —
66
+ * and the HF and XTuner backends give slightly different probabilities.
67
+ * Calibrate on labelled samples of your inputs and gate on `minConfidence`.
68
+ * - **Not a chat model and does not reason.** It picks among the options you
69
+ * describe; the service's optional "thinking" handoff to an external LLM is
70
+ * not used by this bond.
71
+ * - **License:** the code is Apache-2.0; the weights' Hugging Face cards say
72
+ * Apache-2.0 while the repo README says Qwen model terms apply — check
73
+ * LICENSE-QWEN before offering it to third parties.
74
+ * - Use the core's `setProvider`, not `bond('ai-decisions', …)` directly.
75
+ *
76
+ * @module
77
+ */
78
+ export * from './browser-guard.js';
79
+ export * from './provider.js';
80
+ export * from './secrets.js';
81
+ export * from './types.js';
82
+ export * from './wire.js';
83
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AAEH,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Intern-Decision decisions provider for molecule.dev — typed decisions about
3
+ * text AND images from the open-weights Intern-Decision models on a server
4
+ * you run.
5
+ *
6
+ * Intern-Decision (github.com/internlm/Intern-Decision, from InternLM) is a
7
+ * family of Qwen3.5 fine-tunes — 0.8B, 2B and 4B — that answer `choice`,
8
+ * `score` and yes/no questions with a probability per option, and can read up
9
+ * to 8 images alongside the text (a screenshot, a photo, a scanned form). Its
10
+ * maker reports 90.0% average accuracy for the 4B (44 ms/request) and 84.7%
11
+ * for the 2B (33 ms on an RTX 4090). This bond speaks the service's
12
+ * `POST /v1/decisions` route; the question and answer shapes match the Jev /
13
+ * Laya / Jeff bonds, so swapping is a one-line change.
14
+ *
15
+ * @example
16
+ * ```bash
17
+ * # Run the service on a GPU host (it binds 127.0.0.1:7860 and has NO auth)
18
+ * git clone https://github.com/internlm/Intern-Decision && cd Intern-Decision
19
+ * python -m venv .venv && . .venv/bin/activate
20
+ * pip install -r requirements-inference.txt
21
+ * MODEL_CHECKPOINT=/models/Intern-Decision-2B bash scripts/demo.sh
22
+ * ```
23
+ *
24
+ * ```typescript
25
+ * import { readFileSync } from 'node:fs'
26
+ *
27
+ * import { setProvider, requireProvider } from '@molecule/api-ai-decisions'
28
+ * import { provider } from '@molecule/api-ai-decisions-intern-decision'
29
+ *
30
+ * setProvider(provider) // reads INTERN_DECISION_URL (+ INTERN_DECISION_API_KEY for a proxy) on first use
31
+ *
32
+ * const { answers } = await requireProvider().decide({
33
+ * state: 'A screenshot of the app preview after deploy.',
34
+ * images: [{ mimeType: 'image/png', data: readFileSync('preview.png').toString('base64') }],
35
+ * questions: {
36
+ * blank: { type: 'yesNo', instructions: 'The page is blank or shows only an error.' },
37
+ * layout: { type: 'choice', instructions: 'What does the page show?', criteria: { landing: 'a marketing page', app: 'an app screen', error: 'an error page' } },
38
+ * },
39
+ * })
40
+ * answers.blank.probability // 0.04
41
+ * answers.layout.choice // 'landing'
42
+ * ```
43
+ *
44
+ * @remarks
45
+ * - **The service has NO authentication** and binds `127.0.0.1` by default.
46
+ * Never publish its port: reach it over a private network, or put an
47
+ * authenticating reverse proxy in front and set `INTERN_DECISION_API_KEY`
48
+ * (sent as `Authorization: Bearer …` — the service itself ignores it).
49
+ * - **Default port is 7860**, not 8000: `INTERN_DECISION_URL` defaults to
50
+ * `http://127.0.0.1:7860`.
51
+ * - **One checkpoint per server; `model` is ignored.** The service answers with
52
+ * whatever `MODEL_CHECKPOINT` it loaded (`result.model` is always
53
+ * `'intern-decision'`). Run a second server for a second size.
54
+ * - **Limits (checked here before sending, else a 422):** 1–16 questions per
55
+ * request, 1–62 options per `choice` or levels per `score`, up to 8 images of
56
+ * PNG / JPEG / WebP / still GIF, each ≤12 MB decoded and ≤32 MB total (and
57
+ * ≤16 million pixels — checked by the server only). `images[].data` is raw
58
+ * base64 — no `data:` prefix.
59
+ * - **Input is capped at 8,192 tokens** by default (`MAX_INPUT_LENGTH` on the
60
+ * server). Put the decisive text first.
61
+ * - **Requests are serialized** on the server (one model lock); concurrent
62
+ * calls queue rather than fail. A loading server answers 503; this bond
63
+ * retries 429/502/503/504/529 up to 3 times. Errors carry the HTTP `status`.
64
+ * - **Calibration:** each checkpoint ships a fitted temperature (2B: 2.1),
65
+ * applied only when the server is configured with its calibration file —
66
+ * and the HF and XTuner backends give slightly different probabilities.
67
+ * Calibrate on labelled samples of your inputs and gate on `minConfidence`.
68
+ * - **Not a chat model and does not reason.** It picks among the options you
69
+ * describe; the service's optional "thinking" handoff to an external LLM is
70
+ * not used by this bond.
71
+ * - **License:** the code is Apache-2.0; the weights' Hugging Face cards say
72
+ * Apache-2.0 while the repo README says Qwen model terms apply — check
73
+ * LICENSE-QWEN before offering it to third parties.
74
+ * - Use the core's `setProvider`, not `bond('ai-decisions', …)` directly.
75
+ *
76
+ * @module
77
+ */
78
+ export * from './browser-guard.js';
79
+ export * from './provider.js';
80
+ export * from './secrets.js';
81
+ export * from './types.js';
82
+ export * from './wire.js';
83
+ //# sourceMappingURL=index.js.map