bkper 5.1.0 → 5.2.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 (44) hide show
  1. package/README.md +16 -0
  2. package/lib/agent/extensions/bkper-ai-provider.d.ts.map +1 -1
  3. package/lib/agent/extensions/bkper-ai-provider.js +47 -16
  4. package/lib/agent/extensions/bkper-ai-provider.js.map +1 -1
  5. package/lib/agent/extensions/builtins.d.ts.map +1 -1
  6. package/lib/agent/extensions/builtins.js +10 -2
  7. package/lib/agent/extensions/builtins.js.map +1 -1
  8. package/lib/agent/extensions/startup-logo.d.ts +9 -0
  9. package/lib/agent/extensions/startup-logo.d.ts.map +1 -0
  10. package/lib/agent/extensions/startup-logo.js +96 -0
  11. package/lib/agent/extensions/startup-logo.js.map +1 -0
  12. package/lib/agent/extensions/startup.d.ts.map +1 -1
  13. package/lib/agent/extensions/startup.js +63 -33
  14. package/lib/agent/extensions/startup.js.map +1 -1
  15. package/lib/agent/interactive/prompt-history-store.d.ts +1 -0
  16. package/lib/agent/interactive/prompt-history-store.d.ts.map +1 -1
  17. package/lib/agent/interactive/prompt-history-store.js +19 -5
  18. package/lib/agent/interactive/prompt-history-store.js.map +1 -1
  19. package/lib/agent/interactive/run-agent-mode.d.ts.map +1 -1
  20. package/lib/agent/interactive/run-agent-mode.js +5 -2
  21. package/lib/agent/interactive/run-agent-mode.js.map +1 -1
  22. package/lib/agent/interactive/settings.d.ts +26 -4
  23. package/lib/agent/interactive/settings.d.ts.map +1 -1
  24. package/lib/agent/interactive/settings.js +106 -16
  25. package/lib/agent/interactive/settings.js.map +1 -1
  26. package/lib/agent/interactive/themes.d.ts +13 -0
  27. package/lib/agent/interactive/themes.d.ts.map +1 -0
  28. package/lib/agent/interactive/themes.js +36 -0
  29. package/lib/agent/interactive/themes.js.map +1 -0
  30. package/lib/agent/system-prompt.d.ts.map +1 -1
  31. package/lib/agent/system-prompt.js +19 -7
  32. package/lib/agent/system-prompt.js.map +1 -1
  33. package/lib/agent/themes/bkper-dark.json +80 -0
  34. package/lib/agent/themes/bkper-light.json +80 -0
  35. package/lib/cli.js +1 -1
  36. package/lib/cli.js.map +1 -1
  37. package/lib/commands/agent-command.d.ts.map +1 -1
  38. package/lib/commands/agent-command.js +2 -1
  39. package/lib/commands/agent-command.js.map +1 -1
  40. package/lib/docs/ai/decision-models.md +316 -0
  41. package/lib/docs/apps/ai.md +120 -88
  42. package/lib/docs/apps/overview.md +1 -1
  43. package/lib/docs/index.md +2 -1
  44. package/package.json +6 -4
package/lib/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-command.d.ts","sourceRoot":"","sources":["../../src/commands/agent-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAGH,KAAK,cAAc,EACtB,MAAM,wCAAwC,CAAC;AAGhD,MAAM,WAAW,uBAAuB;IACpC,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACrC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,kBAAkB,EAAE,CAAC,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACzC;AAwGD,wBAAsB,eAAe,CACjC,MAAM,EAAE,MAAM,EAAE,EAChB,YAAY,GAAE,wBAAsD,GACrE,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAM5D"}
1
+ {"version":3,"file":"agent-command.d.ts","sourceRoot":"","sources":["../../src/commands/agent-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAGH,KAAK,cAAc,EACtB,MAAM,wCAAwC,CAAC;AAGhD,MAAM,WAAW,uBAAuB;IACpC,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACrC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,kBAAkB,EAAE,CAAC,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACzC;AAyGD,wBAAsB,eAAe,CACjC,MAAM,EAAE,MAAM,EAAE,EAChB,YAAY,GAAE,wBAAsD,GACrE,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAQ5D"}
@@ -76,6 +76,7 @@ const PI_MANAGEMENT_COMMANDS = new Set([
76
76
  'update',
77
77
  'list',
78
78
  'config',
79
+ 'mcp',
79
80
  ]);
80
81
  function isPiManagementCommand(args) {
81
82
  const [command] = args;
@@ -135,7 +136,7 @@ export function runAgentCommand(piArgs_1) {
135
136
  export function registerAgentCommands(program) {
136
137
  program
137
138
  .command('agent [piArgs...]')
138
- .description('Start Bkper Agent or run Pi CLI with Bkper defaults')
139
+ .description('Start Bkper Agent, or run Pi CLI commands as `bkper agent <command>` (e.g. `bkper agent mcp add`)')
139
140
  .allowUnknownOption(true)
140
141
  .allowExcessArguments(true);
141
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"agent-command.js","sourceRoot":"","sources":["../../src/commands/agent-command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-command.js","sourceRoot":"","sources":["../../src/commands/agent-command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,316 @@
1
+ # Decision Models
2
+
3
+ A decision model answers bounded questions about a state. Each answer is typed: the probability that a statement is true, one option from a set you define, or a level on a scale you define. The model writes no text. The model evaluates; your code decides.
4
+
5
+ `POST /v1/decisions` serves decision models: models trained for calibrated decisions. [Jev](#jev-by-typesafe), from TypeSafe, is the first. The interface and its concepts come from TypeSafe's [System One](https://docs.typesafe.ai/concepts/system-one) API, and their documentation is a good companion to this page.
6
+
7
+ ## When to use a decision model
8
+
9
+ | When your code needs | Use |
10
+ | ------------------------------------------------------------- | --------------------------------------------------------------- |
11
+ | A yes/no, one of known options, or a level on a scale | A decision model |
12
+ | Text, explanations, code, tool calls, or a custom JSON object | A [language model](https://bkper.com/docs/ai/ai-gateway.md#send-a-complete-request) |
13
+
14
+ Why decision models suit accounting operations is covered in [AI Fundamentals](https://bkper.com/docs/ai/fundamentals.md#decision-models).
15
+
16
+ ## How a request works
17
+
18
+ A request has one **state** and one or more **questions**. The state is what the model judges: a string, JSON object, or array. Prefer an object with descriptive field names. Decision models currently read text only, so convert images and files to text first.
19
+
20
+ The model evaluates each question independently, in parallel, against the same state, and returns one typed answer per question. There are three question types:
21
+
22
+ - **`noul`** — _Is this true?_ Optional `criteria` describe what yes and no mean. Returns `noul`, the probability of yes from 0 to 1.
23
+ - **`choice`** — _Which one of these?_ `criteria` maps 1–255 options to descriptions, or `null`. Returns the `choice` with `probabilities` and `confidence`.
24
+ - **`score`** — _Which level on this scale?_ `criteria` lists 2–10 levels, lowest first. Returns a weighted `score` with `legend`, `probabilities`, and `confidence`.
25
+
26
+ Ask one snap judgment per question — something a knowledgeable person decides in seconds. Split bigger judgments into several questions and combine the answers in code. Keep arithmetic, balances, and date comparisons in code too, and ask the model only the part that needs judgment. See TypeSafe's [Primitives](https://docs.typesafe.ai/primitives) and [State](https://docs.typesafe.ai/concepts/state).
27
+
28
+ ## Send a request
29
+
30
+ For an incoming bank line, this request asks three questions at once: which Account it belongs to, whether it is already recorded, and how urgently it needs review.
31
+
32
+ ```bash
33
+ curl --fail-with-body https://ai.bkper.app/v1/decisions \
34
+ -H "Authorization: Bearer ${BKPER_TOKEN}" \
35
+ -H "Content-Type: application/json" \
36
+ -H "bkper-ai-source: my-app" \
37
+ --data '{
38
+ "model": "jev",
39
+ "state": {
40
+ "bank_line": {
41
+ "date": "2025-03-11",
42
+ "description": "AMAZON MKTPL*2K4LM",
43
+ "amount": 89.90,
44
+ "direction": "money out of Checking"
45
+ },
46
+ "existing_transaction": {
47
+ "date": "2025-03-10",
48
+ "amount": 89.90,
49
+ "from": "Checking",
50
+ "to": "Office Supplies",
51
+ "description": "Printer toner, Amazon order 114-2K4LM",
52
+ "origin": "manual entry"
53
+ }
54
+ },
55
+ "questions": {
56
+ "account": {
57
+ "type": "choice",
58
+ "instructions": "Which Account should receive the money that left Checking in `bank_line`?",
59
+ "criteria": {
60
+ "Cloud Hosting": "Servers, cloud infrastructure, storage, and hosting providers",
61
+ "Software Subscriptions": "SaaS tools and per-seat software licenses",
62
+ "Office Supplies": "Physical supplies and equipment for the office",
63
+ "Travel": "Flights, hotels, ground transport, and meals while traveling"
64
+ }
65
+ },
66
+ "already_recorded": {
67
+ "type": "noul",
68
+ "instructions": "Does `existing_transaction` already record the movement in `bank_line`?"
69
+ },
70
+ "review_priority": {
71
+ "type": "score",
72
+ "instructions": "How urgently should a bookkeeper review `bank_line`?",
73
+ "criteria": [
74
+ "Routine: consistent with normal activity",
75
+ "Check: unusual but plausibly legitimate",
76
+ "Urgent: large, unapproved, or suspicious"
77
+ ]
78
+ }
79
+ }
80
+ }'
81
+ ```
82
+
83
+ - **`model`** — any model with `type: "decision"` in [`GET /v1/models`](https://bkper.com/docs/ai/ai-gateway.md#model-ids). Each entry lists its `question_types`, `context_window`, and `max_state_question_tokens`.
84
+ - **Question IDs** such as `account` are yours. Answers come back under the same IDs, but **IDs are not sent to the model**, so each `instructions` must stand on its own.
85
+ - **Refer to state fields by name** in backticks, as in `` `bank_line` ``.
86
+ - Each question accepts only `type`, `instructions`, and `criteria`. Instructions, descriptions, and levels can be strings or [structured JSON](https://docs.typesafe.ai/primitives/advanced).
87
+
88
+ ## Read the response
89
+
90
+ A real response to the request above:
91
+
92
+ ```json
93
+ {
94
+ "model": "jev-1.13.0",
95
+ "answers": {
96
+ "account": {
97
+ "type": "choice",
98
+ "choice": "Office Supplies",
99
+ "confidence": 1,
100
+ "probabilities": {
101
+ "Office Supplies": 1,
102
+ "Cloud Hosting": 0,
103
+ "Travel": 0,
104
+ "Software Subscriptions": 0
105
+ }
106
+ },
107
+ "already_recorded": {
108
+ "type": "noul",
109
+ "noul": 0.89
110
+ },
111
+ "review_priority": {
112
+ "type": "score",
113
+ "score": 0.09,
114
+ "confidence": 0.86,
115
+ "legend": {
116
+ "0": "Routine: consistent with normal activity",
117
+ "1": "Check: unusual but plausibly legitimate",
118
+ "2": "Urgent: large, unapproved, or suspicious"
119
+ },
120
+ "probabilities": {
121
+ "0": 0.91,
122
+ "1": 0.09,
123
+ "2": 0
124
+ }
125
+ }
126
+ },
127
+ "usage": { "input_tokens": 607, "output_tokens": 86 }
128
+ }
129
+ ```
130
+
131
+ Bkper validates every answer before returning it, so your code can rely on these guarantees:
132
+
133
+ - `answers` has exactly one entry per question ID, and each answer's `type` matches its question.
134
+ - `choice` is always one of your `criteria` keys.
135
+ - `score` is the probability-weighted level, from `0` to the number of levels minus one. It can fall between levels.
136
+ - `probabilities` has one entry per option or level, and `legend` maps level indexes back to your text. Read both by key: order is not guaranteed, and values can be exactly `0` or `1`.
137
+ - `confidence`, on choice and score answers, runs from 0 to 1 and is higher when probability concentrates on one answer. Noul answers have no `confidence`; the probability itself is the signal. See TypeSafe's [Confidence](https://docs.typesafe.ai/confidence).
138
+ - `model` is the concrete revision that answered, such as `jev-1.13.0`.
139
+
140
+ Usage counts against your allowance at the model's [usage rates](https://bkper.com/docs/ai/models.md#usage-rates).
141
+
142
+ ### Context changes confidence
143
+
144
+ Ask about the same bank line without `existing_transaction`:
145
+
146
+ ```json
147
+ {
148
+ "model": "jev",
149
+ "state": {
150
+ "bank_line": {
151
+ "date": "2025-03-11",
152
+ "description": "AMAZON MKTPL*2K4LM",
153
+ "amount": 89.9,
154
+ "direction": "money out of Checking"
155
+ }
156
+ },
157
+ "questions": {
158
+ "account": {
159
+ "type": "choice",
160
+ "instructions": "Which Account should receive the money that left Checking in `bank_line`?",
161
+ "criteria": {
162
+ "Cloud Hosting": "Servers, cloud infrastructure, storage, and hosting providers",
163
+ "Software Subscriptions": "SaaS tools and per-seat software licenses",
164
+ "Office Supplies": "Physical supplies and equipment for the office",
165
+ "Travel": "Flights, hotels, ground transport, and meals while traveling"
166
+ }
167
+ }
168
+ }
169
+ }
170
+ ```
171
+
172
+ ```json
173
+ {
174
+ "model": "jev-1.13.0",
175
+ "answers": {
176
+ "account": {
177
+ "type": "choice",
178
+ "choice": "Office Supplies",
179
+ "confidence": 0.75,
180
+ "probabilities": {
181
+ "Software Subscriptions": 0.14,
182
+ "Cloud Hosting": 0.02,
183
+ "Office Supplies": 0.81,
184
+ "Travel": 0.02
185
+ }
186
+ }
187
+ },
188
+ "usage": { "input_tokens": 440, "output_tokens": 52 }
189
+ }
190
+ ```
191
+
192
+ The top option is the same, but confidence drops from 1 to 0.75: the model reports that it is less sure.
193
+
194
+ Give the model the context a person would need, such as nearby Transactions, how an Account is usually described, or Book and Account properties. Select that context in code. For example, find Transactions with the same amount inside a date window, then ask the model only whether the descriptions describe the same movement.
195
+
196
+ ## Turn answers into decisions
197
+
198
+ An answer is a judgment, not permission to change a Book. Your code owns the thresholds and the actions, and sends uncertain cases to a person. This is TypeSafe's [confidence-gated routing](https://docs.typesafe.ai/patterns/confidence-routing) pattern:
199
+
200
+ ```ts
201
+ // Keep questions and thresholds in one reviewable place.
202
+ const DUPLICATE_THRESHOLD = 0.8;
203
+ const REVIEW_SCORE_THRESHOLD = 1.5;
204
+ const AUTO_POST_CONFIDENCE = 0.9;
205
+
206
+ interface BankLineAnswers {
207
+ account: { type: 'choice'; choice: string; confidence: number };
208
+ already_recorded: { type: 'noul'; noul: number };
209
+ review_priority: { type: 'score'; score: number; confidence: number };
210
+ }
211
+
212
+ type BankLineDecision =
213
+ | { action: 'check-duplicate' }
214
+ | { action: 'review'; suggestedAccount: string }
215
+ | { action: 'post'; toAccount: string; confidence: number };
216
+
217
+ export function decideBankLine(answers: BankLineAnswers): BankLineDecision {
218
+ if (answers.already_recorded.noul >= DUPLICATE_THRESHOLD) {
219
+ return { action: 'check-duplicate' };
220
+ }
221
+ if (
222
+ answers.review_priority.score >= REVIEW_SCORE_THRESHOLD ||
223
+ answers.account.confidence < AUTO_POST_CONFIDENCE
224
+ ) {
225
+ return { action: 'review', suggestedAccount: answers.account.choice };
226
+ }
227
+ return {
228
+ action: 'post',
229
+ toAccount: answers.account.choice,
230
+ confidence: answers.account.confidence,
231
+ };
232
+ }
233
+ ```
234
+
235
+ The first response returns `check-duplicate`: the movement is probably already recorded. The bank line on its own, at 0.75 confidence, goes to `review`.
236
+
237
+ When your code does post, it creates a normal Transaction from `Checking` to the chosen Account, so the Book stays zero-sum whatever the model answered. The risks to control are a wrong Account and a duplicate movement, which is why those checks come before posting. Store `model` and `confidence` as Transaction properties for the audit trail.
238
+
239
+ Start with conservative thresholds, test them against your own records, and re-check them when the returned `model` changes. For more designs, see TypeSafe's [Patterns](https://docs.typesafe.ai/patterns) and [Cookbooks](https://docs.typesafe.ai/cookbooks), and the open-source [Merge Duplicates app](https://github.com/bkper/bkper-apps/tree/main/merge-duplicates), which suggests duplicate pairs for human review.
240
+
241
+ ## Call from code
242
+
243
+ TypeSafe's JavaScript SDK, `@typesafe-ai/sdk`, works with Bkper AI and infers answer types from your questions. Any other HTTP client can call `POST /v1/decisions` directly:
244
+
245
+ - **In a Bkper Platform app Worker**, send no `Authorization` header. Platform outbound adds authorization and app attribution.
246
+ - **In scripts and servers**, send your own Bkper access token as a bearer token.
247
+ - **In [Bkper CLI Agent](https://bkper.com/docs/ai/bkper-cli-agent.md#what-it-can-do)**, no setup is needed. Describe the outcome and the agent asks the decision model for you.
248
+
249
+ See [Add Bkper AI to an App](https://bkper.com/docs/platform/apps/ai.md#ask-a-decision-model) for the SDK setup in both cases and its limits with Bkper AI.
250
+
251
+ ## Errors and retries
252
+
253
+ Errors use the same envelope as every [Bkper AI endpoint](https://bkper.com/docs/ai/ai-gateway.md#errors). Branch on `error.code`, not only on the HTTP status:
254
+
255
+ ```json
256
+ {
257
+ "error": {
258
+ "message": "Unknown field: questions.route.threshold.",
259
+ "type": "invalid_request_error",
260
+ "param": "questions.route.threshold",
261
+ "code": "invalid_request"
262
+ }
263
+ }
264
+ ```
265
+
266
+ | Status | `error.code` | What to do |
267
+ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
268
+ | `400` | `invalid_request`, `missing_model`, `unsupported_model`, `invalid_state`, `invalid_questions`, `invalid_question`, `unsupported_question_type` | Fix the field named in `error.param`. Do not retry unchanged. |
269
+ | `400` | `provider_rejected` | The model rejected the request. Check its size against the model's limits. |
270
+ | `401`–`403` | `unauthorized`, `billing_overdue`, `entitlement_unavailable` | Fix authentication or account access. Do not retry. |
271
+ | `429` | `usage_limit_exceeded` | The monthly allowance is exhausted. Do not retry. |
272
+ | `429` | `provider_rate_limited` | Retry with backoff. Honor `retry-after` when present. |
273
+ | `503` | `provider_overloaded`, `usage_unavailable` | Retry with backoff. Honor `retry-after` when present. |
274
+ | `502` | `provider_error`, `provider_rejected` | Retry a limited number of times, then fail. |
275
+
276
+ ## Caching
277
+
278
+ Bkper caches decision results for 15 minutes per user. An identical request in that window returns the same answers without calling the model or consuming allowance, and repeats the original `usage`. Aliases of the same model share one cache entry. To get fresh answers, change the request or wait. See [Privacy, retention, and caching](https://bkper.com/docs/ai/ai-gateway.md#privacy-retention-and-caching).
279
+
280
+ ## Common mistakes
281
+
282
+ - **Sending Responses fields.** The body accepts only `model`, `state`, and `questions`. `input`, `stream`, `store`, `temperature`, and `metadata` are rejected.
283
+ - **Putting the question in the ID.** The model never sees IDs. Write the full question in `instructions`.
284
+ - **Asking for analysis.** Ask one snap judgment per question and combine answers in code.
285
+ - **Asking the model to calculate.** Match amounts, compute date windows, and check balances in code.
286
+ - **Treating `noul` as a boolean or `score` as an integer.** Both are continuous. Compare them with thresholds.
287
+ - **Expecting an explanation.** Decision models return no text. Use a [language model](https://bkper.com/docs/ai/ai-gateway.md) when you need one.
288
+
289
+ ## Jev by TypeSafe
290
+
291
+ [Jev](https://docs.typesafe.ai/introduction) is TypeSafe's flagship model and the first System One model. Its Bkper model ID is `jev`.
292
+
293
+ - **Versions.** `jev-latest` and versioned IDs are accepted but always select the current Jev; you cannot pin a version. Log the returned `model`, and re-check tuned thresholds when it changes.
294
+ - **Input.** Text only. English is Jev's primary training language; other languages work with lower accuracy.
295
+ - **Known weak spots.** Literal reading, arithmetic, date comparison, and large states full of irrelevant detail. See [Jev 1.13 jaggedness](https://docs.typesafe.ai/model-jaggedness/jev-1.13).
296
+
297
+ ### Differences from the TypeSafe API
298
+
299
+ Request and answer shapes match TypeSafe's [`POST /v1/systemone`](https://docs.typesafe.ai/api), so TypeSafe's guidance on questions, state, confidence, and patterns applies unchanged. Only the surroundings differ:
300
+
301
+ - **Endpoint and authentication.** Call `https://ai.bkper.app/v1/decisions` with a Bkper access token. TypeSafe API keys do not work here.
302
+ - **SDKs.** TypeSafe SDKs work with base URL `https://ai.bkper.app` and a Bkper access token. See [Call from code](#call-from-code).
303
+ - **Errors.** Bkper returns `400` where TypeSafe returns `422`, and `503` with `provider_overloaded` where TypeSafe returns `529`. A `429` can also mean your Bkper AI allowance is exhausted.
304
+ - **Usage.** Requests count against your [Bkper AI allowance](https://bkper.com/docs/ai/models.md#how-usage-works), not a TypeSafe account.
305
+
306
+ ### Build with a coding agent
307
+
308
+ TypeSafe's [agent skill](https://docs.typesafe.ai/agent-skill) gives coding agents context on questions and patterns. When you use it for a Bkper integration, point the agent to this page — `https://bkper.com/docs/ai/decision-models.md` — for the endpoint, authentication, model ID, and errors.
309
+
310
+ ## Learn more
311
+
312
+ - [`createDecision` API reference](https://bkper.com/docs/api/ai/operations/createdecision.md) — the field-by-field contract.
313
+ - [Models and Usage](https://bkper.com/docs/ai/models.md) — decision models, limits, and usage rates.
314
+ - [Bkper AI Gateway](https://bkper.com/docs/ai/ai-gateway.md) — access, tokens, and privacy.
315
+ - [Add Bkper AI to an App](https://bkper.com/docs/platform/apps/ai.md) — TypeSafe SDK setup for apps and scripts.
316
+ - TypeSafe: [System One](https://docs.typesafe.ai/concepts/system-one), [AI primer](https://docs.typesafe.ai/introduction/machine-learning-primer), [Primitives](https://docs.typesafe.ai/primitives), [State](https://docs.typesafe.ai/concepts/state), [Confidence](https://docs.typesafe.ai/confidence), and [Patterns](https://docs.typesafe.ai/patterns).
@@ -1,123 +1,155 @@
1
1
  # Add Bkper AI to an App
2
2
 
3
- Bkper Platform apps can call [Bkper AI](https://bkper.com/docs/ai/ai-gateway.md) without storing a model-provider key. The platform authorizes the Worker's request using the current user and attributes usage to the app. Model output is a suggestion, not permission to change a Book: keep decisions about resource movements and any resulting writes in application code.
3
+ Bkper Platform apps can call [Bkper AI](https://bkper.com/docs/ai/ai-gateway.md) without storing a model-provider key. The platform authorizes each request as the current user and attributes usage to the app. Scripts and servers outside the platform use the same code with their own Bkper token.
4
4
 
5
- This guide covers a server-side, non-streaming language response. It uses AI SDK to draft a review note from a transaction description. No Book data is written by the example.
5
+ Model output is a suggestion, not permission to change a Book. Keep decisions about resource movements, and any resulting writes, in application code.
6
6
 
7
7
  ## Choose the kind of response
8
8
 
9
- - **A bounded yes/no, choice, or score?** Use a typed evaluation at `POST /v1/evaluations`.
10
- - **Generated text or a custom JSON object?** Use a language model at `POST /v1/responses`. AI SDK is an option for this path.
9
+ - **A yes/no, a choice, or a level on a scale?** Ask a decision model, such as `jev`, with TypeSafe's SDK, `@typesafe-ai/sdk`.
10
+ - **Text or a custom JSON object?** Ask a language model (LLM), such as `gpt-luna`, with AI SDK's Open Responses provider, `@ai-sdk/open-responses`.
11
11
 
12
- Pick a model of the corresponding `type` from the live [`GET /v1/models` catalog](https://ai.bkper.app/v1/models). The catalog also tells you which language models support strict structured output. AI SDK's **Open Responses provider** covers language responses, not Bkper's typed evaluation endpoint. For evaluation models, use HTTP or implement an AI SDK evaluation-model adapter for `experimental_evaluate`, as `bkper-agent` does. See the [Typed Evaluations guide](https://bkper.com/docs/ai/evaluations.md) for requests, responses, decision thresholds, and errors, and the [Merge Duplicates app](https://github.com/bkper/bkper-apps/tree/main/merge-duplicates) for a human-reviewed HTTP example.
12
+ Add the SDK to the **Worker** package. Keep the call in a server service used by your authenticated app API route, and define the route's request and response in the app's Zod/OpenAPI contract.
13
13
 
14
14
  ## Keep authentication in the platform
15
15
 
16
16
  For an interactive app, the flow is:
17
17
 
18
- 1. The client calls a typed app `/api/*` route through `auth.authenticatedFetch()` (or another authenticated client). The template's generated API client can use that fetch provider.
18
+ 1. The client calls a typed app `/api/*` route through `auth.authenticatedFetch()` or another authenticated client.
19
19
  2. Bkper verifies the user's token, removes it before invoking the Worker, and establishes user and app context for outbound requests.
20
- 3. The Worker calls `https://ai.bkper.app/v1/*`. Platform outbound adds authorization and app attribution. **Do not read, forward, or store the user's token in the Worker.**
20
+ 3. The Worker calls Bkper AI. Platform outbound adds authorization and app attribution. **Do not read, forward, or store the user's token in the Worker.**
21
21
 
22
- An authenticated `/events` handler has the same outbound context. A page request does not; start interactive inference from an authenticated `/api/*` route, not from the page handler or the browser.
22
+ An authenticated `/events` handler has the same outbound context. A page request does not; start inference from an authenticated `/api/*` route, not from the page handler or the browser.
23
23
 
24
- ## Example: draft a review note with AI SDK
24
+ ## Ask a decision model
25
25
 
26
- Add `ai`, `@ai-sdk/open-responses`, and `zod` to the **Worker** package. Keep this code in a server service called from your authenticated app API route; define the route's request and response in the app's Zod/OpenAPI contract. The service takes only the description needed for this task, discovers the current language model, and validates its output before returning it to the caller.
26
+ ```ts
27
+ import { score, TypeSafeClient } from '@typesafe-ai/sdk';
28
+
29
+ const decisionClient = new TypeSafeClient({
30
+ apiKey: 'bkper-platform-outbound',
31
+ baseURL: 'https://ai.bkper.app',
32
+ defaultModel: 'jev',
33
+ });
34
+
35
+ export async function scoreRecurring(description: string) {
36
+ const { answers } = await decisionClient.systemOne({
37
+ state: { description },
38
+ questions: {
39
+ recurring: score('How likely is this a recurring charge?', [
40
+ 'Unlikely',
41
+ 'Possible',
42
+ 'Likely',
43
+ ]),
44
+ },
45
+ });
46
+ return answers.recurring;
47
+ }
48
+ ```
49
+
50
+ - **`apiKey`** is required by the SDK. In a Platform Worker, pass any placeholder: platform outbound replaces it with the user's authorization.
51
+ - **`baseURL`** has no `/v1`. The SDK calls `POST /v1/systemone`, which behaves exactly like `POST /v1/decisions`.
52
+ - **The answer is typed** from the question. Bkper AI validates every answer against its question before responding, so your code can use it directly.
53
+
54
+ The Decision Models guide covers questions, state, answers, and thresholds. The open-source [Merge Duplicates app](https://github.com/bkper/bkper-apps/tree/main/merge-duplicates) uses this setup to suggest duplicate pairs for human review.
55
+
56
+ ## Generate a language response
27
57
 
28
58
  ```ts
29
59
  import { createOpenResponses } from '@ai-sdk/open-responses';
30
60
  import { generateText, Output } from 'ai';
31
61
  import { z } from 'zod';
32
62
 
33
- const BASE_URL = 'https://ai.bkper.app/v1';
34
- const ReviewNote = z.strictObject({ note: z.string() });
35
-
36
- export async function draftReviewNote(
37
- description: string,
38
- fetcher: typeof fetch = fetch
39
- ): Promise<{ note: string }> {
40
- const response = await fetcher(`${BASE_URL}/models`);
41
- if (!response.ok) throw new Error(`Model discovery failed (${response.status}).`);
42
-
43
- const catalog = z
44
- .object({
45
- default_model: z.string(),
46
- data: z.array(
47
- z.object({
48
- id: z.string(),
49
- type: z.string(),
50
- structured_output: z
51
- .object({
52
- json_schema: z.boolean(),
53
- strict: z.boolean(),
54
- })
55
- .optional(),
56
- })
57
- ),
58
- })
59
- .parse(await response.json());
60
- const model = catalog.data.find(item => item.id === catalog.default_model);
61
- if (
62
- model?.type !== 'language' ||
63
- !model.structured_output?.json_schema ||
64
- !model.structured_output.strict
65
- ) {
66
- throw new Error('The default model does not support strict JSON output.');
67
- }
68
-
69
- const provider = createOpenResponses({
70
- name: 'bkper-ai',
71
- url: `${BASE_URL}/responses`,
72
- fetch: fetcher,
73
- });
63
+ const llmClient = createOpenResponses({
64
+ name: 'bkper-ai',
65
+ url: 'https://ai.bkper.app/v1/responses',
66
+ });
67
+
68
+ export async function draftReviewNote(description: string) {
74
69
  const { output } = await generateText({
75
- model: provider(model.id),
76
- system: 'Draft a short, neutral review note. Do not invent facts or change Accounts.',
70
+ model: llmClient('gpt-luna'),
71
+ system: 'Draft a short, neutral review note. Do not invent facts.',
77
72
  prompt: description,
78
- output: Output.object({ schema: ReviewNote }),
79
- maxRetries: 0,
73
+ output: Output.object({ schema: z.object({ note: z.string() }) }),
80
74
  });
81
- return ReviewNote.parse(output);
75
+ return output;
82
76
  }
83
77
  ```
84
78
 
85
- **This example is for a Bkper Platform Worker.** With no SDK `apiKey`, the Open Responses provider sends no `Authorization` header; platform outbound supplies authorization and app attribution. A standalone integration such as `bkper-agent` must instead obtain and send its own Bkper OAuth token. Open Responses always requests `strict: true` for structured JSON and omits `store`; Bkper AI treats an omitted `store` as `false` and never persists response state. If you need `strict: false` for a model-supported flexible schema, use `@ai-sdk/openai` with its `.responses()` model and `strictJsonSchema: false`, as `bkper-agent` does. You may cache the catalog briefly instead of fetching it for every call.
79
+ - **No `apiKey`.** The provider then sends no `Authorization` header, and platform outbound adds it.
80
+ - **`url`** is the full `/v1/responses` URL.
81
+ - **`output`** is parsed and validated against your schema by AI SDK. The provider requests strict structured output, which every Bkper language model supports.
86
82
 
87
- The schema deliberately checks only that a `note` string exists. Constraints such as a minimum or maximum string length are **not needed for this example** and may not be supported by every model's strict JSON Schema subset. If your app needs a length limit, check it in application code after generation.
88
-
89
- ## Before using the result
83
+ Keep schemas simple. Constraints such as a string's minimum or maximum length may not be supported by every model's strict JSON Schema subset; check them in code after generation.
90
84
 
91
- - Send only task-relevant data. Validate input and Book permissions at the app API boundary. A generated note must not create, merge, or alter a transaction without deterministic application rules and any required human confirmation.
92
- - If model discovery fails or output does not match the schema, fail safely. Avoid automatic retries on actions that may consume allowance.
93
- - When the AI request fails, preserve the upstream HTTP status, error code, and message **when Bkper AI supplies them**, so users can understand failures such as an exhausted allowance. AI SDK exposes HTTP failures as `APICallError`; read the Bkper AI error envelope from `responseBody`, not from the SDK's generic message. For `NoObjectGeneratedError` or transport errors, return a safe app-defined error instead. Do not return prompts, raw responses, or stack traces to clients.
94
- - Unit-test the server service with a mocked `fetch`: verify the model's type and capability, that no `Authorization` or attribution headers leave the Worker, that only necessary data is sent and `store: true` is never requested, that malformed output is rejected, and that errors remain actionable. Then run the app's normal check/build.
85
+ ## Outside a Platform app
95
86
 
96
- For example, a route can extract the safe fields before mapping them into its typed error response:
87
+ Scripts, servers, and tools send their own Bkper token. Pass it as `apiKey`: both SDKs send it as a bearer token. Get a client each time you need one, so every call uses a current token:
97
88
 
98
89
  ```ts
99
- import { APICallError } from 'ai';
100
-
101
- function bkperAiError(error: unknown) {
102
- if (!APICallError.isInstance(error)) return null;
103
- let body: unknown;
104
- try {
105
- body = JSON.parse(error.responseBody ?? '');
106
- } catch {
107
- return null;
108
- }
109
- const parsed = z
110
- .object({
111
- error: z.object({ code: z.string(), message: z.string() }),
112
- })
113
- .safeParse(body);
114
- if (!parsed.success) return null;
115
- return {
116
- status: error.statusCode ?? 502,
117
- code: parsed.data.error.code,
118
- message: parsed.data.error.message,
119
- };
120
- }
90
+ import { createOpenResponses } from '@ai-sdk/open-responses';
91
+ import { noul, TypeSafeClient } from '@typesafe-ai/sdk';
92
+ import { generateText } from 'ai';
93
+ import { getOAuthToken } from 'bkper';
94
+
95
+ const decisionClient = async () =>
96
+ new TypeSafeClient({
97
+ apiKey: await getOAuthToken(),
98
+ baseURL: 'https://ai.bkper.app',
99
+ defaultModel: 'jev',
100
+ });
101
+
102
+ const llmClient = async () =>
103
+ createOpenResponses({
104
+ name: 'bkper-ai',
105
+ url: 'https://ai.bkper.app/v1/responses',
106
+ apiKey: await getOAuthToken(),
107
+ });
108
+
109
+ const client = await decisionClient();
110
+ const { answers } = await client.systemOne({
111
+ state: { description: 'NETFLIX.COM monthly plan' },
112
+ questions: { streaming: noul('Is this a streaming service?') },
113
+ });
114
+
115
+ const { text } = await generateText({
116
+ model: (await llmClient())('gpt-luna'),
117
+ prompt: 'Describe NETFLIX.COM monthly plan in five words.',
118
+ });
121
119
  ```
122
120
 
123
- For direct HTTP calls, advanced features, or exact request and response fields, use the [Bkper AI API reference](https://bkper.com/docs/api/ai.md) and [AI Gateway guide](https://bkper.com/docs/ai/ai-gateway.md). Bkper AI implements a documented subset of Open Responses, not every OpenAI or AI SDK feature.
121
+ - **`getOAuthToken()`** reads the credentials from `bkper auth login` and refreshes them when needed. In your own server, use your own token provider.
122
+ - **Creating a client is cheap.** Neither SDK makes a request until you ask a question.
123
+ - **Label your usage** with a `bkper-ai-source` header, such as `my-script`: `defaultHeaders` in the TypeSafe SDK, `headers` in Open Responses. In a Platform app, outbound sets the source to the app.
124
+
125
+ ## Handle errors
126
+
127
+ Every Bkper AI error has the same envelope: `{ error: { message, type, param, code } }`. Branch on `error.code`, not only on the HTTP status: a `429` can mean an exhausted allowance or a throttled provider.
128
+
129
+ - **TypeSafe SDK:** an `APIError` with `status` and the envelope in `body`, so read `error.body.error.code`. Network failures and timeouts throw `APIConnectionError`.
130
+ - **AI SDK:** an `APICallError` with `statusCode` and the envelope in `data`, so read `error.data.error.code`. Output that does not match your schema throws `NoObjectGeneratedError`.
131
+
132
+ Both SDKs retry rate limits and server errors twice by default. A failed attempt costs nothing: Bkper AI charges only successful answers.
133
+
134
+ Map these errors to your route's typed error response. Keep the code and message so users understand failures such as an exhausted allowance, but never return prompts, raw responses, or stack traces.
135
+
136
+ ## SDK notes
137
+
138
+ - **Passing your own `fetch`.** The TypeSafe SDK calls `fetch` as its own method, which the Workers runtime rejects with `Illegal invocation`. Wrap it: `fetch: (input, init) => myFetch(input, init)`. Without the option, the SDK's default works.
139
+ - **No `null` values.** The TypeSafe SDK's types accept `null` for state, instructions, and some criteria. Bkper AI rejects them with `400`.
140
+ - **No `client.models.list()`.** It expects TypeSafe's catalog shape. Use the [`GET /v1/models`](https://ai.bkper.app/v1/models) catalog.
141
+ - **Other System One clients** take `https://ai.bkper.app/v1` as their base URL.
142
+ - **Flexible JSON schemas.** Open Responses always requests `strict: true`. For a schema that needs `strict: false`, such as a typed dynamic map, use `@ai-sdk/openai` with base URL `https://ai.bkper.app/v1`, its `.responses()` model, and `strictJsonSchema: false`.
143
+
144
+ ## Before using the result
145
+
146
+ - **Send only task-relevant data.** Validate input and Book permissions at the app API boundary.
147
+ - **Keep writes deterministic.** An answer or generated text must not create, merge, or alter a Transaction without application rules and any required human confirmation.
148
+ - **Test the service.** Mock `fetch` and check what is sent, that the Worker adds no user token, and that errors stay actionable. Then run the app's normal check and build.
149
+
150
+ ## Next steps
151
+
152
+ - [Decision Models](https://bkper.com/docs/ai/decision-models.md): questions, answers, thresholds, and caching.
153
+ - [Bkper AI Gateway](https://bkper.com/docs/ai/ai-gateway.md): tokens, raw HTTP requests, errors, and privacy.
154
+ - [Models and Usage](https://bkper.com/docs/ai/models.md): model IDs, capabilities, and usage rates.
155
+ - [Bkper AI API reference](https://bkper.com/docs/api/ai.md): every request and response field.