@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.js
CHANGED
|
@@ -754,7 +754,20 @@ function createDeleteFieldHandler(ctx) {
|
|
|
754
754
|
function createListObjectsHandler(ctx) {
|
|
755
755
|
return async (args) => {
|
|
756
756
|
const { filter, includeFields } = args ?? {};
|
|
757
|
-
|
|
757
|
+
let objects = [];
|
|
758
|
+
if (ctx.protocol?.getMetaItems) {
|
|
759
|
+
try {
|
|
760
|
+
const fromProtocol = await ctx.protocol.getMetaItems({ type: "object" });
|
|
761
|
+
const arr = Array.isArray(fromProtocol) ? fromProtocol : fromProtocol && typeof fromProtocol === "object" && Array.isArray(fromProtocol.items) ? fromProtocol.items : null;
|
|
762
|
+
objects = arr ?? await ctx.metadataService.listObjects();
|
|
763
|
+
} catch {
|
|
764
|
+
objects = await ctx.metadataService.listObjects();
|
|
765
|
+
}
|
|
766
|
+
} else {
|
|
767
|
+
objects = await ctx.metadataService.listObjects();
|
|
768
|
+
}
|
|
769
|
+
if (!Array.isArray(objects)) objects = [];
|
|
770
|
+
if (!Array.isArray(objects)) objects = [];
|
|
758
771
|
let result = objects.map((o) => {
|
|
759
772
|
const base = {
|
|
760
773
|
name: o.name,
|
|
@@ -791,7 +804,15 @@ function createDescribeObjectHandler(ctx) {
|
|
|
791
804
|
if (!isSnakeCase(objectName)) {
|
|
792
805
|
return JSON.stringify({ error: `Invalid object name "${objectName}". Must be snake_case.` });
|
|
793
806
|
}
|
|
794
|
-
|
|
807
|
+
let objectDef = await ctx.metadataService.getObject(objectName);
|
|
808
|
+
if (!objectDef && ctx.protocol?.getMetaItems) {
|
|
809
|
+
try {
|
|
810
|
+
const all = await ctx.protocol.getMetaItems({ type: "object" });
|
|
811
|
+
const arr = Array.isArray(all) ? all : all && typeof all === "object" && Array.isArray(all.items) ? all.items : [];
|
|
812
|
+
objectDef = arr.find((o) => o?.name === objectName);
|
|
813
|
+
} catch {
|
|
814
|
+
}
|
|
815
|
+
}
|
|
795
816
|
if (!objectDef) {
|
|
796
817
|
return JSON.stringify({ error: `Object "${objectName}" not found` });
|
|
797
818
|
}
|
|
@@ -1329,6 +1350,16 @@ var InMemoryConversationService = class {
|
|
|
1329
1350
|
conversation.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1330
1351
|
return conversation;
|
|
1331
1352
|
}
|
|
1353
|
+
async update(conversationId, patch) {
|
|
1354
|
+
const conversation = this.store.get(conversationId);
|
|
1355
|
+
if (!conversation) {
|
|
1356
|
+
throw new Error(`Conversation "${conversationId}" not found`);
|
|
1357
|
+
}
|
|
1358
|
+
if (patch.title !== void 0) conversation.title = patch.title;
|
|
1359
|
+
if (patch.metadata !== void 0) conversation.metadata = patch.metadata;
|
|
1360
|
+
conversation.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1361
|
+
return conversation;
|
|
1362
|
+
}
|
|
1332
1363
|
async delete(conversationId) {
|
|
1333
1364
|
this.store.delete(conversationId);
|
|
1334
1365
|
}
|
|
@@ -1456,6 +1487,30 @@ var _AIService = class _AIService {
|
|
|
1456
1487
|
this.logger.info(`[AI] LLM adapter swapped: ${prev} \u2192 ${next.name}`);
|
|
1457
1488
|
}
|
|
1458
1489
|
}
|
|
1490
|
+
/**
|
|
1491
|
+
* Best-effort auto-creation of a conversation when the caller did not
|
|
1492
|
+
* supply one but did supply an actor we can attribute the chat to.
|
|
1493
|
+
* Returns the new id on success, or `undefined` if creation failed (in
|
|
1494
|
+
* which case we silently fall back to non-persisted chat).
|
|
1495
|
+
*/
|
|
1496
|
+
async autoCreateConversation(ctx) {
|
|
1497
|
+
const actorId = ctx?.actor?.id;
|
|
1498
|
+
if (!actorId) return void 0;
|
|
1499
|
+
try {
|
|
1500
|
+
const conv = await this.conversationService.create({
|
|
1501
|
+
userId: actorId,
|
|
1502
|
+
metadata: ctx?.environmentId ? { environmentId: ctx.environmentId } : void 0
|
|
1503
|
+
});
|
|
1504
|
+
this.logger.debug("[AI] auto-created conversation", { conversationId: conv.id, actorId });
|
|
1505
|
+
return conv.id;
|
|
1506
|
+
} catch (err) {
|
|
1507
|
+
this.logger.warn("[AI] auto-create conversation failed", {
|
|
1508
|
+
actorId,
|
|
1509
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1510
|
+
});
|
|
1511
|
+
return void 0;
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1459
1514
|
/**
|
|
1460
1515
|
* Best-effort persistence of a single chat message to the conversation
|
|
1461
1516
|
* store. Failures are logged at warn level and swallowed — chat requests
|
|
@@ -1594,7 +1649,12 @@ var _AIService = class _AIService {
|
|
|
1594
1649
|
} = options ?? {};
|
|
1595
1650
|
const maxIterations = maxIter ?? _AIService.DEFAULT_MAX_ITERATIONS;
|
|
1596
1651
|
const registeredTools = this.toolRegistry.getAll();
|
|
1597
|
-
|
|
1652
|
+
let conversationId = toolExecutionContext?.conversationId;
|
|
1653
|
+
let autoCreatedConversationId;
|
|
1654
|
+
if (!conversationId) {
|
|
1655
|
+
autoCreatedConversationId = await this.autoCreateConversation(toolExecutionContext);
|
|
1656
|
+
conversationId = autoCreatedConversationId;
|
|
1657
|
+
}
|
|
1598
1658
|
const mergedTools = [
|
|
1599
1659
|
...registeredTools,
|
|
1600
1660
|
...restOptions.tools ?? []
|
|
@@ -1628,7 +1688,7 @@ var _AIService = class _AIService {
|
|
|
1628
1688
|
content: result.content
|
|
1629
1689
|
});
|
|
1630
1690
|
}
|
|
1631
|
-
return result;
|
|
1691
|
+
return autoCreatedConversationId ? { ...result, conversationId: autoCreatedConversationId } : result;
|
|
1632
1692
|
}
|
|
1633
1693
|
this.logger.debug("[AI] chatWithTools tool calls", {
|
|
1634
1694
|
iteration,
|
|
@@ -1695,7 +1755,7 @@ var _AIService = class _AIService {
|
|
|
1695
1755
|
content: finalResult.content
|
|
1696
1756
|
});
|
|
1697
1757
|
}
|
|
1698
|
-
return finalResult;
|
|
1758
|
+
return autoCreatedConversationId ? { ...finalResult, conversationId: autoCreatedConversationId } : finalResult;
|
|
1699
1759
|
}
|
|
1700
1760
|
/**
|
|
1701
1761
|
* Stream chat with automatic tool call resolution.
|
|
@@ -1713,7 +1773,12 @@ var _AIService = class _AIService {
|
|
|
1713
1773
|
} = options ?? {};
|
|
1714
1774
|
const maxIterations = maxIter ?? _AIService.DEFAULT_MAX_ITERATIONS;
|
|
1715
1775
|
const registeredTools = this.toolRegistry.getAll();
|
|
1716
|
-
|
|
1776
|
+
let conversationId = toolExecutionContext?.conversationId;
|
|
1777
|
+
let autoCreatedConversationId;
|
|
1778
|
+
if (!conversationId) {
|
|
1779
|
+
autoCreatedConversationId = await this.autoCreateConversation(toolExecutionContext);
|
|
1780
|
+
conversationId = autoCreatedConversationId;
|
|
1781
|
+
}
|
|
1717
1782
|
const mergedTools = [
|
|
1718
1783
|
...registeredTools,
|
|
1719
1784
|
...restOptions.tools ?? []
|
|
@@ -1725,6 +1790,14 @@ var _AIService = class _AIService {
|
|
|
1725
1790
|
};
|
|
1726
1791
|
const conversation = [...messages];
|
|
1727
1792
|
let abortedByCallback = false;
|
|
1793
|
+
if (autoCreatedConversationId) {
|
|
1794
|
+
yield {
|
|
1795
|
+
type: "tool-call",
|
|
1796
|
+
toolCallId: "__conversation_meta__",
|
|
1797
|
+
toolName: "__conversation_meta__",
|
|
1798
|
+
input: { conversationId: autoCreatedConversationId }
|
|
1799
|
+
};
|
|
1800
|
+
}
|
|
1728
1801
|
if (conversationId && messages.length > 0) {
|
|
1729
1802
|
const last = messages[messages.length - 1];
|
|
1730
1803
|
if (last && last.role === "user") {
|
|
@@ -2376,6 +2449,56 @@ function buildAIRoutes(aiService, conversationService, logger) {
|
|
|
2376
2449
|
}
|
|
2377
2450
|
}
|
|
2378
2451
|
},
|
|
2452
|
+
{
|
|
2453
|
+
method: "PATCH",
|
|
2454
|
+
path: "/api/v1/ai/conversations/:id",
|
|
2455
|
+
description: "Update mutable conversation fields (title, metadata)",
|
|
2456
|
+
auth: true,
|
|
2457
|
+
permissions: ["ai:conversations"],
|
|
2458
|
+
handler: async (req) => {
|
|
2459
|
+
const id = req.params?.id;
|
|
2460
|
+
if (!id) {
|
|
2461
|
+
return { status: 400, body: { error: "conversation id is required" } };
|
|
2462
|
+
}
|
|
2463
|
+
const body = req.body ?? {};
|
|
2464
|
+
const patch = {};
|
|
2465
|
+
if (body.title !== void 0) {
|
|
2466
|
+
if (typeof body.title !== "string") {
|
|
2467
|
+
return { status: 400, body: { error: "title must be a string" } };
|
|
2468
|
+
}
|
|
2469
|
+
patch.title = body.title;
|
|
2470
|
+
}
|
|
2471
|
+
if (body.metadata !== void 0) {
|
|
2472
|
+
if (typeof body.metadata !== "object" || body.metadata === null || Array.isArray(body.metadata)) {
|
|
2473
|
+
return { status: 400, body: { error: "metadata must be an object" } };
|
|
2474
|
+
}
|
|
2475
|
+
patch.metadata = body.metadata;
|
|
2476
|
+
}
|
|
2477
|
+
if (patch.title === void 0 && patch.metadata === void 0) {
|
|
2478
|
+
return { status: 400, body: { error: "at least one of title or metadata is required" } };
|
|
2479
|
+
}
|
|
2480
|
+
try {
|
|
2481
|
+
if (req.user?.userId) {
|
|
2482
|
+
const existing = await conversationService.get(id);
|
|
2483
|
+
if (!existing) {
|
|
2484
|
+
return { status: 404, body: { error: `Conversation "${id}" not found` } };
|
|
2485
|
+
}
|
|
2486
|
+
if (existing.userId && existing.userId !== req.user.userId) {
|
|
2487
|
+
return { status: 403, body: { error: "You do not have access to this conversation" } };
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
const conversation = await conversationService.update(id, patch);
|
|
2491
|
+
return { status: 200, body: conversation };
|
|
2492
|
+
} catch (err) {
|
|
2493
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2494
|
+
if (msg.includes("not found")) {
|
|
2495
|
+
return { status: 404, body: { error: msg } };
|
|
2496
|
+
}
|
|
2497
|
+
logger.error("[AI Route] PATCH /conversations/:id error", err instanceof Error ? err : void 0);
|
|
2498
|
+
return { status: 500, body: { error: "Internal AI service error" } };
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
},
|
|
2379
2502
|
{
|
|
2380
2503
|
method: "DELETE",
|
|
2381
2504
|
path: "/api/v1/ai/conversations/:id",
|
|
@@ -3139,6 +3262,22 @@ var ObjectQLConversationService = class {
|
|
|
3139
3262
|
});
|
|
3140
3263
|
return await this.get(conversationId);
|
|
3141
3264
|
}
|
|
3265
|
+
async update(conversationId, patch) {
|
|
3266
|
+
const row = await this.engine.findOne(CONVERSATIONS_OBJECT, {
|
|
3267
|
+
where: { id: conversationId }
|
|
3268
|
+
});
|
|
3269
|
+
if (!row) {
|
|
3270
|
+
throw new Error(`Conversation "${conversationId}" not found`);
|
|
3271
|
+
}
|
|
3272
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3273
|
+
const updates = { id: conversationId, updated_at: now };
|
|
3274
|
+
if (patch.title !== void 0) updates.title = patch.title;
|
|
3275
|
+
if (patch.metadata !== void 0) updates.metadata = JSON.stringify(patch.metadata);
|
|
3276
|
+
await this.engine.update(CONVERSATIONS_OBJECT, updates, {
|
|
3277
|
+
where: { id: conversationId }
|
|
3278
|
+
});
|
|
3279
|
+
return await this.get(conversationId);
|
|
3280
|
+
}
|
|
3142
3281
|
async delete(conversationId) {
|
|
3143
3282
|
await this.engine.delete(MESSAGES_OBJECT, {
|
|
3144
3283
|
where: { conversation_id: conversationId },
|
|
@@ -3922,8 +4061,9 @@ import { z } from "zod";
|
|
|
3922
4061
|
|
|
3923
4062
|
// src/schema-retriever.ts
|
|
3924
4063
|
var SchemaRetriever = class {
|
|
3925
|
-
constructor(metadata, options = {}) {
|
|
4064
|
+
constructor(metadata, options = {}, protocol) {
|
|
3926
4065
|
this.metadata = metadata;
|
|
4066
|
+
this.protocol = protocol;
|
|
3927
4067
|
this.options = {
|
|
3928
4068
|
limit: options.limit ?? 3,
|
|
3929
4069
|
minScore: options.minScore ?? 1,
|
|
@@ -3940,7 +4080,19 @@ var SchemaRetriever = class {
|
|
|
3940
4080
|
async retrieve(query) {
|
|
3941
4081
|
const terms = tokenise(query);
|
|
3942
4082
|
if (terms.length === 0) return [];
|
|
3943
|
-
|
|
4083
|
+
let objects = [];
|
|
4084
|
+
if (this.protocol?.getMetaItems) {
|
|
4085
|
+
try {
|
|
4086
|
+
const fromProtocol = await this.protocol.getMetaItems({ type: "object" });
|
|
4087
|
+
const arr = Array.isArray(fromProtocol) ? fromProtocol : fromProtocol && typeof fromProtocol === "object" && Array.isArray(fromProtocol.items) ? fromProtocol.items : null;
|
|
4088
|
+
objects = arr ?? await this.metadata.listObjects();
|
|
4089
|
+
} catch {
|
|
4090
|
+
objects = await this.metadata.listObjects();
|
|
4091
|
+
}
|
|
4092
|
+
} else {
|
|
4093
|
+
objects = await this.metadata.listObjects();
|
|
4094
|
+
}
|
|
4095
|
+
if (!Array.isArray(objects)) objects = [];
|
|
3944
4096
|
const hits = [];
|
|
3945
4097
|
for (const raw of objects) {
|
|
3946
4098
|
const obj = raw;
|
|
@@ -4110,7 +4262,7 @@ var QUERY_DATA_TOOL = {
|
|
|
4110
4262
|
}
|
|
4111
4263
|
};
|
|
4112
4264
|
function createQueryDataHandler(ctx) {
|
|
4113
|
-
const retriever = new SchemaRetriever(ctx.metadata);
|
|
4265
|
+
const retriever = new SchemaRetriever(ctx.metadata, {}, ctx.protocol);
|
|
4114
4266
|
const maxLimit = ctx.maxLimit ?? 100;
|
|
4115
4267
|
return async (args, execCtx) => {
|
|
4116
4268
|
const { request } = args;
|
|
@@ -5377,16 +5529,18 @@ var AIServicePlugin = class {
|
|
|
5377
5529
|
return { adapter: new MemoryLLMAdapter(), description: "MemoryLLMAdapter (echo mode)" };
|
|
5378
5530
|
}
|
|
5379
5531
|
if (provider === "gateway") {
|
|
5380
|
-
const gatewayModel = String(values.gateway_model ?? "").trim();
|
|
5532
|
+
const gatewayModel = String(values.gateway_model ?? "").trim() || String(process.env.AI_GATEWAY_MODEL ?? "").trim();
|
|
5381
5533
|
if (!gatewayModel) return null;
|
|
5534
|
+
const gatewayApiKey = String(values.gateway_api_key ?? "").trim() || String(process.env.AI_GATEWAY_API_KEY ?? "").trim();
|
|
5382
5535
|
try {
|
|
5383
5536
|
const gatewayPkg = "@ai-sdk/gateway";
|
|
5384
|
-
const
|
|
5537
|
+
const mod = await import(
|
|
5385
5538
|
/* webpackIgnore: true */
|
|
5386
5539
|
gatewayPkg
|
|
5387
5540
|
);
|
|
5541
|
+
const gw = gatewayApiKey ? mod.createGateway({ apiKey: gatewayApiKey }) : mod.gateway;
|
|
5388
5542
|
return {
|
|
5389
|
-
adapter: new VercelLLMAdapter({ model:
|
|
5543
|
+
adapter: new VercelLLMAdapter({ model: gw(gatewayModel) }),
|
|
5390
5544
|
description: `Vercel AI Gateway (model: ${gatewayModel})`
|
|
5391
5545
|
};
|
|
5392
5546
|
} catch (err) {
|
|
@@ -5404,7 +5558,12 @@ var AIServicePlugin = class {
|
|
|
5404
5558
|
};
|
|
5405
5559
|
const spec = providerSpecs[provider];
|
|
5406
5560
|
if (!spec) return null;
|
|
5407
|
-
const apiKey = String(values[`${provider}_api_key`] ?? "").trim()
|
|
5561
|
+
const apiKey = String(values[`${provider}_api_key`] ?? "").trim() || // Fall back to the corresponding env var so operators who only
|
|
5562
|
+
// configured env credentials (and didn't paste the key into the
|
|
5563
|
+
// settings form) can still validate the connection.
|
|
5564
|
+
String(
|
|
5565
|
+
process.env[provider === "openai" ? "OPENAI_API_KEY" : provider === "anthropic" ? "ANTHROPIC_API_KEY" : "GOOGLE_GENERATIVE_AI_API_KEY"] ?? ""
|
|
5566
|
+
).trim();
|
|
5408
5567
|
if (!apiKey) return null;
|
|
5409
5568
|
const envKey = provider === "openai" ? "OPENAI_API_KEY" : provider === "anthropic" ? "ANTHROPIC_API_KEY" : "GOOGLE_GENERATIVE_AI_API_KEY";
|
|
5410
5569
|
process.env[envKey] = apiKey;
|
|
@@ -5680,6 +5839,13 @@ var AIServicePlugin = class {
|
|
|
5680
5839
|
metadataService = void 0;
|
|
5681
5840
|
}
|
|
5682
5841
|
}
|
|
5842
|
+
let protocolService;
|
|
5843
|
+
try {
|
|
5844
|
+
const p = ctx.getService("protocol");
|
|
5845
|
+
if (p && typeof p.getMetaItems === "function") protocolService = p;
|
|
5846
|
+
} catch {
|
|
5847
|
+
protocolService = void 0;
|
|
5848
|
+
}
|
|
5683
5849
|
try {
|
|
5684
5850
|
const dataEngine = ctx.getService("data");
|
|
5685
5851
|
if (dataEngine) {
|
|
@@ -5689,7 +5855,8 @@ var AIServicePlugin = class {
|
|
|
5689
5855
|
registerQueryDataTool(this.service.toolRegistry, {
|
|
5690
5856
|
ai: this.service,
|
|
5691
5857
|
metadata: metadataService,
|
|
5692
|
-
dataEngine
|
|
5858
|
+
dataEngine,
|
|
5859
|
+
protocol: protocolService
|
|
5693
5860
|
});
|
|
5694
5861
|
ctx.logger.info("[AI] query_data tool registered");
|
|
5695
5862
|
try {
|
|
@@ -5801,7 +5968,7 @@ var AIServicePlugin = class {
|
|
|
5801
5968
|
}
|
|
5802
5969
|
if (metadataService) {
|
|
5803
5970
|
try {
|
|
5804
|
-
registerMetadataTools(this.service.toolRegistry, { metadataService });
|
|
5971
|
+
registerMetadataTools(this.service.toolRegistry, { metadataService, protocol: protocolService });
|
|
5805
5972
|
ctx.logger.info("[AI] Built-in metadata tools registered");
|
|
5806
5973
|
const { METADATA_TOOL_DEFINITIONS: METADATA_TOOL_DEFINITIONS2 } = await Promise.resolve().then(() => (init_metadata_tools(), metadata_tools_exports));
|
|
5807
5974
|
for (const toolDef of METADATA_TOOL_DEFINITIONS2) {
|
|
@@ -5996,7 +6163,7 @@ var AIServicePlugin = class {
|
|
|
5996
6163
|
}
|
|
5997
6164
|
if (typeof settings.registerAction === "function") {
|
|
5998
6165
|
settings.registerAction("ai", "test_embedder", async ({ values, payload }) => {
|
|
5999
|
-
const overrides = payload
|
|
6166
|
+
const overrides = extractOverrides(payload);
|
|
6000
6167
|
const merged = { ...values ?? {}, ...overrides };
|
|
6001
6168
|
const provider = String(merged.embedder_provider ?? "none");
|
|
6002
6169
|
if (provider === "none") {
|
|
@@ -6041,10 +6208,33 @@ var AIServicePlugin = class {
|
|
|
6041
6208
|
}
|
|
6042
6209
|
if (typeof settings.registerAction === "function") {
|
|
6043
6210
|
settings.registerAction("ai", "test", async ({ values, payload }) => {
|
|
6044
|
-
const overrides = payload
|
|
6211
|
+
const overrides = extractOverrides(payload);
|
|
6045
6212
|
const merged = { ...values ?? {}, ...overrides };
|
|
6046
6213
|
const provider = String(merged.provider ?? "memory");
|
|
6047
6214
|
if (provider === "memory") {
|
|
6215
|
+
const liveName = this.service?.adapterName ?? "";
|
|
6216
|
+
if (this.service && liveName && liveName !== "memory") {
|
|
6217
|
+
const started2 = Date.now();
|
|
6218
|
+
try {
|
|
6219
|
+
const result = await this.service.chat(
|
|
6220
|
+
[{ role: "user", content: "ping" }],
|
|
6221
|
+
{ maxTokens: 8 }
|
|
6222
|
+
);
|
|
6223
|
+
const latency = Date.now() - started2;
|
|
6224
|
+
const preview = String(result?.text ?? "").slice(0, 60);
|
|
6225
|
+
return {
|
|
6226
|
+
ok: true,
|
|
6227
|
+
severity: "info",
|
|
6228
|
+
message: `Env-configured adapter "${liveName}" responded in ${latency}ms${preview ? ` \u2014 "${preview}"` : ""}.`
|
|
6229
|
+
};
|
|
6230
|
+
} catch (err) {
|
|
6231
|
+
return {
|
|
6232
|
+
ok: false,
|
|
6233
|
+
severity: "error",
|
|
6234
|
+
message: `Env-configured adapter "${liveName}" request failed: ${err?.message ?? String(err)}`
|
|
6235
|
+
};
|
|
6236
|
+
}
|
|
6237
|
+
}
|
|
6048
6238
|
return {
|
|
6049
6239
|
ok: true,
|
|
6050
6240
|
severity: "warning",
|
|
@@ -6061,7 +6251,7 @@ var AIServicePlugin = class {
|
|
|
6061
6251
|
return {
|
|
6062
6252
|
ok: false,
|
|
6063
6253
|
severity: "error",
|
|
6064
|
-
message: `Could not build adapter for provider=${provider}. Check API key and that the provider SDK package is installed.`
|
|
6254
|
+
message: `Could not build adapter for provider=${provider}. Check API key (or the corresponding env var) and that the provider SDK package is installed.`
|
|
6065
6255
|
};
|
|
6066
6256
|
}
|
|
6067
6257
|
const started = Date.now();
|
|
@@ -6078,6 +6268,15 @@ var AIServicePlugin = class {
|
|
|
6078
6268
|
message: `${built.description} responded in ${latency}ms${preview ? ` \u2014 "${preview}"` : ""}.`
|
|
6079
6269
|
};
|
|
6080
6270
|
} catch (err) {
|
|
6271
|
+
const isGwAuth = err?.name === "GatewayAuthenticationError";
|
|
6272
|
+
const keyWasProvided = provider === "gateway" && String(merged.gateway_api_key ?? process.env.AI_GATEWAY_API_KEY ?? "").trim().length > 0;
|
|
6273
|
+
if (isGwAuth && keyWasProvided) {
|
|
6274
|
+
return {
|
|
6275
|
+
ok: false,
|
|
6276
|
+
severity: "error",
|
|
6277
|
+
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.`
|
|
6278
|
+
};
|
|
6279
|
+
}
|
|
6081
6280
|
return {
|
|
6082
6281
|
ok: false,
|
|
6083
6282
|
severity: "error",
|
|
@@ -6092,6 +6291,14 @@ var AIServicePlugin = class {
|
|
|
6092
6291
|
this.service = void 0;
|
|
6093
6292
|
}
|
|
6094
6293
|
};
|
|
6294
|
+
function extractOverrides(payload) {
|
|
6295
|
+
if (!payload || typeof payload !== "object") return {};
|
|
6296
|
+
const p = payload;
|
|
6297
|
+
if (p.values && typeof p.values === "object" && p.values !== null) {
|
|
6298
|
+
return p.values;
|
|
6299
|
+
}
|
|
6300
|
+
return p;
|
|
6301
|
+
}
|
|
6095
6302
|
|
|
6096
6303
|
// src/index.ts
|
|
6097
6304
|
init_data_tools();
|