@umituz/react-native-ai-pruna-provider 1.0.42 → 1.0.44

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-pruna-provider",
3
- "version": "1.0.42",
3
+ "version": "1.0.44",
4
4
  "description": "Pruna AI provider for React Native - implements IAIProvider interface for unified AI generation",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -22,7 +22,8 @@ import type { LogEntry } from "../utils/log-collector";
22
22
  import {
23
23
  createRequestKey, getExistingRequest, storeRequest,
24
24
  removeRequest, cancelRequest, cancelAllRequests, hasActiveRequests,
25
- storeRequestIdMapping, getStatusUrlForRequestId, removeRequestIdMapping,
25
+ storeRequestIdMapping, storeImmediateResultMapping,
26
+ getStatusUrlForRequestId, getResponseUrlForRequestId, removeRequestIdMapping,
26
27
  } from "./request-store";
27
28
 
28
29
  export class PrunaProvider implements IAIProvider {
@@ -86,15 +87,26 @@ export class PrunaProvider implements IAIProvider {
86
87
  const apiKey = this.validateInit();
87
88
  const prunaModel = this.validateModel(model);
88
89
  const sessionId = generationLogCollector.startSession();
89
- generationLogCollector.log(sessionId, 'pruna-provider', `submitJob() for model: ${model}`);
90
+ generationLogCollector.log(sessionId, 'pruna-provider', `submitJob() START model: ${model}`);
90
91
  try {
91
92
  const submission = await queueOps.submitJob(prunaModel, input, apiKey, sessionId);
92
93
 
93
- // Store requestId -> statusUrl mapping for getJobStatus/getJobResult
94
- if (submission.statusUrl) {
94
+ // Log response type
95
+ if (submission.responseUrl) {
96
+ generationLogCollector.log(sessionId, 'pruna-provider', `submitJob() IMMEDIATE RESULT - requestId: ${submission.requestId}, responseUrl: ${submission.responseUrl.substring(0, 80)}...`);
97
+ // Store requestId -> responseUrl mapping for immediate results (already complete)
98
+ storeImmediateResultMapping(submission.requestId, submission.responseUrl, model);
99
+ generationLogCollector.log(sessionId, 'pruna-provider', `submitJob() Stored immediate result mapping: ${submission.requestId}`);
100
+ } else if (submission.statusUrl) {
101
+ generationLogCollector.log(sessionId, 'pruna-provider', `submitJob() ASYNC JOB - requestId: ${submission.requestId}, statusUrl: ${submission.statusUrl.substring(0, 80)}...`);
102
+ // Store requestId -> statusUrl mapping for async jobs (requires polling)
95
103
  storeRequestIdMapping(submission.requestId, submission.statusUrl, model);
104
+ generationLogCollector.log(sessionId, 'pruna-provider', `submitJob() Stored async job mapping: ${submission.requestId}`);
105
+ } else {
106
+ generationLogCollector.warn(sessionId, 'pruna-provider', `submitJob() WARNING - No responseUrl or statusUrl in submission`);
96
107
  }
97
108
 
109
+ generationLogCollector.log(sessionId, 'pruna-provider', `submitJob() COMPLETE - returning submission with requestId: ${submission.requestId}`);
98
110
  return submission;
99
111
  } finally {
100
112
  generationLogCollector.endSession(sessionId);
@@ -104,29 +116,82 @@ export class PrunaProvider implements IAIProvider {
104
116
  async getJobStatus(model: string, requestId: string): Promise<JobStatus> {
105
117
  const apiKey = this.validateInit();
106
118
  const prunaModel = this.validateModel(model);
119
+ const sessionId = generationLogCollector.startSession();
120
+ generationLogCollector.log(sessionId, 'pruna-provider', `getJobStatus() START - model: ${model}, requestId: ${requestId}`);
107
121
 
108
- // Look up statusUrl from requestId mapping
109
- const statusUrl = getStatusUrlForRequestId(requestId);
110
- if (statusUrl) {
111
- return queueOps.getJobStatus(prunaModel, statusUrl, apiKey);
112
- }
122
+ try {
123
+ // Check if this is an immediate result (already completed)
124
+ const responseUrl = getResponseUrlForRequestId(requestId);
125
+ if (responseUrl) {
126
+ generationLogCollector.log(sessionId, 'pruna-provider', `getJobStatus() FOUND immediate result for ${requestId} - returning COMPLETED`);
127
+ generationLogCollector.endSession(sessionId);
128
+ // Result is already available
129
+ return {
130
+ status: "COMPLETED",
131
+ requestId,
132
+ };
133
+ }
134
+
135
+ // Look up statusUrl from requestId mapping (async job)
136
+ const statusUrl = getStatusUrlForRequestId(requestId);
137
+ if (statusUrl) {
138
+ generationLogCollector.log(sessionId, 'pruna-provider', `getJobStatus() FOUND async job for ${requestId} - polling statusUrl: ${statusUrl.substring(0, 80)}...`);
139
+ const result = await queueOps.getJobStatus(prunaModel, statusUrl, apiKey);
140
+ generationLogCollector.log(sessionId, 'pruna-provider', `getJobStatus() Poll result: ${result.status}`);
141
+ generationLogCollector.endSession(sessionId);
142
+ return result;
143
+ }
113
144
 
114
- // Fallback: assume requestId is actually a statusUrl (for direct calls with statusUrl)
115
- return queueOps.getJobStatus(prunaModel, requestId, apiKey);
145
+ // Fallback: assume requestId is actually a statusUrl (for direct calls with statusUrl)
146
+ generationLogCollector.log(sessionId, 'pruna-provider', `getJobStatus() NO mapping found - treating ${requestId} as statusUrl directly`);
147
+ const result = await queueOps.getJobStatus(prunaModel, requestId, apiKey);
148
+ generationLogCollector.log(sessionId, 'pruna-provider', `getJobStatus() Direct poll result: ${result.status}`);
149
+ generationLogCollector.endSession(sessionId);
150
+ return result;
151
+ } catch (error) {
152
+ generationLogCollector.error(sessionId, 'pruna-provider', `getJobStatus() ERROR: ${error instanceof Error ? error.message : String(error)}`);
153
+ generationLogCollector.endSession(sessionId);
154
+ throw error;
155
+ }
116
156
  }
117
157
 
118
158
  async getJobResult<T = unknown>(model: string, requestId: string): Promise<T> {
119
159
  const apiKey = this.validateInit();
120
160
  const prunaModel = this.validateModel(model);
161
+ const sessionId = generationLogCollector.startSession();
162
+ generationLogCollector.log(sessionId, 'pruna-provider', `getJobResult() START - model: ${model}, requestId: ${requestId}`);
121
163
 
122
- // Look up statusUrl from requestId mapping
123
- const statusUrl = getStatusUrlForRequestId(requestId);
124
- if (statusUrl) {
125
- return queueOps.getJobResult<T>(prunaModel, statusUrl, apiKey);
126
- }
164
+ try {
165
+ // Check if this is an immediate result (already completed)
166
+ const responseUrl = getResponseUrlForRequestId(requestId);
167
+ if (responseUrl) {
168
+ generationLogCollector.log(sessionId, 'pruna-provider', `getJobResult() FOUND immediate result for ${requestId} - returning url: ${responseUrl.substring(0, 80)}...`);
169
+ generationLogCollector.endSession(sessionId);
170
+ // Return the immediate result
171
+ return { url: responseUrl } as T;
172
+ }
173
+
174
+ // Look up statusUrl from requestId mapping (async job)
175
+ const statusUrl = getStatusUrlForRequestId(requestId);
176
+ if (statusUrl) {
177
+ generationLogCollector.log(sessionId, 'pruna-provider', `getJobResult() FOUND async job for ${requestId} - fetching from statusUrl: ${statusUrl.substring(0, 80)}...`);
178
+ const result = await queueOps.getJobResult<T>(prunaModel, statusUrl, apiKey);
179
+ generationLogCollector.log(sessionId, 'pruna-provider', `getJobResult() Fetch complete`);
180
+ generationLogCollector.endSession(sessionId);
181
+ return result;
182
+ }
127
183
 
128
- // Fallback: assume requestId is actually a statusUrl (for direct calls with statusUrl)
129
- return queueOps.getJobResult<T>(prunaModel, requestId, apiKey);
184
+ // Fallback: assume requestId is actually a statusUrl (for direct calls with statusUrl)
185
+ generationLogCollector.log(sessionId, 'pruna-provider', `getJobResult() NO mapping found - treating ${requestId} as statusUrl directly`);
186
+ const result = await queueOps.getJobResult<T>(prunaModel, requestId, apiKey);
187
+ generationLogCollector.log(sessionId, 'pruna-provider', `getJobResult() Direct fetch complete`);
188
+ generationLogCollector.endSession(sessionId);
189
+ return result;
190
+ } catch (error) {
191
+ generationLogCollector.error(sessionId, 'pruna-provider', `getJobResult() ERROR: ${error instanceof Error ? error.message : String(error)}`);
192
+ generationLogCollector.endSession(sessionId);
193
+ throw error;
194
+ }
130
195
  }
131
196
 
132
197
  async subscribe<T = unknown>(
@@ -16,7 +16,7 @@ const STORE_KEY = "__PRUNA_PROVIDER_REQUESTS__";
16
16
  const TIMER_KEY = "__PRUNA_PROVIDER_CLEANUP_TIMER__";
17
17
  const REQUEST_ID_KEY = "__PRUNA_PROVIDER_REQUEST_IDS__";
18
18
  type RequestStore = Map<string, ActiveRequest>;
19
- type RequestIdMap = Map<string, { statusUrl: string; model: string }>;
19
+ type RequestIdMap = Map<string, { statusUrl?: string; responseUrl?: string; model: string }>;
20
20
 
21
21
  const CLEANUP_INTERVAL = 60_000;
22
22
  const MAX_REQUEST_AGE = 3_660_000; // 61 min — must exceed max allowed timeout (1 hour)
@@ -151,7 +151,11 @@ function getRequestIdMap(): RequestIdMap {
151
151
  }
152
152
 
153
153
  export function storeRequestIdMapping(requestId: string, statusUrl: string, model: string): void {
154
- getRequestIdMap().set(requestId, { statusUrl, model });
154
+ getRequestIdMap().set(requestId, { statusUrl, model, responseUrl: undefined });
155
+ }
156
+
157
+ export function storeImmediateResultMapping(requestId: string, responseUrl: string, model: string): void {
158
+ getRequestIdMap().set(requestId, { statusUrl: undefined, model, responseUrl });
155
159
  }
156
160
 
157
161
  export function getStatusUrlForRequestId(requestId: string): string | undefined {
@@ -159,6 +163,11 @@ export function getStatusUrlForRequestId(requestId: string): string | undefined
159
163
  return mapping?.statusUrl;
160
164
  }
161
165
 
166
+ export function getResponseUrlForRequestId(requestId: string): string | undefined {
167
+ const mapping = getRequestIdMap().get(requestId);
168
+ return mapping?.responseUrl;
169
+ }
170
+
162
171
  export function getModelForRequestId(requestId: string): string | undefined {
163
172
  const mapping = getRequestIdMap().get(requestId);
164
173
  return mapping?.model;