Dart functions that answer questions about text
One Door class over the C library, through Dart FFI. Each call returns its answer and its run facts.
Install
| Channel | Note |
|---|---|
dart pub add thinkthen_dart | |
thinkthen-dart-VERSION-TARGET.tar.gz | The package source, from each release. |
thinkthen-c-VERSION-TARGET.tar.gz | The C library it calls, from the same release. |
Set THINKTHEN_API_KEY in the environment.
A first call
name: first_call
environment:
sdk: ^3.3.0
dependencies:
thinkthen_dart:
path: thinkthen-dartimport 'dart:io';
import 'package:thinkthen_dart/thinkthen_dart.dart';
void main() {
final library = File('thinkthen-c/lib/libthinkthen.so');
final tt = Door(library.absolute.path);
final engine = tt.create();
try {
const question = 'Does the customer ask for a refund?';
final isRefund = tt.decide(
engine,
question,
'Please refund my order. It arrived broken.',
);
assert(isRefund.value.outcome == Outcome.yes);
const refund = '{"decide": "$question", '
'"threshold": "0.2:0.8"}';
final backIsRefund = tt.decide(
engine,
refund,
'I want to send this back.',
);
final outcome = backIsRefund.value.outcome;
assert(outcome == Outcome.notSure);
} finally {
tt.engineFree(engine);
}
}dart pub get
dart run --enable-asserts \
first_call.dartNot sure comes back as Outcome.notSure. Branch on it and send those cases to a person.
Run facts
decide returns a record. .value holds the answer, and .facts holds this call's run facts as a Map.
Errors
A failed call throws a DoorFailure. Its kind names one of six ErrorKind values. It also carries the message and retryable.
Settings and recording
create(settingsJson) takes the settings as JSON. "record" writes a recording to a folder. "replay" answers from that recording with no connection. The Settings page lists every setting.
Jev, Liquid d1 and Ollama from Dart
Dart reads its backend from the environment. Set THINKTHEN_BACKEND to the name below. Set the backend's key variable in the shell, and the same sample asks that backend.
| Backend | Name | Key variable |
|---|---|---|
| TypeSafe Jev | typesafe | TYPESAFE_API_KEY |
| Liquid d1 | liquid | LIQUIDAI_API_KEY, then LIQUID_API_KEY |
| Ollama | ollama | OLLAMA_API_KEY. A local address needs no key. |
export THINKTHEN_BACKEND=typesafe
export TYPESAFE_API_KEY=...export THINKTHEN_BACKEND=liquid
export LIQUIDAI_API_KEY=...export THINKTHEN_BACKEND=ollama
export THINKTHEN_BASE_URL=http://localhost:11535/v1import 'dart:io';
import 'package:thinkthen_dart/thinkthen_dart.dart';
void main() {
final library = File('thinkthen-c/lib/libthinkthen.so');
final tt = Door(library.absolute.path);
final engine = tt.create();
try {
const question = 'Does the customer ask for a refund?';
final brokenIsRefund = tt.decide(
engine,
question,
'Please refund my order. It arrived broken.',
);
final thanksIsRefund = tt.decide(
engine,
question,
'Thanks for the quick help yesterday!',
);
final broken = brokenIsRefund.value.outcome;
final thanks = thanksIsRefund.value.outcome;
assert(broken == Outcome.yes);
assert(thanks == Outcome.no);
} finally {
tt.engineFree(engine);
}
}dart pub get
dart run --enable-asserts \
backends.dartThe configuration file's backend names a default backend for every run. The Configuration page shows the file.
OpenAI Decisions API from Dart
OpenAI announced its Decisions API on 2026-09-29 in its DevDay 2026 recap. OpenAI has published no address, schema or price, so ThinkThen cannot call it. The OpenAI Decisions API page says what ThinkThen knows.
What is different in Dart
Doortakes the C library's path.createmakes an engine, and each call takes that engine first.engineFreecloses it.assertruns only underdart run --enable-asserts.- A Flutter app on Linux adds
thinkthen_dartand passes the library path toDoor.
On GitHub: github.com/botassembly/thinkthen