bkper 5.8.1 → 5.8.2
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/lib/agent/bundle/agent-entry.js +3 -3
- package/lib/agent/extensions/bkper-ai-provider.d.ts.map +1 -1
- package/lib/agent/extensions/bkper-ai-provider.js +14 -4
- package/lib/agent/extensions/bkper-ai-provider.js.map +1 -1
- package/lib/agent/interactive/interactive-mode.d.ts +2 -1
- package/lib/agent/interactive/interactive-mode.d.ts.map +1 -1
- package/lib/agent/interactive/interactive-mode.js +5 -0
- package/lib/agent/interactive/interactive-mode.js.map +1 -1
- package/lib/agent/interactive/terminal.d.ts +8 -0
- package/lib/agent/interactive/terminal.d.ts.map +1 -0
- package/lib/agent/interactive/terminal.js +11 -0
- package/lib/agent/interactive/terminal.js.map +1 -0
- package/lib/agent/pi-shared-modules.d.ts +1 -1
- package/lib/agent/pi-shared-modules.d.ts.map +1 -1
- package/lib/agent/pi-shared-modules.js +1 -1
- package/lib/agent/pi-shared-modules.js.map +1 -1
- package/lib/agent/system-prompt.js +1 -1
- package/lib/agent/system-prompt.js.map +1 -1
- package/lib/docs/ai/system-one-models.md +329 -0
- package/lib/docs/api/ai-gateway.md +121 -46
- package/lib/docs/api/managed-agent.md +2 -0
- package/lib/docs/apps/ai.md +69 -14
- package/lib/docs/apps/configuration.md +2 -1
- package/lib/docs/apps/context-menu.md +141 -1
- package/lib/docs/apps/overview.md +1 -1
- package/lib/docs/apps/quality.md +1 -1
- package/lib/docs/index.md +4 -4
- package/package.json +1 -1
- package/lib/docs/ai/decision-models.md +0 -158
|
@@ -114,7 +114,7 @@ Each time the App iframe finishes loading, Bkper announces the requests it suppo
|
|
|
114
114
|
```js
|
|
115
115
|
{
|
|
116
116
|
type: 'bkper:host-ready',
|
|
117
|
-
supports: ['navigate', 'show-book', 'expand', 'login'],
|
|
117
|
+
supports: ['navigate', 'show-book', 'expand', 'login', 'app-state'],
|
|
118
118
|
}
|
|
119
119
|
```
|
|
120
120
|
|
|
@@ -124,6 +124,7 @@ Send each request only after receiving this message with its name in `supports`:
|
|
|
124
124
|
- `bkper:show-book` with `show-book`.
|
|
125
125
|
- `bkper:expand` with `expand`.
|
|
126
126
|
- `bkper:login` with `login`.
|
|
127
|
+
- `bkper:app-state` with `app-state`.
|
|
127
128
|
|
|
128
129
|
Until then, keep the normal link behavior. Register the message listener when the App starts, so it does not miss the message.
|
|
129
130
|
|
|
@@ -247,6 +248,144 @@ Bkper ignores the message when it does not come from the App iframe currently op
|
|
|
247
248
|
|
|
248
249
|
Bkper does not reply.
|
|
249
250
|
|
|
251
|
+
#### Keeping state in the Book URL
|
|
252
|
+
|
|
253
|
+
An App can keep a short state in the Book's URL, such as the report or item open in it. Reloading the Book, going Back, or opening a shared link of the Book then opens the App where the user left it:
|
|
254
|
+
|
|
255
|
+
```js
|
|
256
|
+
window.parent.postMessage({ type: 'bkper:app-state', state: 'expenses-2025' }, BKPER_ORIGIN);
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Bkper keeps the state as `appState`, next to the App's id in `app`:
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
https://bkper.app/books/abc123/transactions?app=my-app&appState=expenses-2025
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Bkper ignores the message when any of these is true:
|
|
266
|
+
|
|
267
|
+
- It does not come from the App iframe currently open in the panel.
|
|
268
|
+
- It does not come from that iframe's own origin.
|
|
269
|
+
- `app` in the Book URL names another App.
|
|
270
|
+
- `state` is not a string of at most 128 letters (`A–Z`, `a–z`), digits, `_` or `-`.
|
|
271
|
+
|
|
272
|
+
For a valid request, Bkper replaces `appState` in the Book URL without reloading Bkper or the App and without adding a history entry, so Back stays the Book's. An empty `state` removes it. Bkper does not reply.
|
|
273
|
+
|
|
274
|
+
The App reads its state back through the [`${app.state}`](#available-expressions) expression of its menu URL:
|
|
275
|
+
|
|
276
|
+
```yaml
|
|
277
|
+
menuUrl: https://my-app.bkper.app?bookId=${book.id}&state=${app.state}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
- **Opening a Book URL that names the App and its state**, such as from a link, Back, or a reload, opens the App with that state in its URL. When the App is already open, it receives the new URL in [`bkper:app-url-changed`](#live-context-updates) instead.
|
|
281
|
+
- **After a valid `bkper:app-state` that changes the App's URL**, such as a new state with `${app.state}` in its menu URL, the App receives `bkper:app-url-changed` with the state it just sent. Treat it as its own state, not a new place.
|
|
282
|
+
- **Opening the App from the menu, opening another App, or closing the App** removes `appState`.
|
|
283
|
+
|
|
284
|
+
The state is opaque to Bkper and visible in the Book's URL:
|
|
285
|
+
|
|
286
|
+
- Keep it a short reference, such as an id, not data.
|
|
287
|
+
- Anyone can write a link with any `appState`. Validate it, and treat a state the App does not recognize as no state.
|
|
288
|
+
- Older Bkper versions leave `${app.state}` in the URL unreplaced. Treat it, an empty value, or a missing one as no state.
|
|
289
|
+
|
|
290
|
+
### Files in Bkper Agent
|
|
291
|
+
|
|
292
|
+
Bkper Agent shows the HTML files it delivers, such as a report an App's API returns for the agent, beside the conversation. Each file runs in a sandboxed frame:
|
|
293
|
+
|
|
294
|
+
- **An `<iframe sandbox="allow-scripts">` with the file as its `srcdoc`.** The frame's origin is opaque (`null`), so the file cannot reach Bkper, the Agent, or their sessions.
|
|
295
|
+
- **A Content Security Policy ahead of the file's own content**: `default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src data: blob:; font-src data:; media-src data: blob:; form-action 'none'; base-uri 'none'`. Scripts and styles must be inline, and images, fonts, and media `data:` or `blob:` URLs. The file reaches no network.
|
|
296
|
+
- **Up to 1 MB.** Larger HTML files only download.
|
|
297
|
+
|
|
298
|
+
A file can use one request of the Bkper page around the Agent: `bkper:navigate`, such as for an **Open in** link that replaces the Agent with an App in the same panel and Book.
|
|
299
|
+
|
|
300
|
+
#### File host support
|
|
301
|
+
|
|
302
|
+
Each time the file's frame finishes loading, while the Agent is open in a Bkper panel that accepts navigation, the Agent tells the file:
|
|
303
|
+
|
|
304
|
+
```js
|
|
305
|
+
{
|
|
306
|
+
type: 'bkper:host-ready',
|
|
307
|
+
supports: ['navigate'],
|
|
308
|
+
origin: 'https://bkper.app',
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
- `origin` is the Bkper origin to link to. The message's `event.origin` is the Agent's, such as `https://agent.bkper.app`, because the Agent hosts the file, not Bkper.
|
|
313
|
+
- When Bkper starts accepting navigation after the file loaded, the Agent tells the file again.
|
|
314
|
+
- When the Agent is not in a Bkper panel that accepts navigation, such as the Agent opened on its own, the Agent sends nothing. Keep links as plain links that open a new tab.
|
|
315
|
+
|
|
316
|
+
#### Requesting navigation from a file
|
|
317
|
+
|
|
318
|
+
Post the Bkper URL to the Agent, at the `event.origin` of its `bkper:host-ready`:
|
|
319
|
+
|
|
320
|
+
```js
|
|
321
|
+
window.parent.postMessage(
|
|
322
|
+
{
|
|
323
|
+
type: 'bkper:navigate',
|
|
324
|
+
url: 'https://bkper.app/books/abc123/transactions?app=my-app&appState=expenses-2025',
|
|
325
|
+
},
|
|
326
|
+
agentOrigin
|
|
327
|
+
);
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
The Agent ignores the message silently unless all of these are true:
|
|
331
|
+
|
|
332
|
+
- It comes from the file's own frame.
|
|
333
|
+
- That frame has focus: the user is interacting with the file, such as by clicking in it.
|
|
334
|
+
- `url` is an absolute Bkper URL with no username or password, as for a link in the agent's replies.
|
|
335
|
+
- The Agent is open in a Bkper panel that accepts navigation.
|
|
336
|
+
|
|
337
|
+
Then the Agent asks Bkper to navigate, as when the user clicks a link in the conversation:
|
|
338
|
+
|
|
339
|
+
- **A Book page that names an App and its state** (`app` and `appState`): Bkper opens that App with that state, if the App is installed in that Book. When the Agent is open in a Book, the App replaces it in the same panel, without reloading Bkper.
|
|
340
|
+
- **A Book page without `app`**: Bkper navigates to it and the Agent stays open.
|
|
341
|
+
- **Other Bkper pages**: Bkper loads the page as a normal navigation.
|
|
342
|
+
|
|
343
|
+
Neither the Agent nor Bkper replies.
|
|
344
|
+
|
|
345
|
+
Send `bkper:navigate` only in response to a user action, such as a click. The focus rule keeps a file from navigating as it loads, but the frame keeps focus after a click, so the Agent cannot tell a click from a later request.
|
|
346
|
+
|
|
347
|
+
#### File example
|
|
348
|
+
|
|
349
|
+
Keep the link a real link to the App that opens in a new tab, so it works wherever navigation is not available:
|
|
350
|
+
|
|
351
|
+
```html
|
|
352
|
+
<a id="open-in-app" href="https://my-app.bkper.app?bookId=abc123&state=expenses-2025" target="_blank">
|
|
353
|
+
Open in My App
|
|
354
|
+
</a>
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Then turn a plain click into a navigation request once the Agent supports it:
|
|
358
|
+
|
|
359
|
+
```js
|
|
360
|
+
let host; // The Bkper origin to link to, and the Agent's origin to post to.
|
|
361
|
+
|
|
362
|
+
window.addEventListener('message', event => {
|
|
363
|
+
// Only the window around the file, the Agent, tells it what it may ask.
|
|
364
|
+
if (event.source !== window.parent) return;
|
|
365
|
+
|
|
366
|
+
const message = event.data;
|
|
367
|
+
if (message?.type !== 'bkper:host-ready' || !Array.isArray(message.supports)) return;
|
|
368
|
+
host =
|
|
369
|
+
message.supports.includes('navigate') && typeof message.origin === 'string'
|
|
370
|
+
? { bkper: message.origin, agent: event.origin }
|
|
371
|
+
: undefined;
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
document.getElementById('open-in-app').addEventListener('click', event => {
|
|
375
|
+
// Keep modified and non-primary clicks as normal links, such as opening a new tab.
|
|
376
|
+
if (!host || event.button !== 0) return;
|
|
377
|
+
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
|
|
378
|
+
|
|
379
|
+
event.preventDefault();
|
|
380
|
+
const url = new URL('/books/abc123/transactions', host.bkper);
|
|
381
|
+
url.searchParams.set('app', 'my-app');
|
|
382
|
+
url.searchParams.set('appState', 'expenses-2025');
|
|
383
|
+
window.parent.postMessage({ type: 'bkper:navigate', url: url.href }, host.agent);
|
|
384
|
+
});
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
The file cannot verify the Bkper origin itself. It posts only to the window that sent `bkper:host-ready`, and the Agent checks the URL again.
|
|
388
|
+
|
|
250
389
|
### Available expressions
|
|
251
390
|
|
|
252
391
|
The menu URL supports these dynamic expressions:
|
|
@@ -259,5 +398,6 @@ The menu URL supports these dynamic expressions:
|
|
|
259
398
|
| `${account.name}` | The selected account name |
|
|
260
399
|
| `${group.id}` | The selected group ID |
|
|
261
400
|
| `${group.name}` | The selected group name |
|
|
401
|
+
| `${app.state}` | The App's state in the Book URL, URL-encoded; empty without one. See [Keeping state in the Book URL](#keeping-state-in-the-book-url). |
|
|
262
402
|
|
|
263
403
|
For the full list of accepted expressions, see the [Menu URL variables](https://bkper.com/docs/platform/apps/configuration.md#menu-url-variables) reference.
|
|
@@ -21,7 +21,7 @@ The same Worker can expose app-defined `/api/*` routes. Treat those routes as th
|
|
|
21
21
|
Apps call Bkper AI models through the AI gateway, with no provider accounts or keys:
|
|
22
22
|
|
|
23
23
|
- **Language models** — multi-provider models over the Open Responses protocol, for text and structured output.
|
|
24
|
-
- **
|
|
24
|
+
- **System One models** — typed answers with calibrated confidence: judgments, such as yes or no, one of your options, or a level on a scale; values read from documents, such as an invoice total; and estimates of uncertain numbers. Your code decides what to do with them.
|
|
25
25
|
|
|
26
26
|
Usage counts against the user's included Bkper AI allowance. An authenticated app API route or event establishes the user and app identity, and the platform adds authorization and usage attribution to the Worker's requests. For inference used only by the UI, the client can also call Bkper AI directly with the signed-in user's token.
|
|
27
27
|
|
package/lib/docs/apps/quality.md
CHANGED
|
@@ -64,7 +64,7 @@ Start every client with this structure, so it grows by adding pieces instead of
|
|
|
64
64
|
- **Components render and report intent.** A component watches only the stores it shows and changes them only through their actions, in response to the person, never while rendering. Only its own presentation, such as an open menu or hover, stays in the component. Each component owns its CSS.
|
|
65
65
|
- **Stores ask the interface through events.** When a store needs the interface to act, such as focusing an input or scrolling to new content, it fires an event the component listens to. Stores never call components.
|
|
66
66
|
- **One module wires the stores.** It creates them and gives each the stores it depends on. Dependencies point one way. A store changes another store only through that store's actions, and reactions that span stores live in this module. Components get only the stores and actions they use; services stay inside this module.
|
|
67
|
-
- **One module owns the URL.** Only it reads or writes the URL's path, query, and `history`, mapping the URL to state. Put in the URL what a person would reload or share, such as the selected item. Standalone, add a history entry for each place the person goes, so Back works; when a place becomes another, such as a new item once saved, replace its entry. Embedded in a Book, replace the URL so Back stays the Book's. Pass it the window so it can be tested.
|
|
67
|
+
- **One module owns the URL.** Only it reads or writes the URL's path, query, and `history`, mapping the URL to state. Put in the URL what a person would reload or share, such as the selected item. Standalone, add a history entry for each place the person goes, so Back works; when a place becomes another, such as a new item once saved, replace its entry. Embedded in a Book, replace the URL so Back stays the Book's, and keep what a person would reload or share in the Book's URL with [`bkper:app-state`](https://bkper.com/docs/platform/apps/context-menu.md#keeping-state-in-the-book-url). Pass it the window so it can be tested.
|
|
68
68
|
- **Split by concern, not by screen region.** Split a store or component when its parts change for different reasons.
|
|
69
69
|
|
|
70
70
|
## Security
|
package/lib/docs/index.md
CHANGED
|
@@ -8,9 +8,9 @@ For Bkper app implementation, refactoring, or code review, always read `apps/qua
|
|
|
8
8
|
- `cli/app-usage.md` — Using Bkper apps to do work on a Book instead of rebuilding what they do: list a Book's installed apps and the app catalog, read descriptions, readmes, and property schemas, match them to the Book's properties, read an app's OpenAPI spec and call its API as the user, install apps.
|
|
9
9
|
- `cli/app-management.md` — CLI reference for building and deploying Bkper apps: init/git clone/credential helpers, dev/build/deploy workflow, app install/uninstall, secrets management, app logs, bkper.yaml configuration reference (identity, branding, events, menu integration, deployment).
|
|
10
10
|
- `apps/overview.md` — Platform evaluation and capability overview: use when comparing managed Bkper hosting with self-managed infrastructure or clarifying platform responsibilities; use the task-specific app references for implementation.
|
|
11
|
-
- `apps/ai.md` — Bkper AI in apps, scripts, and tools: ask
|
|
12
|
-
- `ai/
|
|
13
|
-
- `api/ai-gateway.md` — Bkper AI Gateway API guide: call Bkper AI language and
|
|
11
|
+
- `apps/ai.md` — Bkper AI in apps, scripts, and tools: ask System One models such as Jev or Clairic, with TypeSafe's SDK for decision questions or `fetch` for any question type, or language models with AI SDK Open Responses, authenticate through app `/api/*` routes or a Bkper token outside the platform, handle errors, and keep Book writes under deterministic application control.
|
|
12
|
+
- `ai/system-one-models.md` — Designing software around System One models: decision questions (Jev, Clef) for yes/no, choice, and score judgments, and extraction questions (Clairic, preview) for values read from documents, with spans, nulls, and estimates. Covers when to use each, the rule that models read and judge while code calculates and decides, a workflow that sorts each condition into code facts and one-judgment questions and combines them in code with thresholds and human review, and worked bank-line and supplier-email examples. The request, answers, errors, and caching are in `api/ai-gateway.md`.
|
|
13
|
+
- `api/ai-gateway.md` — Bkper AI Gateway API guide: call Bkper AI language and System One models from your own client, script, or server — authentication, model IDs, requests, System One request rules and answer guarantees, streaming, errors, caching, and links to each operation's page.
|
|
14
14
|
- `api/managed-agent.md` — Bkper Managed Agent API guide: build apps, chat bots, and scripts on the agent behind Bkper Agent — sessions, instructions, inputs and idempotency, Book context, streams, files, a Slack bot example, limits, errors, and links to each operation's page.
|
|
15
15
|
- `apps/first-app.md` — First-app walkthrough: scaffold, install, run locally, trigger an event, customize the listing, establish shared source, check, and deploy.
|
|
16
16
|
- `apps/architecture.md` — App and template architecture: npm workspace structure, Lit/Vite client, Hono Worker, typed `/api/*` contracts, authentication, `/events`, static assets, and supported app shapes.
|
|
@@ -21,7 +21,7 @@ For Bkper app implementation, refactoring, or code review, always read `apps/qua
|
|
|
21
21
|
- `apps/event-handlers.md` — Event handler behavior: `/events` routing, responses, replay, loop prevention, platform and self-hosted authentication, event payloads, and event types.
|
|
22
22
|
- `apps/deploying.md` — Build, sync, and explicit deploy workflow; production and preview environments, secrets, KV, deployment status, and book installation.
|
|
23
23
|
- `apps/shared-app-source.md` — Bkper-managed private Git source: developer access, first sync, clone workflow, source/deployment separation, safety checks, external remotes, and monorepos.
|
|
24
|
-
- `apps/context-menu.md` — Book context-menu integration: production/development URLs, open modes,
|
|
24
|
+
- `apps/context-menu.md` — Book context-menu integration: production/development URLs, open modes, dynamic Book, query, Account, Group, and App-state expressions, live context updates, keeping App state in the Book URL, and HTML files shown in Bkper Agent (sandbox, size limit, navigation requests).
|
|
25
25
|
- `apps/app-listing.md` — App listing metadata, visibility, publication review, end-user README guidance, and public listing locations.
|
|
26
26
|
- `apps/self-hosted.md` — Self-hosted event-handler alternatives: Cloud Functions, generic webhooks, direct authentication responsibilities, scaling, responses, and retries.
|
|
27
27
|
- `reporting/financial-statements.md` — Deterministic reporting principles and Bkper query semantics for balance sheet and P&L: trusted routes, root reporting groups, permanent vs period date rules, and provisional query patterns.
|
package/package.json
CHANGED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
# Decision Models
|
|
2
|
-
|
|
3
|
-
A decision model judges; your code decides. It reads the facts your code gives it, such as a bank line, and answers narrow questions in a shape you set in advance: how likely something is true, which of your options fits, or where it sits on your scale. It writes no text, and it reports how sure it is as a number your code can compare.
|
|
4
|
-
|
|
5
|
-
Why that suits accounting is covered in [AI Fundamentals](https://bkper.com/docs/ai/fundamentals.md#decision-models). This page is about designing with decision models. [Jev](#jev-by-typesafe), by TypeSafe, is Bkper's first.
|
|
6
|
-
|
|
7
|
-
## When to use one
|
|
8
|
-
|
|
9
|
-
| Your software needs | Use |
|
|
10
|
-
| ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
11
|
-
| A yes or 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/models.md) |
|
|
13
|
-
| A conversation that works on Books, computes, and delivers files | An agent: [Bkper Agent](https://bkper.com/docs/ai/bkper-agent.md), or the [Managed Agent API](https://bkper.com/docs/api/managed-agent.md) in your app |
|
|
14
|
-
|
|
15
|
-
## Where you use them
|
|
16
|
-
|
|
17
|
-
- **In [Bkper CLI Agent](https://bkper.com/docs/ai/bkper-cli-agent.md#what-it-can-do)**, with no setup. Describe the outcome, such as "suggest Accounts for these bank lines and show me only the unsure ones", and the agent asks the decision model for you.
|
|
18
|
-
- **In apps and scripts**, with TypeSafe's SDK. See [Add Bkper AI to an App](https://bkper.com/docs/platform/apps/ai.md#ask-a-decision-model). The open-source [Merge Duplicates app](https://github.com/bkper/bkper-apps/tree/main/merge-duplicates) uses one to suggest duplicate pairs for a person to review.
|
|
19
|
-
|
|
20
|
-
## Three kinds of question
|
|
21
|
-
|
|
22
|
-
Each question gets one typed answer:
|
|
23
|
-
|
|
24
|
-
| Ask | Example | You get |
|
|
25
|
-
| ---------------------------------- | --------------------------------------------- | ---------------------------------------------------- |
|
|
26
|
-
| **Is this true?** (`noul`) | Is this bank line already recorded? | The probability of yes, from 0 to 1 |
|
|
27
|
-
| **Which one of these?** (`choice`) | Which Account should receive this payment? | One of your options, with a confidence from 0 to 1 |
|
|
28
|
-
| **Where on this scale?** (`score`) | How urgently should someone review this line? | A position on your levels, with a confidence |
|
|
29
|
-
|
|
30
|
-
Confidence is high when the model's probability concentrates on one answer. For _Is this true?_, the probability itself is the signal. Ask several questions about the same facts in one request; the model answers each one independently.
|
|
31
|
-
|
|
32
|
-
## Design a decision workflow
|
|
33
|
-
|
|
34
|
-
1. **Find the judgment.**
|
|
35
|
-
|
|
36
|
-
Look for the step where a person glances and decides: which Account, is this a duplicate, does this need a second look. A good question is a snap judgment that a knowledgeable person makes in seconds.
|
|
37
|
-
|
|
38
|
-
2. **Let code gather the facts.**
|
|
39
|
-
|
|
40
|
-
Code fetches the item and the context a person would need, such as nearby Transactions, how an Account is usually described, or Book and Account properties. Pass them as named fields, such as `bank_line` and `existing_transaction`. Facts can also be images, such as a receipt photo. Convert PDFs and other files to text or images first.
|
|
41
|
-
|
|
42
|
-
3. **Ask narrow questions.**
|
|
43
|
-
|
|
44
|
-
Ask one judgment per question. Split bigger judgments into several questions and combine the answers in code. Write each question in full: the model sees your instructions and the facts, never the name your code gives the question.
|
|
45
|
-
|
|
46
|
-
4. **Keep calculation in code.**
|
|
47
|
-
|
|
48
|
-
Match amounts, compute date windows, and check balances in code, then ask the model only the part that needs judgment. For example, find Transactions with the same amount inside a date window, then ask only whether their descriptions describe the same movement.
|
|
49
|
-
|
|
50
|
-
5. **Set thresholds by risk.**
|
|
51
|
-
|
|
52
|
-
Decide how sure the model must be before code acts. A missed suggestion costs a person a few seconds; a duplicate posting misstates a Book. Keep thresholds in one reviewable place.
|
|
53
|
-
|
|
54
|
-
6. **Act when confident; send the rest to a person.**
|
|
55
|
-
|
|
56
|
-
Code acts on answers above the threshold and routes the rest to review. This is TypeSafe's [confidence-gated routing](https://docs.typesafe.ai/patterns/confidence-routing) pattern.
|
|
57
|
-
|
|
58
|
-
7. **Keep Book writes in code.**
|
|
59
|
-
|
|
60
|
-
An answer is a judgment, not permission to change a Book. When code posts, it records a normal Transaction, so the Book stays zero-sum whatever the model answered. Store the model revision and the confidence as Transaction properties for the audit trail.
|
|
61
|
-
|
|
62
|
-
8. **Measure and adjust.**
|
|
63
|
-
|
|
64
|
-
Start with conservative thresholds and test them against your own records. Re-check them when the model's revision changes.
|
|
65
|
-
|
|
66
|
-
## Putting it all together
|
|
67
|
-
|
|
68
|
-
A bank line arrives: `AMAZON MKTPL*2K4LM`, 89.90 out of Checking. Code finds a manual entry from the day before with the same amount, "Printer toner, Amazon order 114-2K4LM", and asks three questions at once. Jev answered:
|
|
69
|
-
|
|
70
|
-
| Question | Answer |
|
|
71
|
-
| --------------------------------------------------------------------------------------------------------- | ------------------------------ |
|
|
72
|
-
| Which Account should receive the money? Cloud Hosting, Software Subscriptions, Office Supplies, or Travel | Office Supplies, confidence 1 |
|
|
73
|
-
| Does the existing entry already record this movement? | Yes, with probability 0.89 |
|
|
74
|
-
| How urgently should a bookkeeper review it? Routine, Check, or Urgent | 0.09, Routine; confidence 0.86 |
|
|
75
|
-
|
|
76
|
-
Code then decides:
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
// Keep questions and thresholds in one reviewable place.
|
|
80
|
-
const DUPLICATE_THRESHOLD = 0.8;
|
|
81
|
-
const REVIEW_SCORE_THRESHOLD = 1.5;
|
|
82
|
-
const AUTO_POST_CONFIDENCE = 0.9;
|
|
83
|
-
|
|
84
|
-
interface BankLineAnswers {
|
|
85
|
-
account: { type: 'choice'; choice: string; confidence: number };
|
|
86
|
-
already_recorded: { type: 'noul'; noul: number };
|
|
87
|
-
review_priority: { type: 'score'; score: number; confidence: number };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
type BankLineDecision =
|
|
91
|
-
| { action: 'check-duplicate' }
|
|
92
|
-
| { action: 'review'; suggestedAccount: string }
|
|
93
|
-
| { action: 'post'; toAccount: string; confidence: number };
|
|
94
|
-
|
|
95
|
-
export function decideBankLine(answers: BankLineAnswers): BankLineDecision {
|
|
96
|
-
if (answers.already_recorded.noul >= DUPLICATE_THRESHOLD) {
|
|
97
|
-
return { action: 'check-duplicate' };
|
|
98
|
-
}
|
|
99
|
-
if (
|
|
100
|
-
answers.review_priority.score >= REVIEW_SCORE_THRESHOLD ||
|
|
101
|
-
answers.account.confidence < AUTO_POST_CONFIDENCE
|
|
102
|
-
) {
|
|
103
|
-
return { action: 'review', suggestedAccount: answers.account.choice };
|
|
104
|
-
}
|
|
105
|
-
return {
|
|
106
|
-
action: 'post',
|
|
107
|
-
toAccount: answers.account.choice,
|
|
108
|
-
confidence: answers.account.confidence,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
These answers return `check-duplicate`: the movement is probably already recorded, so code posts nothing. When code does post, it records a Transaction from Checking to the chosen Account. The risks to control are a wrong Account and a duplicate movement, which is why those checks come first.
|
|
114
|
-
|
|
115
|
-
The exact request and response are in the [AI Gateway API guide](https://bkper.com/docs/api/ai-gateway.md#decision-models).
|
|
116
|
-
|
|
117
|
-
### Context changes confidence
|
|
118
|
-
|
|
119
|
-
Ask about the same bank line without the manual entry, and the answer changes:
|
|
120
|
-
|
|
121
|
-
| Facts given | Which Account? |
|
|
122
|
-
| ----------------------------------- | --------------------------------------------------------------------- |
|
|
123
|
-
| The bank line and the manual entry | Office Supplies, confidence 1 |
|
|
124
|
-
| The bank line alone | Office Supplies, confidence 0.75, with 0.14 on Software Subscriptions |
|
|
125
|
-
|
|
126
|
-
The top option is the same, but the model reports that it is less sure, so `decideBankLine` sends the line to review. Give the model the context a person would need.
|
|
127
|
-
|
|
128
|
-
For more designs, see TypeSafe's [Patterns](https://docs.typesafe.ai/patterns) and [Cookbooks](https://docs.typesafe.ai/cookbooks).
|
|
129
|
-
|
|
130
|
-
## Common mistakes
|
|
131
|
-
|
|
132
|
-
- **Asking for analysis.** Ask one snap judgment per question and combine the answers in code.
|
|
133
|
-
- **Asking the model to calculate.** Match amounts, compute date windows, and check balances in code.
|
|
134
|
-
- **Putting the question in its name.** The model never sees question IDs. Write the full question in its instructions.
|
|
135
|
-
- **Treating answers as verdicts.** A probability of yes is not a boolean, and a score can fall between levels. Compare both with thresholds.
|
|
136
|
-
- **Expecting an explanation.** Decision models return no text. Use a [language model](https://bkper.com/docs/ai/models.md) when you need one.
|
|
137
|
-
- **Sending a language-model request.** A decision request carries only the model, the facts, and the questions. See the [request rules](https://bkper.com/docs/api/ai-gateway.md#decision-request).
|
|
138
|
-
|
|
139
|
-
## Jev by TypeSafe
|
|
140
|
-
|
|
141
|
-
[Jev](https://docs.typesafe.ai/introduction) is TypeSafe's flagship model and the first System One model. Its Bkper model ID is `jev`.
|
|
142
|
-
|
|
143
|
-
- **Versions.** `jev-latest` and versioned IDs are accepted but always select the current Jev; you cannot pin a version. Log the revision each answer reports, and re-check tuned thresholds when it changes.
|
|
144
|
-
- **Input.** Text and images. English is Jev's primary training language; other languages work with lower accuracy.
|
|
145
|
-
- **Images.** An experimental TypeSafe feature, so accuracy and limits can change. Send PNG or JPEG images between 280 and 1568 pixels per side as base64 `assets` in a JSON request; TypeSafe's SDKs upload images in a form Bkper AI does not accept. Image tokens count as input. See TypeSafe's [Images](https://docs.typesafe.ai/images) guide.
|
|
146
|
-
- **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).
|
|
147
|
-
|
|
148
|
-
Requests count against your Bkper AI allowance at Jev's [usage rates](https://bkper.com/docs/ai/models.md#usage-rates).
|
|
149
|
-
|
|
150
|
-
## Build it
|
|
151
|
-
|
|
152
|
-
- [Add Bkper AI to an App](https://bkper.com/docs/platform/apps/ai.md#ask-a-decision-model) — ask a decision model from an app Worker, a script, or a browser with TypeSafe's SDK.
|
|
153
|
-
- [AI Gateway API: decision models](https://bkper.com/docs/api/ai-gateway.md#decision-models) — the request, answer guarantees, errors, caching, and compatibility with TypeSafe.
|
|
154
|
-
- [`createDecision` reference](https://bkper.com/docs/api/ai-gateway/operations/createdecision.md) — every field.
|
|
155
|
-
- [Models and Usage](https://bkper.com/docs/ai/models.md) — usage rates, the allowance, and privacy.
|
|
156
|
-
- Building with a coding agent? Point it to this page for design, and to `https://bkper.com/docs/api/ai-gateway.md` for the endpoint, authentication, and errors. TypeSafe's [agent skill](https://docs.typesafe.ai/agent-skill) adds questions and patterns.
|
|
157
|
-
- TypeSafe: [System One](https://docs.typesafe.ai/concepts/system-one), [How to build with System One](https://docs.typesafe.ai/concepts/how-to-build-with-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).
|
|
158
|
-
- [Back to AI overview](https://bkper.com/docs/ai.md).
|