@vincemakes/kiso-provider-openai 0.15.12 → 0.16.1

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/dist/index.d.ts CHANGED
@@ -20,6 +20,18 @@ import type { Adapter } from "@vincemakes/kiso-core";
20
20
  export interface OpenAICompatProviderConfig {
21
21
  readonly apiKey?: string;
22
22
  readonly baseUrl?: string;
23
+ /** MG-1 (A5): the adapter's replay identity — providerId as the runtime
24
+ * resolved it (deepseek / zai / openai / custom). Absent = "custom"
25
+ * with the baseUrl origin as the endpoint term. */
26
+ readonly scope?: OpenAICompatScope;
27
+ }
28
+ /** MG-1 (A5): the compat adapter's own half of the continuation scope.
29
+ * apiId is constant ("openai-chat") and modelId is per-request; only the
30
+ * provider identity and (for custom) the endpoint origin need injecting —
31
+ * the generic compat wire cannot know WHICH provider it is. */
32
+ export interface OpenAICompatScope {
33
+ readonly providerId: string;
34
+ readonly endpoint?: string;
23
35
  }
24
36
  /**
25
37
  * High-level factory (round 7): builds the adapter FROM CONFIG, owning the SDK
@@ -29,5 +41,8 @@ export interface OpenAICompatProviderConfig {
29
41
  * through a hoisted root.
30
42
  */
31
43
  export declare function createOpenAICompatProvider(config?: OpenAICompatProviderConfig): Adapter;
32
- export declare function createOpenAICompatAdapter(client: OpenAI): Adapter;
44
+ export interface OpenAICompatAdapterOptions {
45
+ readonly scope?: OpenAICompatScope;
46
+ }
47
+ export declare function createOpenAICompatAdapter(client: OpenAI, adapterOpts?: OpenAICompatAdapterOptions): Adapter;
33
48
  export type { ChatCompletionChunk };
package/dist/index.js CHANGED
@@ -29,9 +29,21 @@ export function createOpenAICompatProvider(config = {}) {
29
29
  ...(config.apiKey !== undefined ? { apiKey: config.apiKey } : {}),
30
30
  ...(config.baseUrl !== undefined ? { baseURL: config.baseUrl } : {}),
31
31
  });
32
- return createOpenAICompatAdapter(client);
32
+ const origin = (() => {
33
+ if (config.baseUrl === undefined)
34
+ return undefined;
35
+ try {
36
+ return new URL(config.baseUrl).origin;
37
+ }
38
+ catch {
39
+ return undefined;
40
+ }
41
+ })();
42
+ const scope = config.scope ?? (origin !== undefined ? { providerId: "custom", endpoint: origin } : undefined);
43
+ return createOpenAICompatAdapter(client, { ...(scope !== undefined ? { scope } : {}) });
33
44
  }
34
- export function createOpenAICompatAdapter(client) {
45
+ export function createOpenAICompatAdapter(client, adapterOpts = {}) {
46
+ const ownScope = adapterOpts.scope;
35
47
  return {
36
48
  async *stream(options) {
37
49
  // The explicit streaming params type keeps the `stream: true`
@@ -39,7 +51,17 @@ export function createOpenAICompatAdapter(client) {
39
51
  // create() call as the NON-streaming variant (TS2504).
40
52
  const body = {
41
53
  model: options.model,
42
- messages: toOpenAIMessages(options.messages, options.systemPrompt),
54
+ messages: toOpenAIMessages(options.messages, options.systemPrompt, options.model, ownScope),
55
+ // XP-1: the resolved setting, DeepSeek V4 shape (the
56
+ // thinking-mode guide, read 2026-08-26): top-level
57
+ // thinking:{type} + reasoning_effort. Absent adds NO key.
58
+ // The `thinking` extension is absent from the SDK's param
59
+ // type; the spread rides a cast — the reasoning_content
60
+ // precedent, one object over.
61
+ ...({
62
+ ...(options.reasoning?.thinking !== undefined ? { thinking: { type: options.reasoning.thinking } } : {}),
63
+ ...(options.reasoning?.effort !== undefined ? { reasoning_effort: options.reasoning.effort } : {}),
64
+ }),
43
65
  stream: true,
44
66
  // D5: request real streaming usage — without this the
45
67
  // provider never sends a usage chunk and we would
@@ -317,7 +339,24 @@ function toOpenAIToolResultContent(content) {
317
339
  : `[image omitted — OpenAI tool results accept text only: ${b.sourceType === "base64" ? `${b.mediaType ?? "image"} (${b.data?.length ?? 0} base64 chars)` : `url ${b.url ?? ""}`}]`)
318
340
  .join("");
319
341
  }
320
- function toOpenAIMessages(messages, systemPrompt) {
342
+ /** A5: the reasoning text replays ONLY when the turn's envelope matches
343
+ * THIS binding — provider AND api AND model AND (for custom) the endpoint
344
+ * origin. Foreign content is withheld as "" so the monotone PRESENCE
345
+ * discipline (below) holds byte-stably. A turn with NO envelope is the
346
+ * grandfather: pre-A5 logs replay under the pre-existing rule verbatim. */
347
+ function reasoningFor(msg, model, ownScope) {
348
+ const c = msg.continuation;
349
+ if (c === undefined)
350
+ return msg.reasoning ?? "";
351
+ const s = c.scope;
352
+ const providerId = ownScope?.providerId ?? "custom";
353
+ const matches = s.apiId === "openai-chat" &&
354
+ s.providerId === providerId &&
355
+ s.modelId === model &&
356
+ (s.providerId !== "custom" || s.endpoint === ownScope?.endpoint);
357
+ return matches ? (msg.reasoning ?? "") : "";
358
+ }
359
+ function toOpenAIMessages(messages, systemPrompt, model = "", ownScope) {
321
360
  const out = [];
322
361
  // The OpenAI API takes the system prompt as a system-role message; compat
323
362
  // providers (GLM/Kimi/DeepSeek/OpenRouter) follow the same shape. It was
@@ -366,7 +405,7 @@ function toOpenAIMessages(messages, systemPrompt) {
366
405
  // added via spread so the literal stays assignable (the union
367
406
  // type carries the extra key). Presence follows hasReasoning
368
407
  // (the monotone rule above — the field never flips mid-history).
369
- ...(hasReasoning ? { reasoning_content: msg.reasoning ?? "" } : {}),
408
+ ...(hasReasoning ? { reasoning_content: reasoningFor(msg, model, ownScope) } : {}),
370
409
  });
371
410
  }
372
411
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-provider-openai",
3
- "version": "0.15.12",
3
+ "version": "0.16.1",
4
4
  "description": "kiso OpenAI-compatible adapter \u2014 OpenAI + the compat family (GLM, Kimi, DeepSeek, OpenRouter) via base_url swap, reasoning dialects digested.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -21,7 +21,7 @@
21
21
  "test": "vitest run"
22
22
  },
23
23
  "dependencies": {
24
- "@vincemakes/kiso-core": "0.15.12",
24
+ "@vincemakes/kiso-core": "0.16.1",
25
25
  "openai": "^7.3.0"
26
26
  },
27
27
  "devDependencies": {