@objectstack/service-ai 6.7.0 → 6.8.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/LICENSE +93 -202
- package/dist/index.cjs +225 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +180 -138
- package/dist/index.d.ts +180 -138
- package/dist/index.js +225 -18
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.cjs
CHANGED
|
@@ -766,7 +766,20 @@ function createDeleteFieldHandler(ctx) {
|
|
|
766
766
|
function createListObjectsHandler(ctx) {
|
|
767
767
|
return async (args) => {
|
|
768
768
|
const { filter, includeFields } = args ?? {};
|
|
769
|
-
|
|
769
|
+
let objects = [];
|
|
770
|
+
if (ctx.protocol?.getMetaItems) {
|
|
771
|
+
try {
|
|
772
|
+
const fromProtocol = await ctx.protocol.getMetaItems({ type: "object" });
|
|
773
|
+
const arr = Array.isArray(fromProtocol) ? fromProtocol : fromProtocol && typeof fromProtocol === "object" && Array.isArray(fromProtocol.items) ? fromProtocol.items : null;
|
|
774
|
+
objects = arr ?? await ctx.metadataService.listObjects();
|
|
775
|
+
} catch {
|
|
776
|
+
objects = await ctx.metadataService.listObjects();
|
|
777
|
+
}
|
|
778
|
+
} else {
|
|
779
|
+
objects = await ctx.metadataService.listObjects();
|
|
780
|
+
}
|
|
781
|
+
if (!Array.isArray(objects)) objects = [];
|
|
782
|
+
if (!Array.isArray(objects)) objects = [];
|
|
770
783
|
let result = objects.map((o) => {
|
|
771
784
|
const base = {
|
|
772
785
|
name: o.name,
|
|
@@ -803,7 +816,15 @@ function createDescribeObjectHandler(ctx) {
|
|
|
803
816
|
if (!isSnakeCase(objectName)) {
|
|
804
817
|
return JSON.stringify({ error: `Invalid object name "${objectName}". Must be snake_case.` });
|
|
805
818
|
}
|
|
806
|
-
|
|
819
|
+
let objectDef = await ctx.metadataService.getObject(objectName);
|
|
820
|
+
if (!objectDef && ctx.protocol?.getMetaItems) {
|
|
821
|
+
try {
|
|
822
|
+
const all = await ctx.protocol.getMetaItems({ type: "object" });
|
|
823
|
+
const arr = Array.isArray(all) ? all : all && typeof all === "object" && Array.isArray(all.items) ? all.items : [];
|
|
824
|
+
objectDef = arr.find((o) => o?.name === objectName);
|
|
825
|
+
} catch {
|
|
826
|
+
}
|
|
827
|
+
}
|
|
807
828
|
if (!objectDef) {
|
|
808
829
|
return JSON.stringify({ error: `Object "${objectName}" not found` });
|
|
809
830
|
}
|
|
@@ -1403,6 +1424,16 @@ var InMemoryConversationService = class {
|
|
|
1403
1424
|
conversation.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1404
1425
|
return conversation;
|
|
1405
1426
|
}
|
|
1427
|
+
async update(conversationId, patch) {
|
|
1428
|
+
const conversation = this.store.get(conversationId);
|
|
1429
|
+
if (!conversation) {
|
|
1430
|
+
throw new Error(`Conversation "${conversationId}" not found`);
|
|
1431
|
+
}
|
|
1432
|
+
if (patch.title !== void 0) conversation.title = patch.title;
|
|
1433
|
+
if (patch.metadata !== void 0) conversation.metadata = patch.metadata;
|
|
1434
|
+
conversation.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1435
|
+
return conversation;
|
|
1436
|
+
}
|
|
1406
1437
|
async delete(conversationId) {
|
|
1407
1438
|
this.store.delete(conversationId);
|
|
1408
1439
|
}
|
|
@@ -1530,6 +1561,30 @@ var _AIService = class _AIService {
|
|
|
1530
1561
|
this.logger.info(`[AI] LLM adapter swapped: ${prev} \u2192 ${next.name}`);
|
|
1531
1562
|
}
|
|
1532
1563
|
}
|
|
1564
|
+
/**
|
|
1565
|
+
* Best-effort auto-creation of a conversation when the caller did not
|
|
1566
|
+
* supply one but did supply an actor we can attribute the chat to.
|
|
1567
|
+
* Returns the new id on success, or `undefined` if creation failed (in
|
|
1568
|
+
* which case we silently fall back to non-persisted chat).
|
|
1569
|
+
*/
|
|
1570
|
+
async autoCreateConversation(ctx) {
|
|
1571
|
+
const actorId = ctx?.actor?.id;
|
|
1572
|
+
if (!actorId) return void 0;
|
|
1573
|
+
try {
|
|
1574
|
+
const conv = await this.conversationService.create({
|
|
1575
|
+
userId: actorId,
|
|
1576
|
+
metadata: ctx?.environmentId ? { environmentId: ctx.environmentId } : void 0
|
|
1577
|
+
});
|
|
1578
|
+
this.logger.debug("[AI] auto-created conversation", { conversationId: conv.id, actorId });
|
|
1579
|
+
return conv.id;
|
|
1580
|
+
} catch (err) {
|
|
1581
|
+
this.logger.warn("[AI] auto-create conversation failed", {
|
|
1582
|
+
actorId,
|
|
1583
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1584
|
+
});
|
|
1585
|
+
return void 0;
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1533
1588
|
/**
|
|
1534
1589
|
* Best-effort persistence of a single chat message to the conversation
|
|
1535
1590
|
* store. Failures are logged at warn level and swallowed — chat requests
|
|
@@ -1668,7 +1723,12 @@ var _AIService = class _AIService {
|
|
|
1668
1723
|
} = options ?? {};
|
|
1669
1724
|
const maxIterations = maxIter ?? _AIService.DEFAULT_MAX_ITERATIONS;
|
|
1670
1725
|
const registeredTools = this.toolRegistry.getAll();
|
|
1671
|
-
|
|
1726
|
+
let conversationId = toolExecutionContext?.conversationId;
|
|
1727
|
+
let autoCreatedConversationId;
|
|
1728
|
+
if (!conversationId) {
|
|
1729
|
+
autoCreatedConversationId = await this.autoCreateConversation(toolExecutionContext);
|
|
1730
|
+
conversationId = autoCreatedConversationId;
|
|
1731
|
+
}
|
|
1672
1732
|
const mergedTools = [
|
|
1673
1733
|
...registeredTools,
|
|
1674
1734
|
...restOptions.tools ?? []
|
|
@@ -1702,7 +1762,7 @@ var _AIService = class _AIService {
|
|
|
1702
1762
|
content: result.content
|
|
1703
1763
|
});
|
|
1704
1764
|
}
|
|
1705
|
-
return result;
|
|
1765
|
+
return autoCreatedConversationId ? { ...result, conversationId: autoCreatedConversationId } : result;
|
|
1706
1766
|
}
|
|
1707
1767
|
this.logger.debug("[AI] chatWithTools tool calls", {
|
|
1708
1768
|
iteration,
|
|
@@ -1769,7 +1829,7 @@ var _AIService = class _AIService {
|
|
|
1769
1829
|
content: finalResult.content
|
|
1770
1830
|
});
|
|
1771
1831
|
}
|
|
1772
|
-
return finalResult;
|
|
1832
|
+
return autoCreatedConversationId ? { ...finalResult, conversationId: autoCreatedConversationId } : finalResult;
|
|
1773
1833
|
}
|
|
1774
1834
|
/**
|
|
1775
1835
|
* Stream chat with automatic tool call resolution.
|
|
@@ -1787,7 +1847,12 @@ var _AIService = class _AIService {
|
|
|
1787
1847
|
} = options ?? {};
|
|
1788
1848
|
const maxIterations = maxIter ?? _AIService.DEFAULT_MAX_ITERATIONS;
|
|
1789
1849
|
const registeredTools = this.toolRegistry.getAll();
|
|
1790
|
-
|
|
1850
|
+
let conversationId = toolExecutionContext?.conversationId;
|
|
1851
|
+
let autoCreatedConversationId;
|
|
1852
|
+
if (!conversationId) {
|
|
1853
|
+
autoCreatedConversationId = await this.autoCreateConversation(toolExecutionContext);
|
|
1854
|
+
conversationId = autoCreatedConversationId;
|
|
1855
|
+
}
|
|
1791
1856
|
const mergedTools = [
|
|
1792
1857
|
...registeredTools,
|
|
1793
1858
|
...restOptions.tools ?? []
|
|
@@ -1799,6 +1864,14 @@ var _AIService = class _AIService {
|
|
|
1799
1864
|
};
|
|
1800
1865
|
const conversation = [...messages];
|
|
1801
1866
|
let abortedByCallback = false;
|
|
1867
|
+
if (autoCreatedConversationId) {
|
|
1868
|
+
yield {
|
|
1869
|
+
type: "tool-call",
|
|
1870
|
+
toolCallId: "__conversation_meta__",
|
|
1871
|
+
toolName: "__conversation_meta__",
|
|
1872
|
+
input: { conversationId: autoCreatedConversationId }
|
|
1873
|
+
};
|
|
1874
|
+
}
|
|
1802
1875
|
if (conversationId && messages.length > 0) {
|
|
1803
1876
|
const last = messages[messages.length - 1];
|
|
1804
1877
|
if (last && last.role === "user") {
|
|
@@ -2450,6 +2523,56 @@ function buildAIRoutes(aiService, conversationService, logger) {
|
|
|
2450
2523
|
}
|
|
2451
2524
|
}
|
|
2452
2525
|
},
|
|
2526
|
+
{
|
|
2527
|
+
method: "PATCH",
|
|
2528
|
+
path: "/api/v1/ai/conversations/:id",
|
|
2529
|
+
description: "Update mutable conversation fields (title, metadata)",
|
|
2530
|
+
auth: true,
|
|
2531
|
+
permissions: ["ai:conversations"],
|
|
2532
|
+
handler: async (req) => {
|
|
2533
|
+
const id = req.params?.id;
|
|
2534
|
+
if (!id) {
|
|
2535
|
+
return { status: 400, body: { error: "conversation id is required" } };
|
|
2536
|
+
}
|
|
2537
|
+
const body = req.body ?? {};
|
|
2538
|
+
const patch = {};
|
|
2539
|
+
if (body.title !== void 0) {
|
|
2540
|
+
if (typeof body.title !== "string") {
|
|
2541
|
+
return { status: 400, body: { error: "title must be a string" } };
|
|
2542
|
+
}
|
|
2543
|
+
patch.title = body.title;
|
|
2544
|
+
}
|
|
2545
|
+
if (body.metadata !== void 0) {
|
|
2546
|
+
if (typeof body.metadata !== "object" || body.metadata === null || Array.isArray(body.metadata)) {
|
|
2547
|
+
return { status: 400, body: { error: "metadata must be an object" } };
|
|
2548
|
+
}
|
|
2549
|
+
patch.metadata = body.metadata;
|
|
2550
|
+
}
|
|
2551
|
+
if (patch.title === void 0 && patch.metadata === void 0) {
|
|
2552
|
+
return { status: 400, body: { error: "at least one of title or metadata is required" } };
|
|
2553
|
+
}
|
|
2554
|
+
try {
|
|
2555
|
+
if (req.user?.userId) {
|
|
2556
|
+
const existing = await conversationService.get(id);
|
|
2557
|
+
if (!existing) {
|
|
2558
|
+
return { status: 404, body: { error: `Conversation "${id}" not found` } };
|
|
2559
|
+
}
|
|
2560
|
+
if (existing.userId && existing.userId !== req.user.userId) {
|
|
2561
|
+
return { status: 403, body: { error: "You do not have access to this conversation" } };
|
|
2562
|
+
}
|
|
2563
|
+
}
|
|
2564
|
+
const conversation = await conversationService.update(id, patch);
|
|
2565
|
+
return { status: 200, body: conversation };
|
|
2566
|
+
} catch (err) {
|
|
2567
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2568
|
+
if (msg.includes("not found")) {
|
|
2569
|
+
return { status: 404, body: { error: msg } };
|
|
2570
|
+
}
|
|
2571
|
+
logger.error("[AI Route] PATCH /conversations/:id error", err instanceof Error ? err : void 0);
|
|
2572
|
+
return { status: 500, body: { error: "Internal AI service error" } };
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
},
|
|
2453
2576
|
{
|
|
2454
2577
|
method: "DELETE",
|
|
2455
2578
|
path: "/api/v1/ai/conversations/:id",
|
|
@@ -3213,6 +3336,22 @@ var ObjectQLConversationService = class {
|
|
|
3213
3336
|
});
|
|
3214
3337
|
return await this.get(conversationId);
|
|
3215
3338
|
}
|
|
3339
|
+
async update(conversationId, patch) {
|
|
3340
|
+
const row = await this.engine.findOne(CONVERSATIONS_OBJECT, {
|
|
3341
|
+
where: { id: conversationId }
|
|
3342
|
+
});
|
|
3343
|
+
if (!row) {
|
|
3344
|
+
throw new Error(`Conversation "${conversationId}" not found`);
|
|
3345
|
+
}
|
|
3346
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3347
|
+
const updates = { id: conversationId, updated_at: now };
|
|
3348
|
+
if (patch.title !== void 0) updates.title = patch.title;
|
|
3349
|
+
if (patch.metadata !== void 0) updates.metadata = JSON.stringify(patch.metadata);
|
|
3350
|
+
await this.engine.update(CONVERSATIONS_OBJECT, updates, {
|
|
3351
|
+
where: { id: conversationId }
|
|
3352
|
+
});
|
|
3353
|
+
return await this.get(conversationId);
|
|
3354
|
+
}
|
|
3216
3355
|
async delete(conversationId) {
|
|
3217
3356
|
await this.engine.delete(MESSAGES_OBJECT, {
|
|
3218
3357
|
where: { conversation_id: conversationId },
|
|
@@ -3996,8 +4135,9 @@ var import_zod = require("zod");
|
|
|
3996
4135
|
|
|
3997
4136
|
// src/schema-retriever.ts
|
|
3998
4137
|
var SchemaRetriever = class {
|
|
3999
|
-
constructor(metadata, options = {}) {
|
|
4138
|
+
constructor(metadata, options = {}, protocol) {
|
|
4000
4139
|
this.metadata = metadata;
|
|
4140
|
+
this.protocol = protocol;
|
|
4001
4141
|
this.options = {
|
|
4002
4142
|
limit: options.limit ?? 3,
|
|
4003
4143
|
minScore: options.minScore ?? 1,
|
|
@@ -4014,7 +4154,19 @@ var SchemaRetriever = class {
|
|
|
4014
4154
|
async retrieve(query) {
|
|
4015
4155
|
const terms = tokenise(query);
|
|
4016
4156
|
if (terms.length === 0) return [];
|
|
4017
|
-
|
|
4157
|
+
let objects = [];
|
|
4158
|
+
if (this.protocol?.getMetaItems) {
|
|
4159
|
+
try {
|
|
4160
|
+
const fromProtocol = await this.protocol.getMetaItems({ type: "object" });
|
|
4161
|
+
const arr = Array.isArray(fromProtocol) ? fromProtocol : fromProtocol && typeof fromProtocol === "object" && Array.isArray(fromProtocol.items) ? fromProtocol.items : null;
|
|
4162
|
+
objects = arr ?? await this.metadata.listObjects();
|
|
4163
|
+
} catch {
|
|
4164
|
+
objects = await this.metadata.listObjects();
|
|
4165
|
+
}
|
|
4166
|
+
} else {
|
|
4167
|
+
objects = await this.metadata.listObjects();
|
|
4168
|
+
}
|
|
4169
|
+
if (!Array.isArray(objects)) objects = [];
|
|
4018
4170
|
const hits = [];
|
|
4019
4171
|
for (const raw of objects) {
|
|
4020
4172
|
const obj = raw;
|
|
@@ -4184,7 +4336,7 @@ var QUERY_DATA_TOOL = {
|
|
|
4184
4336
|
}
|
|
4185
4337
|
};
|
|
4186
4338
|
function createQueryDataHandler(ctx) {
|
|
4187
|
-
const retriever = new SchemaRetriever(ctx.metadata);
|
|
4339
|
+
const retriever = new SchemaRetriever(ctx.metadata, {}, ctx.protocol);
|
|
4188
4340
|
const maxLimit = ctx.maxLimit ?? 100;
|
|
4189
4341
|
return async (args, execCtx) => {
|
|
4190
4342
|
const { request } = args;
|
|
@@ -5451,16 +5603,18 @@ var AIServicePlugin = class {
|
|
|
5451
5603
|
return { adapter: new MemoryLLMAdapter(), description: "MemoryLLMAdapter (echo mode)" };
|
|
5452
5604
|
}
|
|
5453
5605
|
if (provider === "gateway") {
|
|
5454
|
-
const gatewayModel = String(values.gateway_model ?? "").trim();
|
|
5606
|
+
const gatewayModel = String(values.gateway_model ?? "").trim() || String(process.env.AI_GATEWAY_MODEL ?? "").trim();
|
|
5455
5607
|
if (!gatewayModel) return null;
|
|
5608
|
+
const gatewayApiKey = String(values.gateway_api_key ?? "").trim() || String(process.env.AI_GATEWAY_API_KEY ?? "").trim();
|
|
5456
5609
|
try {
|
|
5457
5610
|
const gatewayPkg = "@ai-sdk/gateway";
|
|
5458
|
-
const
|
|
5611
|
+
const mod = await import(
|
|
5459
5612
|
/* webpackIgnore: true */
|
|
5460
5613
|
gatewayPkg
|
|
5461
5614
|
);
|
|
5615
|
+
const gw = gatewayApiKey ? mod.createGateway({ apiKey: gatewayApiKey }) : mod.gateway;
|
|
5462
5616
|
return {
|
|
5463
|
-
adapter: new VercelLLMAdapter({ model:
|
|
5617
|
+
adapter: new VercelLLMAdapter({ model: gw(gatewayModel) }),
|
|
5464
5618
|
description: `Vercel AI Gateway (model: ${gatewayModel})`
|
|
5465
5619
|
};
|
|
5466
5620
|
} catch (err) {
|
|
@@ -5478,7 +5632,12 @@ var AIServicePlugin = class {
|
|
|
5478
5632
|
};
|
|
5479
5633
|
const spec = providerSpecs[provider];
|
|
5480
5634
|
if (!spec) return null;
|
|
5481
|
-
const apiKey = String(values[`${provider}_api_key`] ?? "").trim()
|
|
5635
|
+
const apiKey = String(values[`${provider}_api_key`] ?? "").trim() || // Fall back to the corresponding env var so operators who only
|
|
5636
|
+
// configured env credentials (and didn't paste the key into the
|
|
5637
|
+
// settings form) can still validate the connection.
|
|
5638
|
+
String(
|
|
5639
|
+
process.env[provider === "openai" ? "OPENAI_API_KEY" : provider === "anthropic" ? "ANTHROPIC_API_KEY" : "GOOGLE_GENERATIVE_AI_API_KEY"] ?? ""
|
|
5640
|
+
).trim();
|
|
5482
5641
|
if (!apiKey) return null;
|
|
5483
5642
|
const envKey = provider === "openai" ? "OPENAI_API_KEY" : provider === "anthropic" ? "ANTHROPIC_API_KEY" : "GOOGLE_GENERATIVE_AI_API_KEY";
|
|
5484
5643
|
process.env[envKey] = apiKey;
|
|
@@ -5754,6 +5913,13 @@ var AIServicePlugin = class {
|
|
|
5754
5913
|
metadataService = void 0;
|
|
5755
5914
|
}
|
|
5756
5915
|
}
|
|
5916
|
+
let protocolService;
|
|
5917
|
+
try {
|
|
5918
|
+
const p = ctx.getService("protocol");
|
|
5919
|
+
if (p && typeof p.getMetaItems === "function") protocolService = p;
|
|
5920
|
+
} catch {
|
|
5921
|
+
protocolService = void 0;
|
|
5922
|
+
}
|
|
5757
5923
|
try {
|
|
5758
5924
|
const dataEngine = ctx.getService("data");
|
|
5759
5925
|
if (dataEngine) {
|
|
@@ -5763,7 +5929,8 @@ var AIServicePlugin = class {
|
|
|
5763
5929
|
registerQueryDataTool(this.service.toolRegistry, {
|
|
5764
5930
|
ai: this.service,
|
|
5765
5931
|
metadata: metadataService,
|
|
5766
|
-
dataEngine
|
|
5932
|
+
dataEngine,
|
|
5933
|
+
protocol: protocolService
|
|
5767
5934
|
});
|
|
5768
5935
|
ctx.logger.info("[AI] query_data tool registered");
|
|
5769
5936
|
try {
|
|
@@ -5875,7 +6042,7 @@ var AIServicePlugin = class {
|
|
|
5875
6042
|
}
|
|
5876
6043
|
if (metadataService) {
|
|
5877
6044
|
try {
|
|
5878
|
-
registerMetadataTools(this.service.toolRegistry, { metadataService });
|
|
6045
|
+
registerMetadataTools(this.service.toolRegistry, { metadataService, protocol: protocolService });
|
|
5879
6046
|
ctx.logger.info("[AI] Built-in metadata tools registered");
|
|
5880
6047
|
const { METADATA_TOOL_DEFINITIONS: METADATA_TOOL_DEFINITIONS2 } = await Promise.resolve().then(() => (init_metadata_tools(), metadata_tools_exports));
|
|
5881
6048
|
for (const toolDef of METADATA_TOOL_DEFINITIONS2) {
|
|
@@ -6070,7 +6237,7 @@ var AIServicePlugin = class {
|
|
|
6070
6237
|
}
|
|
6071
6238
|
if (typeof settings.registerAction === "function") {
|
|
6072
6239
|
settings.registerAction("ai", "test_embedder", async ({ values, payload }) => {
|
|
6073
|
-
const overrides = payload
|
|
6240
|
+
const overrides = extractOverrides(payload);
|
|
6074
6241
|
const merged = { ...values ?? {}, ...overrides };
|
|
6075
6242
|
const provider = String(merged.embedder_provider ?? "none");
|
|
6076
6243
|
if (provider === "none") {
|
|
@@ -6115,10 +6282,33 @@ var AIServicePlugin = class {
|
|
|
6115
6282
|
}
|
|
6116
6283
|
if (typeof settings.registerAction === "function") {
|
|
6117
6284
|
settings.registerAction("ai", "test", async ({ values, payload }) => {
|
|
6118
|
-
const overrides = payload
|
|
6285
|
+
const overrides = extractOverrides(payload);
|
|
6119
6286
|
const merged = { ...values ?? {}, ...overrides };
|
|
6120
6287
|
const provider = String(merged.provider ?? "memory");
|
|
6121
6288
|
if (provider === "memory") {
|
|
6289
|
+
const liveName = this.service?.adapterName ?? "";
|
|
6290
|
+
if (this.service && liveName && liveName !== "memory") {
|
|
6291
|
+
const started2 = Date.now();
|
|
6292
|
+
try {
|
|
6293
|
+
const result = await this.service.chat(
|
|
6294
|
+
[{ role: "user", content: "ping" }],
|
|
6295
|
+
{ maxTokens: 8 }
|
|
6296
|
+
);
|
|
6297
|
+
const latency = Date.now() - started2;
|
|
6298
|
+
const preview = String(result?.text ?? "").slice(0, 60);
|
|
6299
|
+
return {
|
|
6300
|
+
ok: true,
|
|
6301
|
+
severity: "info",
|
|
6302
|
+
message: `Env-configured adapter "${liveName}" responded in ${latency}ms${preview ? ` \u2014 "${preview}"` : ""}.`
|
|
6303
|
+
};
|
|
6304
|
+
} catch (err) {
|
|
6305
|
+
return {
|
|
6306
|
+
ok: false,
|
|
6307
|
+
severity: "error",
|
|
6308
|
+
message: `Env-configured adapter "${liveName}" request failed: ${err?.message ?? String(err)}`
|
|
6309
|
+
};
|
|
6310
|
+
}
|
|
6311
|
+
}
|
|
6122
6312
|
return {
|
|
6123
6313
|
ok: true,
|
|
6124
6314
|
severity: "warning",
|
|
@@ -6135,7 +6325,7 @@ var AIServicePlugin = class {
|
|
|
6135
6325
|
return {
|
|
6136
6326
|
ok: false,
|
|
6137
6327
|
severity: "error",
|
|
6138
|
-
message: `Could not build adapter for provider=${provider}. Check API key and that the provider SDK package is installed.`
|
|
6328
|
+
message: `Could not build adapter for provider=${provider}. Check API key (or the corresponding env var) and that the provider SDK package is installed.`
|
|
6139
6329
|
};
|
|
6140
6330
|
}
|
|
6141
6331
|
const started = Date.now();
|
|
@@ -6152,6 +6342,15 @@ var AIServicePlugin = class {
|
|
|
6152
6342
|
message: `${built.description} responded in ${latency}ms${preview ? ` \u2014 "${preview}"` : ""}.`
|
|
6153
6343
|
};
|
|
6154
6344
|
} catch (err) {
|
|
6345
|
+
const isGwAuth = err?.name === "GatewayAuthenticationError";
|
|
6346
|
+
const keyWasProvided = provider === "gateway" && String(merged.gateway_api_key ?? process.env.AI_GATEWAY_API_KEY ?? "").trim().length > 0;
|
|
6347
|
+
if (isGwAuth && keyWasProvided) {
|
|
6348
|
+
return {
|
|
6349
|
+
ok: false,
|
|
6350
|
+
severity: "error",
|
|
6351
|
+
message: `${built.description}: API key was rejected by the AI Gateway (invalid, expired, or lacking access to model "${String(merged.gateway_model)}"). Create a new key at https://vercel.com/dashboard/ai-gateway/api-keys and re-save the settings.`
|
|
6352
|
+
};
|
|
6353
|
+
}
|
|
6155
6354
|
return {
|
|
6156
6355
|
ok: false,
|
|
6157
6356
|
severity: "error",
|
|
@@ -6166,6 +6365,14 @@ var AIServicePlugin = class {
|
|
|
6166
6365
|
this.service = void 0;
|
|
6167
6366
|
}
|
|
6168
6367
|
};
|
|
6368
|
+
function extractOverrides(payload) {
|
|
6369
|
+
if (!payload || typeof payload !== "object") return {};
|
|
6370
|
+
const p = payload;
|
|
6371
|
+
if (p.values && typeof p.values === "object" && p.values !== null) {
|
|
6372
|
+
return p.values;
|
|
6373
|
+
}
|
|
6374
|
+
return p;
|
|
6375
|
+
}
|
|
6169
6376
|
|
|
6170
6377
|
// src/index.ts
|
|
6171
6378
|
init_data_tools();
|