@tanstack-ai-browser/apfel 0.0.1 → 0.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.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # @tanstack-ai-browser/apfel
2
2
 
3
- A [TanStack AI](https://tanstack.com/ai) adapter for Apple's on-device Foundation Model, served on your Mac by [apfel](https://apfel.franzai.com)'s OpenAI-compatible server. The browser streams straight from localhost: start it with `apfel --serve --cors`.
3
+ A [TanStack AI](https://tanstack.com/ai) adapter for Apple's on-device Foundation Model, served on your Mac by [apfel](https://apfel.franzai.com)'s OpenAI-compatible server. The browser streams straight from apfel.
4
+
5
+ It's a thin pass-through: TanStack's OpenAI-compatible Chat Completions adapter (`@tanstack/ai-openai/compatible`) pointed at apfel. Tool calls go to apfel as `tools` and come back as apfel parses them; structured output goes as `response_format`, which apfel holds the model to with Apple's guided generation. The adapter adds an availability check and renames `modelOptions` for the request.
4
6
 
5
7
  ```sh
6
8
  npm install @tanstack-ai-browser/apfel @tanstack/ai
@@ -8,11 +10,40 @@ npm install @tanstack-ai-browser/apfel @tanstack/ai
8
10
 
9
11
  ```ts
10
12
  import { chat } from "@tanstack/ai"
11
- import { apfel, isApfelAvailable } from "@tanstack-ai-browser/apfel"
13
+ import { apfelText } from "@tanstack-ai-browser/apfel"
14
+
15
+ const adapter = apfelText()
12
16
 
13
- if (await isApfelAvailable()) {
14
- const stream = chat({ adapter: apfel(), messages, threadId })
17
+ if ((await adapter.availability()) === "available") {
18
+ const stream = chat({ adapter, messages, threadId, tools })
15
19
  }
16
20
  ```
17
21
 
18
- **Status:** early (0.0.x); the API may change. See the [repository README](https://github.com/daveycodez/tanstack-ai-browser#readme).
22
+ Start apfel with `apfel --serve --cors`.
23
+
24
+ ## Images
25
+
26
+ Image parts go to apfel as OpenAI `image_url` parts, so `adapter.inputModalities` lists `"image"` for Apple's model. Apple's model reads images natively on macOS 27 and later; on older macOS, apfel passes it only the text and labels it reads from the image.
27
+
28
+ ## Config
29
+
30
+ - `baseURL`: apfel's API, up to `/v1`. It defaults to `http://127.0.0.1:11434/v1`.
31
+ - `defaultHeaders`: headers for every request, such as a bearer token.
32
+
33
+ ## Availability
34
+
35
+ - `adapter.availability()` resolves to `"available"` when apfel lists the model within 10 seconds, and to `"unavailable"` otherwise.
36
+ - `adapter.create({ signal? })` makes the same check. It resolves to the adapter, or rejects. Nothing loads, since apfel runs the model outside the page.
37
+
38
+ ## Model options
39
+
40
+ `modelOptions` are the request fields apfel takes, with OpenAI's names, sent as given (as TanStack's adapters do with their provider's fields): `max_tokens`, `temperature`, `top_p` and `seed`.
41
+
42
+ ## Exports
43
+
44
+ - `@tanstack-ai-browser/apfel`:
45
+ - `apfelText(config?)` for Apple's model, or `apfelText(model, config?)` for another model apfel serves
46
+ - the types `ApfelConfig`, `ApfelModel`, `ApfelTextAdapter`, `ApfelTextModelOptions` and `Availability`
47
+ - the catalog: `APFEL_CHAT_MODELS` and `APFEL_MODEL_META`, with the types `ApfelChatModel` and `ApfelModelMeta`
48
+
49
+ **Status:** early (0.x). The API may change.
package/dist/adapter.d.ts CHANGED
@@ -1,91 +1,45 @@
1
- import type { AdapterYieldChunk, TextOptions } from "@tanstack/ai";
2
- import { BaseTextAdapter } from "@tanstack/ai/adapters";
3
- import type { StructuredOutputOptions, StructuredOutputResult } from "@tanstack/ai/adapters";
4
- /** Where `apfel --serve` listens by default. */
5
- export declare const APFEL_BASE_URL = "http://127.0.0.1:11434/v1";
6
- /** The model id apfel serves Apple's Foundation Model under. */
7
- export declare const APFEL_MODEL = "apple-foundationmodel";
8
- /**
9
- * A model call's token counts and timings. apfel reports token counts only
10
- * in the usage at the end of the stream; counts it doesn't report are left
11
- * out.
12
- */
13
- export type ApfelStats = {
14
- /** Tokens of the prompt. */
15
- inputTokens?: number;
16
- /** Prompt tokens served from a cache, if apfel reports them. */
17
- cachedTokens?: number;
18
- /** Tokens the model generated. */
19
- outputTokens?: number;
20
- /** From sending the request to the first generated token, in ms. */
21
- firstTokenMs?: number;
22
- /** Tokens generated after the first chunk (estimated, see below). */
23
- decodeTokens?: number;
24
- /** From the first generated chunk to the last, in ms. */
25
- decodeMs?: number;
26
- };
27
- export type ApfelOptions = {
28
- /** apfel's OpenAI-compatible API, up to `/v1`. */
29
- baseUrl?: string;
30
- /** The model id to ask apfel for. */
31
- model?: string;
32
- /**
33
- * The call's stats at its first token (`done: false`, time to first token
34
- * only) and when it ends (`done: true`). `callId` is unique per model
35
- * call; `chat()` makes one per step of its agent loop.
36
- */
37
- onStats?: (stats: ApfelStats, run: {
38
- threadId: string;
39
- runId: string;
40
- callId: string;
41
- done: boolean;
42
- }) => void;
1
+ import type { OpenAICompatibleChatAdapter } from "@tanstack/ai-openai/compatible";
2
+ import type { ApfelChatModel } from "./model-meta.js";
3
+ export type ApfelConfig = {
4
+ /** apfel's OpenAI-compatible API, up to `/v1`. `http://127.0.0.1:11434/v1` by default. */
5
+ baseURL?: string;
6
+ /** Headers sent with every request, such as apfel's bearer token. */
7
+ defaultHeaders?: Record<string, string>;
43
8
  };
44
- /**
45
- * Request fields apfel takes for Apple's model. apfel rejects parameters
46
- * the model doesn't support (stop, penalties, n…) with HTTP 400.
47
- */
48
- export type ApfelModelOptions = {
49
- temperature?: number;
9
+ /** Per-call `modelOptions`: the request fields apfel takes, with OpenAI's names, sent as given. */
10
+ export type ApfelTextModelOptions = {
11
+ /** Most tokens to generate. */
50
12
  max_tokens?: number;
13
+ temperature?: number;
14
+ top_p?: number;
51
15
  seed?: number;
52
16
  };
53
- type ApfelReasoning = never;
54
- type MetadataByModality = {
55
- text: unknown;
56
- image: unknown;
57
- audio: unknown;
58
- video: unknown;
59
- document: unknown;
17
+ /** The Prompt API's availability values; apfel's model is "available" or "unavailable". */
18
+ export type Availability = "unavailable" | "downloadable" | "downloading" | "available";
19
+ /** TanStack's OpenAI-compatible adapter for apfel, with apfel's availability. */
20
+ export type ApfelTextAdapter = OpenAICompatibleChatAdapter<ApfelModel, ApfelTextModelOptions> & {
21
+ /** Text and images for Apple's model; not known for another model. */
22
+ readonly inputModalities: ReadonlyArray<"text" | "image"> | undefined;
23
+ /** "available" if apfel answers and serves the model, else "unavailable". */
24
+ availability(signal?: AbortSignal): Promise<Availability>;
25
+ /** Resolves to this adapter if apfel serves the model, else rejects. Nothing loads. */
26
+ create(options?: {
27
+ signal?: AbortSignal;
28
+ }): Promise<ApfelTextAdapter>;
60
29
  };
61
- export declare class ApfelTextAdapter extends BaseTextAdapter<string, ApfelModelOptions, readonly ["text"], MetadataByModality, ReadonlyArray<string>, unknown, never, ApfelReasoning> {
62
- readonly name: "apfel";
63
- readonly api: "apfel";
64
- private readonly baseUrl;
65
- private readonly onStats;
66
- constructor(options?: ApfelOptions);
67
- chatStream(options: TextOptions<ApfelModelOptions>): AsyncIterable<AdapterYieldChunk>;
68
- /**
69
- * A JSON answer for `chat({ outputSchema })`, from apfel's JSON mode:
70
- * `response_format: json_schema` constrains Apple's model to the schema
71
- * (guided generation). `chat()` validates the result.
72
- */
73
- structuredOutput(options: StructuredOutputOptions<ApfelModelOptions>): Promise<StructuredOutputResult<unknown>>;
74
- }
30
+ /** A model apfel serves: Apple's ("apple-foundationmodel", the default), or any other name. */
31
+ export type ApfelModel = ApfelChatModel | (string & {});
75
32
  /**
76
- * A TanStack AI adapter for Apple's on-device Foundation Model through
77
- * apfel (`apfel --serve --cors`).
33
+ * An adapter for a model apfel serves: Apple's on-device model by default.
78
34
  *
79
35
  * @example
80
36
  * ```ts
81
- * chat({ adapter: apfel(), messages, threadId })
37
+ * const adapter = apfelText()
38
+ * if ((await adapter.availability()) === "available") {
39
+ * chat({ adapter, messages, tools })
40
+ * }
82
41
  * ```
83
42
  */
84
- export declare function apfel(options?: ApfelOptions): ApfelTextAdapter;
85
- /**
86
- * Whether apfel is running and serves the model: true if `GET /v1/models`
87
- * lists it within 10 seconds.
88
- */
89
- export declare function isApfelAvailable(options?: Pick<ApfelOptions, "baseUrl" | "model">): Promise<boolean>;
90
- export {};
43
+ export declare function apfelText(config?: ApfelConfig): ApfelTextAdapter;
44
+ export declare function apfelText(model: ApfelModel, config?: ApfelConfig): ApfelTextAdapter;
91
45
  //# sourceMappingURL=adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,iBAAiB,EAEjB,WAAW,EAEZ,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,uBAAuB,CAAA;AAQ9B,gDAAgD;AAChD,eAAO,MAAM,cAAc,8BAA8B,CAAA;AACzD,gEAAgE;AAChE,eAAO,MAAM,WAAW,0BAA0B,CAAA;AAElD;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,CACR,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,KACpE,IAAI,CAAA;CACV,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,cAAc,GAAG,KAAK,CAAA;AAE3B,KAAK,kBAAkB,GAAG;IACxB,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,EAAE,OAAO,CAAA;IACd,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AAmOD,qBAAa,gBAAiB,SAAQ,eAAe,CACnD,MAAM,EACN,iBAAiB,EACjB,SAAS,CAAC,MAAM,CAAC,EACjB,kBAAkB,EAClB,aAAa,CAAC,MAAM,CAAC,EACrB,OAAO,EACP,KAAK,EACL,cAAc,CACf;IACC,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAS;IAChC,SAAkB,GAAG,EAAG,OAAO,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;gBAErC,OAAO,GAAE,YAAiB;IAM/B,UAAU,CACf,OAAO,EAAE,WAAW,CAAC,iBAAiB,CAAC,GACtC,aAAa,CAAC,iBAAiB,CAAC;IAmUnC;;;;OAIG;IACG,gBAAgB,CACpB,OAAO,EAAE,uBAAuB,CAAC,iBAAiB,CAAC,GAClD,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;CAsE5C;AAED;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,oBAE3C;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,OAAO,CAAM,oBActD"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAA;AAGjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD,MAAM,MAAM,WAAW,GAAG;IACxB,0FAA0F;IAC1F,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACxC,CAAA;AAED,mGAAmG;AACnG,MAAM,MAAM,qBAAqB,GAAG;IAClC,+BAA+B;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,2FAA2F;AAC3F,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,cAAc,GAAG,aAAa,GAAG,WAAW,CAAA;AAEvF,iFAAiF;AACjF,MAAM,MAAM,gBAAgB,GAAG,2BAA2B,CAAC,UAAU,EAAE,qBAAqB,CAAC,GAAG;IAC9F,sEAAsE;IACtE,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,SAAS,CAAA;IACrE,6EAA6E;IAC7E,YAAY,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACzD,uFAAuF;IACvF,MAAM,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;CACtE,CAAA;AAID,+FAA+F;AAC/F,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAEvD;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,gBAAgB,CAAA;AACjE,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,gBAAgB,CAAA"}