@prismshadow/mmsp 0.5.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 (116) hide show
  1. package/README.md +121 -0
  2. package/dist/ant_messages/client.d.ts +59 -0
  3. package/dist/ant_messages/client.d.ts.map +1 -0
  4. package/dist/ant_messages/client.js +419 -0
  5. package/dist/ant_messages/index.d.ts +2 -0
  6. package/dist/ant_messages/index.d.ts.map +1 -0
  7. package/dist/ant_messages/index.js +18 -0
  8. package/dist/anthropic_official/client.d.ts +63 -0
  9. package/dist/anthropic_official/client.d.ts.map +1 -0
  10. package/dist/anthropic_official/client.js +540 -0
  11. package/dist/anthropic_official/index.d.ts +2 -0
  12. package/dist/anthropic_official/index.d.ts.map +1 -0
  13. package/dist/anthropic_official/index.js +18 -0
  14. package/dist/autoClient.d.ts +96 -0
  15. package/dist/autoClient.d.ts.map +1 -0
  16. package/dist/autoClient.js +258 -0
  17. package/dist/baseClient.d.ts +111 -0
  18. package/dist/baseClient.d.ts.map +1 -0
  19. package/dist/baseClient.js +284 -0
  20. package/dist/deepseek_official/client.d.ts +60 -0
  21. package/dist/deepseek_official/client.d.ts.map +1 -0
  22. package/dist/deepseek_official/client.js +407 -0
  23. package/dist/deepseek_official/index.d.ts +2 -0
  24. package/dist/deepseek_official/index.d.ts.map +1 -0
  25. package/dist/deepseek_official/index.js +18 -0
  26. package/dist/errors.d.ts +84 -0
  27. package/dist/errors.d.ts.map +1 -0
  28. package/dist/errors.js +140 -0
  29. package/dist/gemini_generate_content/client.d.ts +86 -0
  30. package/dist/gemini_generate_content/client.d.ts.map +1 -0
  31. package/dist/gemini_generate_content/client.js +809 -0
  32. package/dist/gemini_generate_content/index.d.ts +2 -0
  33. package/dist/gemini_generate_content/index.d.ts.map +1 -0
  34. package/dist/gemini_generate_content/index.js +18 -0
  35. package/dist/gemini_official/client.d.ts +87 -0
  36. package/dist/gemini_official/client.d.ts.map +1 -0
  37. package/dist/gemini_official/client.js +780 -0
  38. package/dist/gemini_official/index.d.ts +2 -0
  39. package/dist/gemini_official/index.d.ts.map +1 -0
  40. package/dist/gemini_official/index.js +18 -0
  41. package/dist/index.d.ts +6 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +44 -0
  44. package/dist/integration/index.d.ts +1 -0
  45. package/dist/integration/index.d.ts.map +1 -0
  46. package/dist/integration/index.js +14 -0
  47. package/dist/integration/playground.d.ts +17 -0
  48. package/dist/integration/playground.d.ts.map +1 -0
  49. package/dist/integration/playground.js +3246 -0
  50. package/dist/integration/tracer.d.ts +188 -0
  51. package/dist/integration/tracer.d.ts.map +1 -0
  52. package/dist/integration/tracer.js +1928 -0
  53. package/dist/legacy.d.ts +13 -0
  54. package/dist/legacy.d.ts.map +1 -0
  55. package/dist/legacy.js +59 -0
  56. package/dist/minimax_official/client.d.ts +43 -0
  57. package/dist/minimax_official/client.d.ts.map +1 -0
  58. package/dist/minimax_official/client.js +346 -0
  59. package/dist/minimax_official/index.d.ts +2 -0
  60. package/dist/minimax_official/index.d.ts.map +1 -0
  61. package/dist/minimax_official/index.js +18 -0
  62. package/dist/moonshot_official/client.d.ts +73 -0
  63. package/dist/moonshot_official/client.d.ts.map +1 -0
  64. package/dist/moonshot_official/client.js +477 -0
  65. package/dist/moonshot_official/index.d.ts +2 -0
  66. package/dist/moonshot_official/index.d.ts.map +1 -0
  67. package/dist/moonshot_official/index.js +18 -0
  68. package/dist/openai_chat/client.d.ts +67 -0
  69. package/dist/openai_chat/client.d.ts.map +1 -0
  70. package/dist/openai_chat/client.js +419 -0
  71. package/dist/openai_chat/index.d.ts +2 -0
  72. package/dist/openai_chat/index.d.ts.map +1 -0
  73. package/dist/openai_chat/index.js +18 -0
  74. package/dist/openai_chat_vllm_adapter/client.d.ts +15 -0
  75. package/dist/openai_chat_vllm_adapter/client.d.ts.map +1 -0
  76. package/dist/openai_chat_vllm_adapter/client.js +118 -0
  77. package/dist/openai_chat_vllm_adapter/index.d.ts +2 -0
  78. package/dist/openai_chat_vllm_adapter/index.d.ts.map +1 -0
  79. package/dist/openai_chat_vllm_adapter/index.js +5 -0
  80. package/dist/openai_embedding/client.d.ts +46 -0
  81. package/dist/openai_embedding/client.d.ts.map +1 -0
  82. package/dist/openai_embedding/client.js +124 -0
  83. package/dist/openai_embedding/index.d.ts +2 -0
  84. package/dist/openai_embedding/index.d.ts.map +1 -0
  85. package/dist/openai_embedding/index.js +18 -0
  86. package/dist/openai_official/client.d.ts +61 -0
  87. package/dist/openai_official/client.d.ts.map +1 -0
  88. package/dist/openai_official/client.js +464 -0
  89. package/dist/openai_official/index.d.ts +2 -0
  90. package/dist/openai_official/index.d.ts.map +1 -0
  91. package/dist/openai_official/index.js +18 -0
  92. package/dist/openai_responses/client.d.ts +61 -0
  93. package/dist/openai_responses/client.d.ts.map +1 -0
  94. package/dist/openai_responses/client.js +449 -0
  95. package/dist/openai_responses/index.d.ts +2 -0
  96. package/dist/openai_responses/index.d.ts.map +1 -0
  97. package/dist/openai_responses/index.js +18 -0
  98. package/dist/registry.d.ts +49 -0
  99. package/dist/registry.d.ts.map +1 -0
  100. package/dist/registry.js +798 -0
  101. package/dist/streamItems.d.ts +36 -0
  102. package/dist/streamItems.d.ts.map +1 -0
  103. package/dist/streamItems.js +183 -0
  104. package/dist/types.d.ts +190 -0
  105. package/dist/types.d.ts.map +1 -0
  106. package/dist/types.js +37 -0
  107. package/dist/utils.d.ts +99 -0
  108. package/dist/utils.d.ts.map +1 -0
  109. package/dist/utils.js +312 -0
  110. package/dist/zai_official/client.d.ts +78 -0
  111. package/dist/zai_official/client.d.ts.map +1 -0
  112. package/dist/zai_official/client.js +420 -0
  113. package/dist/zai_official/index.d.ts +2 -0
  114. package/dist/zai_official/index.d.ts.map +1 -0
  115. package/dist/zai_official/index.js +18 -0
  116. package/package.json +68 -0
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ // Copyright 2025 Prism Shadow. and/or its affiliates
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ var __importDefault = (this && this.__importDefault) || function (mod) {
16
+ return (mod && mod.__esModule) ? mod : { "default": mod };
17
+ };
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.OpenaiEmbeddingClient = void 0;
20
+ const openai_1 = __importDefault(require("openai"));
21
+ const baseClient_1 = require("../baseClient");
22
+ const errors_1 = require("../errors");
23
+ const utils_1 = require("../utils");
24
+ /**
25
+ * OpenAI Embeddings-compatible client implementation.
26
+ */
27
+ class OpenaiEmbeddingClient extends baseClient_1.LLMClient {
28
+ /**
29
+ * Initialize OpenAI-compatible embedding client with model, API key, and base URL.
30
+ */
31
+ constructor(options) {
32
+ super();
33
+ this._model = options.model;
34
+ const { apiKey: key, baseUrl: url } = (0, utils_1.resolveCredentials)(this.constructor.name, options, { key: "OPENAI_API_KEY", baseUrl: "OPENAI_BASE_URL" });
35
+ this._client = new openai_1.default({
36
+ apiKey: key,
37
+ baseURL: url,
38
+ defaultHeaders: options.defaultHeaders,
39
+ });
40
+ }
41
+ /**
42
+ * Transform universal configuration to OpenAI Embeddings configuration.
43
+ */
44
+ transformUniConfigToModelConfig(config) {
45
+ if (config.fast_mode) {
46
+ throw new errors_1.UnsupportedParameterError({
47
+ client: this.constructor.name,
48
+ parameter: "fast_mode",
49
+ message: "OpenAI embeddings do not support fast mode.",
50
+ });
51
+ }
52
+ const params = {
53
+ model: this._model,
54
+ };
55
+ const dimensions = config.embedding_config?.dimensions;
56
+ if (dimensions !== undefined) {
57
+ params.dimensions = dimensions;
58
+ }
59
+ return params;
60
+ }
61
+ /**
62
+ * Transform universal messages to OpenAI Embeddings input strings.
63
+ */
64
+ transformUniMessageToModelInput(messages) {
65
+ const texts = [];
66
+ for (const msg of messages) {
67
+ let msgText = "";
68
+ for (const item of msg.content_items) {
69
+ if (item.type !== "text.done") {
70
+ throw new Error("OpenAI embeddings only support text content items.");
71
+ }
72
+ msgText += item.text;
73
+ }
74
+ texts.push(msgText || " ");
75
+ }
76
+ return texts;
77
+ }
78
+ /**
79
+ * Transform an OpenAI Embeddings response into a universal event, one complete item per vector.
80
+ */
81
+ transformModelOutputToUniEvent(modelOutput) {
82
+ return {
83
+ role: "assistant",
84
+ event_type: "stop",
85
+ content_items: modelOutput.data.map((item) => ({
86
+ type: "embedding.delta",
87
+ embedding: item.embedding,
88
+ })),
89
+ usage_metadata: {
90
+ cached_tokens: null,
91
+ prompt_tokens: modelOutput.usage?.prompt_tokens ?? null,
92
+ thoughts_tokens: null,
93
+ response_tokens: null,
94
+ },
95
+ finish_reason: "stop",
96
+ };
97
+ }
98
+ /**
99
+ * Generate embeddings using OpenAI Embeddings-compatible API.
100
+ */
101
+ async *_streamingResponseInternal(options) {
102
+ const params = {
103
+ ...this.transformUniConfigToModelConfig(options.config),
104
+ input: this.transformUniMessageToModelInput(options.messages),
105
+ };
106
+ const result = await this._client.embeddings.create(params, {
107
+ signal: options.signal,
108
+ });
109
+ yield this.transformModelOutputToUniEvent(result);
110
+ }
111
+ /**
112
+ * List the model ids the configured endpoint serves.
113
+ *
114
+ * @returns The model ids, in the order the endpoint returned them.
115
+ */
116
+ async listModels() {
117
+ const models = [];
118
+ for await (const model of this._client.models.list()) {
119
+ models.push(model.id);
120
+ }
121
+ return models;
122
+ }
123
+ }
124
+ exports.OpenaiEmbeddingClient = OpenaiEmbeddingClient;
@@ -0,0 +1,2 @@
1
+ export { OpenaiEmbeddingClient } from "./client";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/openai_embedding/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ // Copyright 2025 Prism Shadow. and/or its affiliates
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.OpenaiEmbeddingClient = void 0;
17
+ var client_1 = require("./client");
18
+ Object.defineProperty(exports, "OpenaiEmbeddingClient", { enumerable: true, get: function () { return client_1.OpenaiEmbeddingClient; } });
@@ -0,0 +1,61 @@
1
+ import type { ResponseInputItem, ResponseStreamEvent } from "openai/resources/responses/responses";
2
+ import { LLMClient } from "../baseClient";
3
+ import { UniConfig, UniEvent, UniMessage } from "../types";
4
+ /**
5
+ * GPT-6-specific LLM client implementation (also serves GPT-5.6, GPT-5.5 and GPT-5.4).
6
+ */
7
+ export declare class OpenAIOfficialClient extends LLMClient {
8
+ protected _model: string;
9
+ private _client;
10
+ /**
11
+ * Initialize GPT-6 client with model and API key.
12
+ */
13
+ constructor(options: {
14
+ model: string;
15
+ apiKey?: string;
16
+ baseUrl?: string | null;
17
+ defaultHeaders?: Record<string, string>;
18
+ });
19
+ /**
20
+ * Convert ThinkingLevel enum to OpenAI's reasoning effort.
21
+ */
22
+ private _convertThinkingLevelToEffort;
23
+ /**
24
+ * Convert ToolChoice to OpenAI's tool_choice format with allowed tools support.
25
+ */
26
+ private _convertToolChoice;
27
+ /**
28
+ * Convert an image URL to an input_image item, at the detail the API needs
29
+ * to read it.
30
+ */
31
+ private _convertImageUrl;
32
+ /**
33
+ * Transform universal configuration to OpenAI Responses API configuration.
34
+ */
35
+ transformUniConfigToModelConfig(config: UniConfig): any;
36
+ /**
37
+ * Transform universal message format to OpenAI Responses API input format.
38
+ */
39
+ transformUniMessageToModelInput(messages: UniMessage[], _signal?: AbortSignal): ResponseInputItem[];
40
+ /**
41
+ * Transform one OpenAI Responses API stream event into a universal event, identifying items by
42
+ * output item id. An item needs no done: it is done when the next one begins or the stream
43
+ * ends.
44
+ */
45
+ transformModelOutputToUniEvent(modelOutput: ResponseStreamEvent): UniEvent;
46
+ /**
47
+ * Stream generate using OpenAI Responses API with unified conversion methods.
48
+ */
49
+ _streamingResponseInternal(options: {
50
+ messages: UniMessage[];
51
+ config: UniConfig;
52
+ signal?: AbortSignal;
53
+ }): AsyncGenerator<UniEvent>;
54
+ /**
55
+ * List the model ids the configured endpoint serves.
56
+ *
57
+ * @returns The model ids, in the order the endpoint returned them.
58
+ */
59
+ listModels(): Promise<string[]>;
60
+ }
61
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/openai_official/client.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,iBAAiB,EACjB,mBAAmB,EAEpB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAOL,SAAS,EACT,QAAQ,EACR,UAAU,EAGX,MAAM,UAAU,CAAC;AAOlB;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;IACjD,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,OAAO,CAAS;IAExB;;OAEG;gBACS,OAAO,EAAE;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACzC;IAeD;;OAEG;IACH,OAAO,CAAC,6BAA6B;IAoBrC;;OAEG;IAEH,OAAO,CAAC,kBAAkB;IAW1B;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;IAEH,+BAA+B,CAAC,MAAM,EAAE,SAAS,GAAG,GAAG;IAmEvD;;OAEG;IACH,+BAA+B,CAC7B,QAAQ,EAAE,UAAU,EAAE,EACtB,OAAO,CAAC,EAAE,WAAW,GACpB,iBAAiB,EAAE;IAkJtB;;;;OAIG;IACH,8BAA8B,CAAC,WAAW,EAAE,mBAAmB,GAAG,QAAQ;IAmJ1E;;OAEG;IACI,0BAA0B,CAAC,OAAO,EAAE;QACzC,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,MAAM,EAAE,SAAS,CAAC;QAClB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GAAG,cAAc,CAAC,QAAQ,CAAC;IAqB5B;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAQtC"}
@@ -0,0 +1,464 @@
1
+ "use strict";
2
+ // Copyright 2025 Prism Shadow. and/or its affiliates
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ var __importDefault = (this && this.__importDefault) || function (mod) {
16
+ return (mod && mod.__esModule) ? mod : { "default": mod };
17
+ };
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.OpenAIOfficialClient = void 0;
20
+ const openai_1 = __importDefault(require("openai"));
21
+ const baseClient_1 = require("../baseClient");
22
+ const errors_1 = require("../errors");
23
+ const types_1 = require("../types");
24
+ const utils_1 = require("../utils");
25
+ /**
26
+ * GPT-6-specific LLM client implementation (also serves GPT-5.6, GPT-5.5 and GPT-5.4).
27
+ */
28
+ class OpenAIOfficialClient extends baseClient_1.LLMClient {
29
+ /**
30
+ * Initialize GPT-6 client with model and API key.
31
+ */
32
+ constructor(options) {
33
+ super();
34
+ this._model = options.model;
35
+ const { apiKey: key, baseUrl: url } = (0, utils_1.resolveCredentials)(this.constructor.name, options, { key: "OPENAI_API_KEY", baseUrl: "OPENAI_BASE_URL" });
36
+ this._client = new openai_1.default({
37
+ apiKey: key,
38
+ baseURL: url,
39
+ defaultHeaders: options.defaultHeaders,
40
+ });
41
+ }
42
+ /**
43
+ * Convert ThinkingLevel enum to OpenAI's reasoning effort.
44
+ */
45
+ _convertThinkingLevelToEffort(thinkingLevel) {
46
+ if (thinkingLevel === types_1.ThinkingLevel.NONE && this._model.includes("gpt-6")) {
47
+ // GPT-6 rejects both "none" and "minimal" with a 400 (verified live 2026-09-09:
48
+ // "Unsupported value: 'none' is not supported with the 'gpt-6-astra' model.
49
+ // Supported values are: 'low', 'medium', 'high', 'xhigh', and 'max'."), so NONE
50
+ // degrades to the lowest effort the generation accepts.
51
+ return "low";
52
+ }
53
+ const mapping = {
54
+ [types_1.ThinkingLevel.NONE]: "none",
55
+ [types_1.ThinkingLevel.LOW]: "low",
56
+ [types_1.ThinkingLevel.MEDIUM]: "medium",
57
+ [types_1.ThinkingLevel.HIGH]: "high",
58
+ [types_1.ThinkingLevel.XHIGH]: "xhigh",
59
+ [types_1.ThinkingLevel.MAX]: "max",
60
+ };
61
+ return mapping[thinkingLevel];
62
+ }
63
+ /**
64
+ * Convert ToolChoice to OpenAI's tool_choice format with allowed tools support.
65
+ */
66
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
67
+ _convertToolChoice(toolChoice) {
68
+ if (Array.isArray(toolChoice)) {
69
+ return {
70
+ mode: "required",
71
+ tools: toolChoice.map((name) => ({ type: "function", name })),
72
+ };
73
+ }
74
+ return toolChoice;
75
+ }
76
+ /**
77
+ * Convert an image URL to an input_image item, at the detail the API needs
78
+ * to read it.
79
+ */
80
+ _convertImageUrl(imageUrl) {
81
+ const detail = (0, utils_1.openaiImageDetail)(this._model, imageUrl);
82
+ return detail
83
+ ? { type: "input_image", image_url: imageUrl, detail }
84
+ : { type: "input_image", image_url: imageUrl };
85
+ }
86
+ /**
87
+ * Transform universal configuration to OpenAI Responses API configuration.
88
+ */
89
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
90
+ transformUniConfigToModelConfig(config) {
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ const openaiConfig = {
93
+ model: this._model,
94
+ store: false,
95
+ include: ["reasoning.encrypted_content"],
96
+ };
97
+ if (config.system_prompt !== undefined) {
98
+ openaiConfig.instructions = config.system_prompt;
99
+ }
100
+ if (config.max_tokens !== undefined) {
101
+ openaiConfig.max_output_tokens = config.max_tokens;
102
+ }
103
+ if (config.temperature !== undefined && config.temperature !== 1.0) {
104
+ throw new errors_1.UnsupportedParameterError({
105
+ client: this.constructor.name,
106
+ parameter: "temperature",
107
+ message: "GPT-6 does not support setting temperature.",
108
+ });
109
+ }
110
+ if (config.thinking_level !== undefined) {
111
+ openaiConfig.reasoning = {
112
+ effort: this._convertThinkingLevelToEffort(config.thinking_level),
113
+ };
114
+ }
115
+ if (config.thinking_summary) {
116
+ // reasoning.summary stands on its own, with or without an effort (verified live
117
+ // 2026-09-03 on the OpenAI and OpenRouter endpoints). False needs no key: the
118
+ // Responses API returns no summary unless one is asked for.
119
+ openaiConfig.reasoning = openaiConfig.reasoning ?? {};
120
+ openaiConfig.reasoning.summary = "concise";
121
+ }
122
+ if (config.tools !== undefined) {
123
+ openaiConfig.tools = config.tools.map((tool) => ({
124
+ type: "function",
125
+ ...tool,
126
+ }));
127
+ }
128
+ if (config.tool_choice !== undefined) {
129
+ openaiConfig.tool_choice = this._convertToolChoice(config.tool_choice);
130
+ }
131
+ if (config.fast_mode) {
132
+ openaiConfig.service_tier = "priority";
133
+ }
134
+ if (config.prompt_caching !== undefined &&
135
+ config.prompt_caching !== types_1.PromptCaching.ENABLE) {
136
+ throw new errors_1.UnsupportedParameterError({
137
+ client: this.constructor.name,
138
+ parameter: "prompt_caching",
139
+ message: "prompt_caching must be ENABLE for GPT-6.",
140
+ });
141
+ }
142
+ return openaiConfig;
143
+ }
144
+ /**
145
+ * Transform universal message format to OpenAI Responses API input format.
146
+ */
147
+ transformUniMessageToModelInput(messages, _signal) {
148
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
149
+ const inputList = [];
150
+ for (const msg of messages) {
151
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
152
+ let contentItems = [];
153
+ let lastPhase = null;
154
+ for (const item of msg.content_items) {
155
+ // anything that is not message content becomes an input item of its own, so the
156
+ // text collected so far is flushed first to keep the order the model produced
157
+ if (item.type !== "text.done" &&
158
+ item.type !== "image_url.done" &&
159
+ contentItems.length > 0) {
160
+ // Every turn goes back as a typed message item — the Responses API's EasyInputMessage
161
+ // shape, where type "message" is valid for any role. A vLLM-style Responses server
162
+ // answers a bare { role: "assistant", content: [...] } item with a 400 on the turn that
163
+ // replays it and takes the typed form for every role; OpenAI, DeepSeek and MiniMax accept
164
+ // either shape. Nothing beyond that minimal shape goes out: an id or a status the server
165
+ // never sent would be an invention.
166
+ const entry = {
167
+ type: "message",
168
+ role: msg.role,
169
+ content: contentItems,
170
+ };
171
+ if (lastPhase !== null) {
172
+ entry.phase = lastPhase;
173
+ }
174
+ inputList.push(entry);
175
+ contentItems = [];
176
+ }
177
+ if (item.type === "text.done") {
178
+ const phase = item.fidelity?.phase;
179
+ if (msg.role === "assistant" && phase) {
180
+ // split different phases
181
+ if (lastPhase !== null &&
182
+ lastPhase !== phase &&
183
+ contentItems.length > 0) {
184
+ inputList.push({
185
+ type: "message",
186
+ role: msg.role,
187
+ content: contentItems,
188
+ phase: lastPhase,
189
+ });
190
+ contentItems = [];
191
+ }
192
+ lastPhase = phase;
193
+ }
194
+ if (msg.role === "user") {
195
+ contentItems.push({ type: "input_text", text: item.text });
196
+ }
197
+ else {
198
+ contentItems.push({ type: "output_text", text: item.text });
199
+ }
200
+ }
201
+ else if (item.type === "image_url.done") {
202
+ contentItems.push(this._convertImageUrl(item.image_url));
203
+ }
204
+ else if (item.type === "thinking.done") {
205
+ // rebuild the reasoning item from the recorded wire fields: the thinking
206
+ // text goes back through the channel that carried it (histories recorded
207
+ // by the pre-channel client carry encrypted_content and stream summaries)
208
+ const fidelity = item.fidelity ?? {};
209
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
210
+ const reasoning = { type: "reasoning", summary: [] };
211
+ const summaryChannel = fidelity.channel === "summary" ||
212
+ (!("channel" in fidelity) && fidelity.encrypted_content != null);
213
+ if (summaryChannel) {
214
+ if (item.thinking) {
215
+ reasoning.summary = [
216
+ { type: "summary_text", text: item.thinking },
217
+ ];
218
+ }
219
+ }
220
+ else if (item.thinking) {
221
+ reasoning.content = [
222
+ { type: "reasoning_text", text: item.thinking },
223
+ ];
224
+ }
225
+ for (const key of ["encrypted_content", "signature", "format"]) {
226
+ if (fidelity[key] != null) {
227
+ reasoning[key] = fidelity[key];
228
+ }
229
+ }
230
+ inputList.push(reasoning);
231
+ }
232
+ else if (item.type === "tool_call.done") {
233
+ inputList.push({
234
+ type: "function_call",
235
+ call_id: item.tool_call_id,
236
+ name: item.name,
237
+ arguments: JSON.stringify(item.arguments),
238
+ });
239
+ }
240
+ else if (item.type === "tool_result.done") {
241
+ if (!item.tool_call_id) {
242
+ throw new Error("tool_call_id is required for tool result.");
243
+ }
244
+ // Tool results are input items
245
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
246
+ const imageParts = [];
247
+ if (item.images) {
248
+ for (const imageUrl of item.images) {
249
+ imageParts.push(this._convertImageUrl(imageUrl));
250
+ }
251
+ }
252
+ // a plain string is the form the Responses API documents for a text
253
+ // result and the one every endpoint fronting this model accepts; the
254
+ // content-part list is reserved for results carrying images
255
+ const output = imageParts.length > 0
256
+ ? [{ type: "input_text", text: item.text }, ...imageParts]
257
+ : item.text;
258
+ inputList.push({
259
+ type: "function_call_output",
260
+ call_id: item.tool_call_id,
261
+ output,
262
+ });
263
+ }
264
+ else {
265
+ throw new Error(`Unknown item: ${JSON.stringify(item)}`);
266
+ }
267
+ }
268
+ if (contentItems.length > 0) {
269
+ const entry = {
270
+ type: "message",
271
+ role: msg.role,
272
+ content: contentItems,
273
+ };
274
+ if (lastPhase !== null) {
275
+ entry.phase = lastPhase;
276
+ }
277
+ inputList.push(entry);
278
+ }
279
+ }
280
+ return inputList;
281
+ }
282
+ /**
283
+ * Transform one OpenAI Responses API stream event into a universal event, identifying items by
284
+ * output item id. An item needs no done: it is done when the next one begins or the stream
285
+ * ends.
286
+ */
287
+ transformModelOutputToUniEvent(modelOutput) {
288
+ let eventType = "delta";
289
+ const contentItems = [];
290
+ let usageMetadata = null;
291
+ let finishReason = null;
292
+ const openaiEventType = modelOutput.type;
293
+ if (openaiEventType === "response.output_text.delta") {
294
+ contentItems.push({
295
+ type: "text.delta",
296
+ text: modelOutput.delta,
297
+ fidelity: { item_id: modelOutput.item_id },
298
+ });
299
+ }
300
+ else if (openaiEventType === "response.reasoning_summary_text.delta" ||
301
+ openaiEventType === "response.reasoning_text.delta") {
302
+ contentItems.push({
303
+ type: "thinking.delta",
304
+ thinking: modelOutput.delta,
305
+ fidelity: { item_id: modelOutput.item_id },
306
+ });
307
+ }
308
+ else if (openaiEventType === "response.output_item.added") {
309
+ // an item begins: a delta under its id, empty unless it carries the call's name or the
310
+ // message's phase, ends the item before it
311
+ const item = modelOutput.item;
312
+ if (item.type === "function_call") {
313
+ contentItems.push({
314
+ type: "tool_call.delta",
315
+ name: item.name,
316
+ arguments: "",
317
+ tool_call_id: item.call_id,
318
+ // a server that sends no item id still sends the call id
319
+ fidelity: { item_id: item.id || item.call_id },
320
+ });
321
+ }
322
+ else if (item.type === "message") {
323
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
324
+ const phase = item.phase;
325
+ contentItems.push({
326
+ type: "text.delta",
327
+ text: "",
328
+ fidelity: { item_id: item.id, ...(phase != null ? { phase } : {}) },
329
+ });
330
+ }
331
+ else if (item.type === "reasoning") {
332
+ contentItems.push({
333
+ type: "thinking.delta",
334
+ thinking: "",
335
+ fidelity: { item_id: item.id },
336
+ });
337
+ }
338
+ }
339
+ else if (openaiEventType === "response.output_item.done") {
340
+ const item = modelOutput.item;
341
+ if (item.type === "reasoning") {
342
+ // the completed item carries the canonical wire fields to send back on the
343
+ // next turn (identical to the response.completed copy, but adjacent to the
344
+ // thinking deltas so the fidelity lands on the item that carried the text);
345
+ // record the channel plus the fields the server demands back. This event is the
346
+ // only source of encrypted_content, because the streaming-events reference says
347
+ // of response.output_item.added: "For reasoning items, encrypted_content may be
348
+ // incomplete while the item is in progress. Use the reasoning item from the
349
+ // corresponding response.output_item.done event when passing it as input to a
350
+ // subsequent request."
351
+ const fidelity = { item_id: item.id };
352
+ if (item.summary && item.summary.length > 0) {
353
+ fidelity.channel = "summary";
354
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
355
+ }
356
+ else if (item.content?.length > 0) {
357
+ fidelity.channel = "content";
358
+ }
359
+ for (const key of ["encrypted_content", "signature", "format"]) {
360
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
361
+ if (item[key] != null) {
362
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
363
+ fidelity[key] = item[key];
364
+ }
365
+ }
366
+ contentItems.push({ type: "thinking.delta", thinking: "", fidelity });
367
+ }
368
+ }
369
+ else if (openaiEventType === "response.function_call_arguments.delta") {
370
+ contentItems.push({
371
+ type: "tool_call.delta",
372
+ name: "",
373
+ arguments: modelOutput.delta,
374
+ tool_call_id: "",
375
+ fidelity: { item_id: modelOutput.item_id },
376
+ });
377
+ }
378
+ else if (openaiEventType === "response.completed" ||
379
+ openaiEventType === "response.incomplete") {
380
+ eventType = "stop";
381
+ const response = modelOutput.response;
382
+ const finishReasonMapping = {
383
+ completed: "stop",
384
+ incomplete: "length",
385
+ };
386
+ if (response.status) {
387
+ finishReason = finishReasonMapping[response.status] || "unknown";
388
+ }
389
+ if (response.usage) {
390
+ const inputTokens = response.usage.input_tokens;
391
+ const outputTokens = response.usage.output_tokens;
392
+ const cachedTokens = response.usage.input_tokens_details.cached_tokens;
393
+ const reasoningTokens = response.usage.output_tokens_details.reasoning_tokens;
394
+ usageMetadata = {
395
+ cached_tokens: cachedTokens,
396
+ prompt_tokens: inputTokens - cachedTokens,
397
+ thoughts_tokens: reasoningTokens,
398
+ response_tokens: outputTokens - reasoningTokens,
399
+ };
400
+ }
401
+ }
402
+ else if ([
403
+ "response.created",
404
+ "response.in_progress",
405
+ "response.output_text.done",
406
+ "response.function_call_arguments.done",
407
+ "response.reasoning_summary_part.added",
408
+ "response.reasoning_summary_part.done",
409
+ "response.reasoning_summary_text.done",
410
+ "response.reasoning_text.done",
411
+ "response.content_part.added",
412
+ "response.content_part.done",
413
+ // gateway heartbeat on long generations; carries no content
414
+ "keepalive",
415
+ ].includes(openaiEventType)) {
416
+ // lifecycle events, and repeats of what the deltas carry
417
+ }
418
+ else if ((0, utils_1.isDebugEnabled)()) {
419
+ throw new Error(`Unknown output: ${JSON.stringify(modelOutput)}`);
420
+ }
421
+ else {
422
+ // a gateway injects its own events (heartbeats, cost tickers) into the stream, and
423
+ // killing a long generation over one costs more than dropping it
424
+ }
425
+ return {
426
+ role: "assistant",
427
+ event_type: eventType,
428
+ content_items: contentItems,
429
+ usage_metadata: usageMetadata,
430
+ finish_reason: finishReason,
431
+ };
432
+ }
433
+ /**
434
+ * Stream generate using OpenAI Responses API with unified conversion methods.
435
+ */
436
+ async *_streamingResponseInternal(options) {
437
+ const openaiConfig = this.transformUniConfigToModelConfig(options.config);
438
+ const inputList = this.transformUniMessageToModelInput(options.messages, options.signal);
439
+ const params = {
440
+ ...openaiConfig,
441
+ input: inputList,
442
+ stream: true,
443
+ };
444
+ const stream = await this._client.responses.create(params, {
445
+ signal: options.signal,
446
+ });
447
+ for await (const event of stream) {
448
+ yield this.transformModelOutputToUniEvent(event);
449
+ }
450
+ }
451
+ /**
452
+ * List the model ids the configured endpoint serves.
453
+ *
454
+ * @returns The model ids, in the order the endpoint returned them.
455
+ */
456
+ async listModels() {
457
+ const models = [];
458
+ for await (const model of this._client.models.list()) {
459
+ models.push(model.id);
460
+ }
461
+ return models;
462
+ }
463
+ }
464
+ exports.OpenAIOfficialClient = OpenAIOfficialClient;