@ubiquity-os/plugin-sdk 3.8.0 → 3.8.4

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/llm.d.mts CHANGED
@@ -1,6 +1,5 @@
1
- import { ChatCompletionMessageParam, ChatCompletionCreateParamsNonStreaming, ChatCompletion, ChatCompletionChunk } from 'openai/resources/chat/completions';
2
- import { C as Context } from './context-Dwl3aRX-.mjs';
3
- import { PluginInput } from './signature.mjs';
1
+ import { ChatCompletionMessageParam, ChatCompletion, ChatCompletionChunk } from 'openai/resources/chat/completions';
2
+ import { C as Context } from './context-sqbr2o6i.mjs';
4
3
  import '@octokit/webhooks';
5
4
  import '@ubiquity-os/ubiquity-os-logger';
6
5
  import '@octokit/plugin-rest-endpoint-methods';
@@ -8,16 +7,54 @@ import './octokit.mjs';
8
7
  import '@octokit/core/types';
9
8
  import '@octokit/plugin-paginate-graphql';
10
9
  import '@octokit/plugin-paginate-rest';
11
- import '@octokit/request-error';
10
+ import '@octokit/webhooks/node_modules/@octokit/request-error';
12
11
  import '@octokit/core';
13
- import '@sinclair/typebox';
14
12
 
13
+ type LlmResponseFormat = {
14
+ type: "json_object" | "text";
15
+ } | {
16
+ type: string;
17
+ [key: string]: unknown;
18
+ };
19
+ type LlmPayload = {
20
+ repository?: {
21
+ owner?: {
22
+ login?: string;
23
+ };
24
+ name?: string;
25
+ };
26
+ installation?: {
27
+ id?: number;
28
+ };
29
+ };
30
+ type LlmAuthContext = {
31
+ authToken?: string;
32
+ ubiquityKernelToken?: string;
33
+ payload?: LlmPayload;
34
+ eventPayload?: LlmPayload;
35
+ };
15
36
  type LlmCallOptions = {
16
37
  baseUrl?: string;
17
38
  model?: string;
18
39
  stream?: boolean;
19
40
  messages: ChatCompletionMessageParam[];
20
- } & Partial<Omit<ChatCompletionCreateParamsNonStreaming, "model" | "messages" | "stream">>;
21
- declare function callLlm(options: LlmCallOptions, input: PluginInput | Context): Promise<ChatCompletion | AsyncIterable<ChatCompletionChunk>>;
41
+ max_tokens?: number;
42
+ max_completion_tokens?: number;
43
+ temperature?: number;
44
+ top_p?: number;
45
+ frequency_penalty?: number;
46
+ presence_penalty?: number;
47
+ response_format?: LlmResponseFormat;
48
+ stop?: string | string[];
49
+ n?: number;
50
+ logit_bias?: Record<string, number>;
51
+ seed?: number;
52
+ user?: string;
53
+ metadata?: Record<string, unknown>;
54
+ tools?: unknown[];
55
+ tool_choice?: string | Record<string, unknown>;
56
+ [key: string]: unknown;
57
+ };
58
+ declare function callLlm(options: LlmCallOptions, input: Context | LlmAuthContext): Promise<ChatCompletion | AsyncIterable<ChatCompletionChunk>>;
22
59
 
23
60
  export { type LlmCallOptions, callLlm };
package/dist/llm.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { ChatCompletionMessageParam, ChatCompletionCreateParamsNonStreaming, ChatCompletion, ChatCompletionChunk } from 'openai/resources/chat/completions';
2
- import { C as Context } from './context-zLHgu52i.js';
3
- import { PluginInput } from './signature.js';
1
+ import { ChatCompletionMessageParam, ChatCompletion, ChatCompletionChunk } from 'openai/resources/chat/completions';
2
+ import { C as Context } from './context-BbEmsEct.js';
4
3
  import '@octokit/webhooks';
5
4
  import '@ubiquity-os/ubiquity-os-logger';
6
5
  import '@octokit/plugin-rest-endpoint-methods';
@@ -8,16 +7,54 @@ import './octokit.js';
8
7
  import '@octokit/core/types';
9
8
  import '@octokit/plugin-paginate-graphql';
10
9
  import '@octokit/plugin-paginate-rest';
11
- import '@octokit/request-error';
10
+ import '@octokit/webhooks/node_modules/@octokit/request-error';
12
11
  import '@octokit/core';
13
- import '@sinclair/typebox';
14
12
 
13
+ type LlmResponseFormat = {
14
+ type: "json_object" | "text";
15
+ } | {
16
+ type: string;
17
+ [key: string]: unknown;
18
+ };
19
+ type LlmPayload = {
20
+ repository?: {
21
+ owner?: {
22
+ login?: string;
23
+ };
24
+ name?: string;
25
+ };
26
+ installation?: {
27
+ id?: number;
28
+ };
29
+ };
30
+ type LlmAuthContext = {
31
+ authToken?: string;
32
+ ubiquityKernelToken?: string;
33
+ payload?: LlmPayload;
34
+ eventPayload?: LlmPayload;
35
+ };
15
36
  type LlmCallOptions = {
16
37
  baseUrl?: string;
17
38
  model?: string;
18
39
  stream?: boolean;
19
40
  messages: ChatCompletionMessageParam[];
20
- } & Partial<Omit<ChatCompletionCreateParamsNonStreaming, "model" | "messages" | "stream">>;
21
- declare function callLlm(options: LlmCallOptions, input: PluginInput | Context): Promise<ChatCompletion | AsyncIterable<ChatCompletionChunk>>;
41
+ max_tokens?: number;
42
+ max_completion_tokens?: number;
43
+ temperature?: number;
44
+ top_p?: number;
45
+ frequency_penalty?: number;
46
+ presence_penalty?: number;
47
+ response_format?: LlmResponseFormat;
48
+ stop?: string | string[];
49
+ n?: number;
50
+ logit_bias?: Record<string, number>;
51
+ seed?: number;
52
+ user?: string;
53
+ metadata?: Record<string, unknown>;
54
+ tools?: unknown[];
55
+ tool_choice?: string | Record<string, unknown>;
56
+ [key: string]: unknown;
57
+ };
58
+ declare function callLlm(options: LlmCallOptions, input: Context | LlmAuthContext): Promise<ChatCompletion | AsyncIterable<ChatCompletionChunk>>;
22
59
 
23
60
  export { type LlmCallOptions, callLlm };
package/dist/llm.js CHANGED
@@ -23,7 +23,6 @@ __export(llm_exports, {
23
23
  callLlm: () => callLlm
24
24
  });
25
25
  module.exports = __toCommonJS(llm_exports);
26
- var EMPTY_STRING = "";
27
26
  function normalizeBaseUrl(baseUrl) {
28
27
  let normalized = baseUrl.trim();
29
28
  while (normalized.endsWith("/")) {
@@ -31,53 +30,56 @@ function normalizeBaseUrl(baseUrl) {
31
30
  }
32
31
  return normalized;
33
32
  }
34
- var MAX_LLM_RETRIES = 2;
35
- var RETRY_BACKOFF_MS = [250, 750];
36
- function getRetryDelayMs(attempt) {
37
- return RETRY_BACKOFF_MS[Math.min(attempt, RETRY_BACKOFF_MS.length - 1)] ?? 750;
38
- }
39
- function sleep(ms) {
40
- return new Promise((resolve) => setTimeout(resolve, ms));
41
- }
42
33
  function getEnvString(name) {
43
- if (typeof process === "undefined" || !process?.env) return EMPTY_STRING;
44
- return String(process.env[name] ?? EMPTY_STRING).trim();
34
+ if (typeof process === "undefined" || !process?.env) return "";
35
+ return String(process.env[name] ?? "").trim();
45
36
  }
46
37
  function getAiBaseUrl(options) {
47
38
  if (typeof options.baseUrl === "string" && options.baseUrl.trim()) {
48
39
  return normalizeBaseUrl(options.baseUrl);
49
40
  }
50
- const envBaseUrl = getEnvString("UOS_AI_URL") || getEnvString("UOS_AI_BASE_URL");
41
+ const envBaseUrl = getEnvString("UBQ_AI_BASE_URL") || getEnvString("UBQ_AI_URL");
51
42
  if (envBaseUrl) return normalizeBaseUrl(envBaseUrl);
52
- return "https://ai-ubq-fi.deno.dev";
43
+ return "https://ai.ubq.fi";
53
44
  }
54
45
  async function callLlm(options, input) {
55
- const authToken = String(input.authToken ?? EMPTY_STRING).trim();
56
- if (!authToken) {
57
- const err = new Error("Missing authToken in input");
58
- err.status = 401;
59
- throw err;
46
+ const inputPayload = input;
47
+ const authToken = inputPayload.authToken;
48
+ const ubiquityKernelToken = inputPayload.ubiquityKernelToken;
49
+ const payload = inputPayload.payload ?? inputPayload.eventPayload;
50
+ const owner = payload?.repository?.owner?.login ?? "";
51
+ const repo = payload?.repository?.name ?? "";
52
+ const installationId = payload?.installation?.id;
53
+ if (!authToken) throw new Error("Missing authToken in inputs");
54
+ const isKernelTokenRequired = authToken.trim().startsWith("gh");
55
+ if (isKernelTokenRequired && !ubiquityKernelToken) {
56
+ throw new Error("Missing ubiquityKernelToken in inputs (kernel attestation is required for GitHub auth)");
60
57
  }
61
- const kernelToken = "ubiquityKernelToken" in input ? input.ubiquityKernelToken : void 0;
62
- const payload = getPayload(input);
63
- const { owner, repo, installationId } = getRepoMetadata(payload);
64
- ensureKernelToken(authToken, kernelToken);
65
58
  const { baseUrl, model, stream: isStream, messages, ...rest } = options;
66
- ensureMessages(messages);
67
- const url = buildAiUrl(options, baseUrl);
59
+ const url = `${getAiBaseUrl({ ...options, baseUrl })}/v1/chat/completions`;
68
60
  const body = JSON.stringify({
69
61
  ...rest,
70
62
  ...model ? { model } : {},
71
63
  messages,
72
64
  stream: isStream ?? false
73
65
  });
74
- const headers = buildHeaders(authToken, {
75
- owner,
76
- repo,
77
- installationId,
78
- ubiquityKernelToken: kernelToken
79
- });
80
- const response = await fetchWithRetry(url, { method: "POST", headers, body }, MAX_LLM_RETRIES);
66
+ const headers = {
67
+ Authorization: `Bearer ${authToken}`,
68
+ "Content-Type": "application/json"
69
+ };
70
+ if (owner) headers["X-GitHub-Owner"] = owner;
71
+ if (repo) headers["X-GitHub-Repo"] = repo;
72
+ if (typeof installationId === "number" && Number.isFinite(installationId)) {
73
+ headers["X-GitHub-Installation-Id"] = String(installationId);
74
+ }
75
+ if (ubiquityKernelToken) {
76
+ headers["X-Ubiquity-Kernel-Token"] = ubiquityKernelToken;
77
+ }
78
+ const response = await fetch(url, { method: "POST", headers, body });
79
+ if (!response.ok) {
80
+ const err = await response.text();
81
+ throw new Error(`LLM API error: ${response.status} - ${err}`);
82
+ }
81
83
  if (isStream) {
82
84
  if (!response.body) {
83
85
  throw new Error("LLM API error: missing response body for streaming request");
@@ -86,122 +88,29 @@ async function callLlm(options, input) {
86
88
  }
87
89
  return response.json();
88
90
  }
89
- function ensureKernelToken(authToken, kernelToken) {
90
- const isKernelTokenRequired = authToken.startsWith("gh");
91
- if (isKernelTokenRequired && !kernelToken) {
92
- const err = new Error("Missing ubiquityKernelToken in input (kernel attestation is required for GitHub auth)");
93
- err.status = 401;
94
- throw err;
95
- }
96
- }
97
- function ensureMessages(messages) {
98
- if (!Array.isArray(messages) || messages.length === 0) {
99
- const err = new Error("messages must be a non-empty array");
100
- err.status = 400;
101
- throw err;
102
- }
103
- }
104
- function buildAiUrl(options, baseUrl) {
105
- return `${getAiBaseUrl({ ...options, baseUrl })}/v1/chat/completions`;
106
- }
107
- async function fetchWithRetry(url, options, maxRetries) {
108
- let attempt = 0;
109
- let lastError;
110
- while (attempt <= maxRetries) {
111
- try {
112
- const response = await fetch(url, options);
113
- if (response.ok) return response;
114
- const errText = await response.text();
115
- if (response.status >= 500 && attempt < maxRetries) {
116
- await sleep(getRetryDelayMs(attempt));
117
- attempt += 1;
118
- continue;
119
- }
120
- const error = new Error(`LLM API error: ${response.status} - ${errText}`);
121
- error.status = response.status;
122
- throw error;
123
- } catch (error) {
124
- lastError = error;
125
- if (attempt >= maxRetries) throw error;
126
- await sleep(getRetryDelayMs(attempt));
127
- attempt += 1;
128
- }
129
- }
130
- throw lastError ?? new Error("LLM API error: request failed after retries");
131
- }
132
- function getPayload(input) {
133
- if ("payload" in input) {
134
- return input.payload;
135
- }
136
- return input.eventPayload;
137
- }
138
- function getRepoMetadata(payload) {
139
- const repoPayload = payload;
140
- return {
141
- owner: repoPayload?.repository?.owner?.login ?? EMPTY_STRING,
142
- repo: repoPayload?.repository?.name ?? EMPTY_STRING,
143
- installationId: repoPayload?.installation?.id
144
- };
145
- }
146
- function buildHeaders(authToken, options) {
147
- const headers = {
148
- Authorization: `Bearer ${authToken}`,
149
- "Content-Type": "application/json"
150
- };
151
- if (options.owner) headers["X-GitHub-Owner"] = options.owner;
152
- if (options.repo) headers["X-GitHub-Repo"] = options.repo;
153
- if (typeof options.installationId === "number" && Number.isFinite(options.installationId)) {
154
- headers["X-GitHub-Installation-Id"] = String(options.installationId);
155
- }
156
- if (options.ubiquityKernelToken) {
157
- headers["X-Ubiquity-Kernel-Token"] = options.ubiquityKernelToken;
158
- }
159
- return headers;
160
- }
161
91
  async function* parseSseStream(body) {
162
92
  const reader = body.getReader();
163
93
  const decoder = new TextDecoder();
164
- let buffer = EMPTY_STRING;
94
+ let buffer = "";
165
95
  try {
166
96
  while (true) {
167
97
  const { value, done: isDone } = await reader.read();
168
98
  if (isDone) break;
169
99
  buffer += decoder.decode(value, { stream: true });
170
- const { events, remainder } = splitSseEvents(buffer);
171
- buffer = remainder;
100
+ const events = buffer.split("\n\n");
101
+ buffer = events.pop() || "";
172
102
  for (const event of events) {
173
- const data = getEventData(event);
174
- if (!data) continue;
175
- if (data.trim() === "[DONE]") return;
176
- yield parseEventData(data);
103
+ if (event.startsWith("data: ")) {
104
+ const data = event.slice(6);
105
+ if (data === "[DONE]") return;
106
+ yield JSON.parse(data);
107
+ }
177
108
  }
178
109
  }
179
110
  } finally {
180
111
  reader.releaseLock();
181
112
  }
182
113
  }
183
- function splitSseEvents(buffer) {
184
- const normalized = buffer.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
185
- const parts = normalized.split("\n\n");
186
- const remainder = parts.pop() ?? EMPTY_STRING;
187
- return { events: parts, remainder };
188
- }
189
- function getEventData(event) {
190
- if (!event.trim()) return null;
191
- const dataLines = event.split("\n").filter((line) => line.startsWith("data:"));
192
- if (!dataLines.length) return null;
193
- const data = dataLines.map((line) => line.startsWith("data: ") ? line.slice(6) : line.slice(5).replace(/^ /, EMPTY_STRING)).join("\n");
194
- return data || null;
195
- }
196
- function parseEventData(data) {
197
- try {
198
- return JSON.parse(data);
199
- } catch (error) {
200
- const message = error instanceof Error ? error.message : String(error);
201
- const preview = data.length > 200 ? `${data.slice(0, 200)}...` : data;
202
- throw new Error(`LLM stream parse error: ${message}. Data: ${preview}`);
203
- }
204
- }
205
114
  // Annotate the CommonJS export names for ESM import in node:
206
115
  0 && (module.exports = {
207
116
  callLlm
package/dist/llm.mjs CHANGED
@@ -1,5 +1,4 @@
1
1
  // src/llm/index.ts
2
- var EMPTY_STRING = "";
3
2
  function normalizeBaseUrl(baseUrl) {
4
3
  let normalized = baseUrl.trim();
5
4
  while (normalized.endsWith("/")) {
@@ -7,53 +6,56 @@ function normalizeBaseUrl(baseUrl) {
7
6
  }
8
7
  return normalized;
9
8
  }
10
- var MAX_LLM_RETRIES = 2;
11
- var RETRY_BACKOFF_MS = [250, 750];
12
- function getRetryDelayMs(attempt) {
13
- return RETRY_BACKOFF_MS[Math.min(attempt, RETRY_BACKOFF_MS.length - 1)] ?? 750;
14
- }
15
- function sleep(ms) {
16
- return new Promise((resolve) => setTimeout(resolve, ms));
17
- }
18
9
  function getEnvString(name) {
19
- if (typeof process === "undefined" || !process?.env) return EMPTY_STRING;
20
- return String(process.env[name] ?? EMPTY_STRING).trim();
10
+ if (typeof process === "undefined" || !process?.env) return "";
11
+ return String(process.env[name] ?? "").trim();
21
12
  }
22
13
  function getAiBaseUrl(options) {
23
14
  if (typeof options.baseUrl === "string" && options.baseUrl.trim()) {
24
15
  return normalizeBaseUrl(options.baseUrl);
25
16
  }
26
- const envBaseUrl = getEnvString("UOS_AI_URL") || getEnvString("UOS_AI_BASE_URL");
17
+ const envBaseUrl = getEnvString("UBQ_AI_BASE_URL") || getEnvString("UBQ_AI_URL");
27
18
  if (envBaseUrl) return normalizeBaseUrl(envBaseUrl);
28
- return "https://ai-ubq-fi.deno.dev";
19
+ return "https://ai.ubq.fi";
29
20
  }
30
21
  async function callLlm(options, input) {
31
- const authToken = String(input.authToken ?? EMPTY_STRING).trim();
32
- if (!authToken) {
33
- const err = new Error("Missing authToken in input");
34
- err.status = 401;
35
- throw err;
22
+ const inputPayload = input;
23
+ const authToken = inputPayload.authToken;
24
+ const ubiquityKernelToken = inputPayload.ubiquityKernelToken;
25
+ const payload = inputPayload.payload ?? inputPayload.eventPayload;
26
+ const owner = payload?.repository?.owner?.login ?? "";
27
+ const repo = payload?.repository?.name ?? "";
28
+ const installationId = payload?.installation?.id;
29
+ if (!authToken) throw new Error("Missing authToken in inputs");
30
+ const isKernelTokenRequired = authToken.trim().startsWith("gh");
31
+ if (isKernelTokenRequired && !ubiquityKernelToken) {
32
+ throw new Error("Missing ubiquityKernelToken in inputs (kernel attestation is required for GitHub auth)");
36
33
  }
37
- const kernelToken = "ubiquityKernelToken" in input ? input.ubiquityKernelToken : void 0;
38
- const payload = getPayload(input);
39
- const { owner, repo, installationId } = getRepoMetadata(payload);
40
- ensureKernelToken(authToken, kernelToken);
41
34
  const { baseUrl, model, stream: isStream, messages, ...rest } = options;
42
- ensureMessages(messages);
43
- const url = buildAiUrl(options, baseUrl);
35
+ const url = `${getAiBaseUrl({ ...options, baseUrl })}/v1/chat/completions`;
44
36
  const body = JSON.stringify({
45
37
  ...rest,
46
38
  ...model ? { model } : {},
47
39
  messages,
48
40
  stream: isStream ?? false
49
41
  });
50
- const headers = buildHeaders(authToken, {
51
- owner,
52
- repo,
53
- installationId,
54
- ubiquityKernelToken: kernelToken
55
- });
56
- const response = await fetchWithRetry(url, { method: "POST", headers, body }, MAX_LLM_RETRIES);
42
+ const headers = {
43
+ Authorization: `Bearer ${authToken}`,
44
+ "Content-Type": "application/json"
45
+ };
46
+ if (owner) headers["X-GitHub-Owner"] = owner;
47
+ if (repo) headers["X-GitHub-Repo"] = repo;
48
+ if (typeof installationId === "number" && Number.isFinite(installationId)) {
49
+ headers["X-GitHub-Installation-Id"] = String(installationId);
50
+ }
51
+ if (ubiquityKernelToken) {
52
+ headers["X-Ubiquity-Kernel-Token"] = ubiquityKernelToken;
53
+ }
54
+ const response = await fetch(url, { method: "POST", headers, body });
55
+ if (!response.ok) {
56
+ const err = await response.text();
57
+ throw new Error(`LLM API error: ${response.status} - ${err}`);
58
+ }
57
59
  if (isStream) {
58
60
  if (!response.body) {
59
61
  throw new Error("LLM API error: missing response body for streaming request");
@@ -62,122 +64,29 @@ async function callLlm(options, input) {
62
64
  }
63
65
  return response.json();
64
66
  }
65
- function ensureKernelToken(authToken, kernelToken) {
66
- const isKernelTokenRequired = authToken.startsWith("gh");
67
- if (isKernelTokenRequired && !kernelToken) {
68
- const err = new Error("Missing ubiquityKernelToken in input (kernel attestation is required for GitHub auth)");
69
- err.status = 401;
70
- throw err;
71
- }
72
- }
73
- function ensureMessages(messages) {
74
- if (!Array.isArray(messages) || messages.length === 0) {
75
- const err = new Error("messages must be a non-empty array");
76
- err.status = 400;
77
- throw err;
78
- }
79
- }
80
- function buildAiUrl(options, baseUrl) {
81
- return `${getAiBaseUrl({ ...options, baseUrl })}/v1/chat/completions`;
82
- }
83
- async function fetchWithRetry(url, options, maxRetries) {
84
- let attempt = 0;
85
- let lastError;
86
- while (attempt <= maxRetries) {
87
- try {
88
- const response = await fetch(url, options);
89
- if (response.ok) return response;
90
- const errText = await response.text();
91
- if (response.status >= 500 && attempt < maxRetries) {
92
- await sleep(getRetryDelayMs(attempt));
93
- attempt += 1;
94
- continue;
95
- }
96
- const error = new Error(`LLM API error: ${response.status} - ${errText}`);
97
- error.status = response.status;
98
- throw error;
99
- } catch (error) {
100
- lastError = error;
101
- if (attempt >= maxRetries) throw error;
102
- await sleep(getRetryDelayMs(attempt));
103
- attempt += 1;
104
- }
105
- }
106
- throw lastError ?? new Error("LLM API error: request failed after retries");
107
- }
108
- function getPayload(input) {
109
- if ("payload" in input) {
110
- return input.payload;
111
- }
112
- return input.eventPayload;
113
- }
114
- function getRepoMetadata(payload) {
115
- const repoPayload = payload;
116
- return {
117
- owner: repoPayload?.repository?.owner?.login ?? EMPTY_STRING,
118
- repo: repoPayload?.repository?.name ?? EMPTY_STRING,
119
- installationId: repoPayload?.installation?.id
120
- };
121
- }
122
- function buildHeaders(authToken, options) {
123
- const headers = {
124
- Authorization: `Bearer ${authToken}`,
125
- "Content-Type": "application/json"
126
- };
127
- if (options.owner) headers["X-GitHub-Owner"] = options.owner;
128
- if (options.repo) headers["X-GitHub-Repo"] = options.repo;
129
- if (typeof options.installationId === "number" && Number.isFinite(options.installationId)) {
130
- headers["X-GitHub-Installation-Id"] = String(options.installationId);
131
- }
132
- if (options.ubiquityKernelToken) {
133
- headers["X-Ubiquity-Kernel-Token"] = options.ubiquityKernelToken;
134
- }
135
- return headers;
136
- }
137
67
  async function* parseSseStream(body) {
138
68
  const reader = body.getReader();
139
69
  const decoder = new TextDecoder();
140
- let buffer = EMPTY_STRING;
70
+ let buffer = "";
141
71
  try {
142
72
  while (true) {
143
73
  const { value, done: isDone } = await reader.read();
144
74
  if (isDone) break;
145
75
  buffer += decoder.decode(value, { stream: true });
146
- const { events, remainder } = splitSseEvents(buffer);
147
- buffer = remainder;
76
+ const events = buffer.split("\n\n");
77
+ buffer = events.pop() || "";
148
78
  for (const event of events) {
149
- const data = getEventData(event);
150
- if (!data) continue;
151
- if (data.trim() === "[DONE]") return;
152
- yield parseEventData(data);
79
+ if (event.startsWith("data: ")) {
80
+ const data = event.slice(6);
81
+ if (data === "[DONE]") return;
82
+ yield JSON.parse(data);
83
+ }
153
84
  }
154
85
  }
155
86
  } finally {
156
87
  reader.releaseLock();
157
88
  }
158
89
  }
159
- function splitSseEvents(buffer) {
160
- const normalized = buffer.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
161
- const parts = normalized.split("\n\n");
162
- const remainder = parts.pop() ?? EMPTY_STRING;
163
- return { events: parts, remainder };
164
- }
165
- function getEventData(event) {
166
- if (!event.trim()) return null;
167
- const dataLines = event.split("\n").filter((line) => line.startsWith("data:"));
168
- if (!dataLines.length) return null;
169
- const data = dataLines.map((line) => line.startsWith("data: ") ? line.slice(6) : line.slice(5).replace(/^ /, EMPTY_STRING)).join("\n");
170
- return data || null;
171
- }
172
- function parseEventData(data) {
173
- try {
174
- return JSON.parse(data);
175
- } catch (error) {
176
- const message = error instanceof Error ? error.message : String(error);
177
- const preview = data.length > 200 ? `${data.slice(0, 200)}...` : data;
178
- throw new Error(`LLM stream parse error: ${message}. Data: ${preview}`);
179
- }
180
- }
181
90
  export {
182
91
  callLlm
183
92
  };
@@ -3,12 +3,12 @@ import * as _octokit_plugin_paginate_graphql from '@octokit/plugin-paginate-grap
3
3
  import * as _octokit_plugin_rest_endpoint_methods from '@octokit/plugin-rest-endpoint-methods';
4
4
  export { RestEndpointMethodTypes } from '@octokit/plugin-rest-endpoint-methods';
5
5
  import * as _octokit_plugin_paginate_rest from '@octokit/plugin-paginate-rest';
6
- import * as _octokit_request_error from '@octokit/request-error';
6
+ import * as _octokit_webhooks_node_modules__octokit_request_error from '@octokit/webhooks/node_modules/@octokit/request-error';
7
7
  import { Octokit } from '@octokit/core';
8
8
 
9
9
  declare const customOctokit: typeof Octokit & _octokit_core_types.Constructor<{
10
10
  retry: {
11
- retryRequest: (error: _octokit_request_error.RequestError, retries: number, retryAfter: number) => _octokit_request_error.RequestError;
11
+ retryRequest: (error: _octokit_webhooks_node_modules__octokit_request_error.RequestError, retries: number, retryAfter: number) => _octokit_webhooks_node_modules__octokit_request_error.RequestError;
12
12
  };
13
13
  } & {
14
14
  paginate: _octokit_plugin_paginate_rest.PaginateInterface;
package/dist/octokit.d.ts CHANGED
@@ -3,12 +3,12 @@ import * as _octokit_plugin_paginate_graphql from '@octokit/plugin-paginate-grap
3
3
  import * as _octokit_plugin_rest_endpoint_methods from '@octokit/plugin-rest-endpoint-methods';
4
4
  export { RestEndpointMethodTypes } from '@octokit/plugin-rest-endpoint-methods';
5
5
  import * as _octokit_plugin_paginate_rest from '@octokit/plugin-paginate-rest';
6
- import * as _octokit_request_error from '@octokit/request-error';
6
+ import * as _octokit_webhooks_node_modules__octokit_request_error from '@octokit/webhooks/node_modules/@octokit/request-error';
7
7
  import { Octokit } from '@octokit/core';
8
8
 
9
9
  declare const customOctokit: typeof Octokit & _octokit_core_types.Constructor<{
10
10
  retry: {
11
- retryRequest: (error: _octokit_request_error.RequestError, retries: number, retryAfter: number) => _octokit_request_error.RequestError;
11
+ retryRequest: (error: _octokit_webhooks_node_modules__octokit_request_error.RequestError, retries: number, retryAfter: number) => _octokit_webhooks_node_modules__octokit_request_error.RequestError;
12
12
  };
13
13
  } & {
14
14
  paginate: _octokit_plugin_paginate_rest.PaginateInterface;