@axiom-lattice/core 6.0.0 → 6.1.1
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/index.d.mts +203 -5
- package/dist/index.d.ts +203 -5
- package/dist/index.js +403 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +399 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -50,6 +50,17 @@ var ModelLattice = class extends BaseChatModel {
|
|
|
50
50
|
this.config = config;
|
|
51
51
|
this.llm = this.initChatModel(config);
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* 返回构造时使用的配置
|
|
55
|
+
*
|
|
56
|
+
* 供调用方(如 models 控制器)读取 apiKey 是否存在、以及展示元数据,
|
|
57
|
+
* 避免反射读取私有字段。
|
|
58
|
+
*
|
|
59
|
+
* @returns 构造时传入的 LLMConfig
|
|
60
|
+
*/
|
|
61
|
+
getConfig() {
|
|
62
|
+
return this.config;
|
|
63
|
+
}
|
|
53
64
|
/**
|
|
54
65
|
* 返回模型类型
|
|
55
66
|
*/
|
|
@@ -189,6 +200,9 @@ var ModelLattice = class extends BaseChatModel {
|
|
|
189
200
|
maxRetries: config.maxRetries || 2,
|
|
190
201
|
streaming: config.streaming,
|
|
191
202
|
reasoning: { effort: "none" },
|
|
203
|
+
// Responses API and Chat Completions are different paths with different
|
|
204
|
+
// request fields; an endpoint that supports only one rejects the other.
|
|
205
|
+
...config.useResponsesApi ? { useResponsesApi: true } : {},
|
|
192
206
|
apiKey: config.apiKey || process.env[config.apiKeyEnvName || "OPENAI_API_KEY"],
|
|
193
207
|
configuration: {
|
|
194
208
|
baseURL: config.baseURL
|
|
@@ -279,9 +293,74 @@ var ModelLatticeManager = class _ModelLatticeManager extends BaseLatticeManager
|
|
|
279
293
|
getLatticeKeys() {
|
|
280
294
|
return this.keys();
|
|
281
295
|
}
|
|
296
|
+
// ========== 租户维度 API ==========
|
|
297
|
+
// 键由基类拼装为 models:{tenantId}:{key}。注意 "default" 租户的键与旧版
|
|
298
|
+
// key-only API 完全一致(models:default:{key}),因此对该租户是逐字节兼容的。
|
|
299
|
+
/**
|
|
300
|
+
* 以租户维度注册模型Lattice
|
|
301
|
+
*
|
|
302
|
+
* 同名 key 采用「后写覆盖」语义:先移除再注册,避免基类重复注册时抛错。
|
|
303
|
+
*
|
|
304
|
+
* @param tenantId 租户ID
|
|
305
|
+
* @param key Lattice键名
|
|
306
|
+
* @param config 模型配置
|
|
307
|
+
*/
|
|
308
|
+
registerLatticeWithTenant(tenantId2, key5, config) {
|
|
309
|
+
const client = new ModelLattice(config);
|
|
310
|
+
const modelLattice = {
|
|
311
|
+
key: key5,
|
|
312
|
+
client
|
|
313
|
+
};
|
|
314
|
+
if (this.hasWithTenant(tenantId2, key5)) {
|
|
315
|
+
this.removeWithTenant(tenantId2, key5);
|
|
316
|
+
}
|
|
317
|
+
this.registerWithTenant(tenantId2, key5, modelLattice);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* 获取指定租户的模型Lattice
|
|
321
|
+
* @param tenantId 租户ID
|
|
322
|
+
* @param key Lattice键名
|
|
323
|
+
*/
|
|
324
|
+
getModelLatticeWithTenant(tenantId2, key5) {
|
|
325
|
+
return this.getWithTenant(tenantId2, key5);
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* 检查指定租户的模型Lattice是否存在
|
|
329
|
+
* @param tenantId 租户ID
|
|
330
|
+
* @param key Lattice键名
|
|
331
|
+
*/
|
|
332
|
+
hasLatticeWithTenant(tenantId2, key5) {
|
|
333
|
+
return this.hasWithTenant(tenantId2, key5);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* 获取指定租户的所有模型Lattice
|
|
337
|
+
* @param tenantId 租户ID
|
|
338
|
+
*/
|
|
339
|
+
getAllLatticesByTenant(tenantId2) {
|
|
340
|
+
return this.getAllByTenant(tenantId2);
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* 获取指定租户的所有模型键名
|
|
344
|
+
*
|
|
345
|
+
* 只返回键名,不构造 Lattice 对象数组,适合仅需判断存在性的调用方。
|
|
346
|
+
*
|
|
347
|
+
* @param tenantId 租户ID
|
|
348
|
+
*/
|
|
349
|
+
getLatticeKeysByTenant(tenantId2) {
|
|
350
|
+
return this.keysByTenant(tenantId2);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* 移除指定租户的模型Lattice
|
|
354
|
+
* @param tenantId 租户ID
|
|
355
|
+
* @param key Lattice键名
|
|
356
|
+
*/
|
|
357
|
+
removeLatticeWithTenant(tenantId2, key5) {
|
|
358
|
+
return this.removeWithTenant(tenantId2, key5);
|
|
359
|
+
}
|
|
282
360
|
};
|
|
283
361
|
var modelLatticeManager = ModelLatticeManager.getInstance();
|
|
284
362
|
var registerModelLattice = (key5, config) => modelLatticeManager.registerLattice(key5, config);
|
|
363
|
+
var registerModelLatticeForTenant = (tenantId2, key5, config) => modelLatticeManager.registerLatticeWithTenant(tenantId2, key5, config);
|
|
285
364
|
var getModelLattice = (key5) => modelLatticeManager.getModelLattice(key5);
|
|
286
365
|
|
|
287
366
|
// src/tool_lattice/get_current_date_time/index.ts
|
|
@@ -2013,6 +2092,240 @@ var InMemoryMcpServerConfigStore = class {
|
|
|
2013
2092
|
}
|
|
2014
2093
|
};
|
|
2015
2094
|
|
|
2095
|
+
// src/store_lattice/InMemoryModelProviderStore.ts
|
|
2096
|
+
var InMemoryModelProviderStore = class {
|
|
2097
|
+
constructor() {
|
|
2098
|
+
this.providers = /* @__PURE__ */ new Map();
|
|
2099
|
+
this.models = /* @__PURE__ */ new Map();
|
|
2100
|
+
}
|
|
2101
|
+
/**
|
|
2102
|
+
* Get composite key for providers
|
|
2103
|
+
*/
|
|
2104
|
+
getProviderKey(tenantId2, id) {
|
|
2105
|
+
return `${tenantId2}:${id}`;
|
|
2106
|
+
}
|
|
2107
|
+
/**
|
|
2108
|
+
* Get composite key for snapshot models
|
|
2109
|
+
*/
|
|
2110
|
+
getModelKey(tenantId2, providerId, modelId) {
|
|
2111
|
+
return `${tenantId2}:${providerId}:${modelId}`;
|
|
2112
|
+
}
|
|
2113
|
+
/**
|
|
2114
|
+
* Get all provider configurations for a tenant
|
|
2115
|
+
*/
|
|
2116
|
+
async listProviders(tenantId2) {
|
|
2117
|
+
return Array.from(this.providers.values()).filter(
|
|
2118
|
+
(provider) => provider.tenantId === tenantId2
|
|
2119
|
+
);
|
|
2120
|
+
}
|
|
2121
|
+
/**
|
|
2122
|
+
* Get a provider configuration by ID
|
|
2123
|
+
*/
|
|
2124
|
+
async getProviderById(tenantId2, id) {
|
|
2125
|
+
return this.providers.get(this.getProviderKey(tenantId2, id)) || null;
|
|
2126
|
+
}
|
|
2127
|
+
/**
|
|
2128
|
+
* Get a provider configuration by business name
|
|
2129
|
+
*/
|
|
2130
|
+
async getProviderByName(tenantId2, name) {
|
|
2131
|
+
const providers = await this.listProviders(tenantId2);
|
|
2132
|
+
return providers.find((provider) => provider.name === name) || null;
|
|
2133
|
+
}
|
|
2134
|
+
/**
|
|
2135
|
+
* Create a new provider configuration
|
|
2136
|
+
*/
|
|
2137
|
+
async createProvider(tenantId2, id, data) {
|
|
2138
|
+
const now = /* @__PURE__ */ new Date();
|
|
2139
|
+
const entry = {
|
|
2140
|
+
id,
|
|
2141
|
+
tenantId: tenantId2,
|
|
2142
|
+
name: data.name,
|
|
2143
|
+
displayName: data.displayName,
|
|
2144
|
+
protocol: data.protocol,
|
|
2145
|
+
apiStyle: data.apiStyle ?? "chat-completions",
|
|
2146
|
+
// Phase 1 pins the LLM provider: the UI does not offer a choice, and some
|
|
2147
|
+
// initChatModel branches hardcode their own baseURL and would silently
|
|
2148
|
+
// ignore the tenant's (see ADR-138 decision 7b).
|
|
2149
|
+
llmProvider: "openai",
|
|
2150
|
+
baseURL: data.baseURL,
|
|
2151
|
+
apiKey: data.apiKey || void 0,
|
|
2152
|
+
apiKeyHint: data.apiKey ? data.apiKey.slice(-4) : void 0,
|
|
2153
|
+
enabled: data.enabled ?? true,
|
|
2154
|
+
status: "unknown",
|
|
2155
|
+
createdAt: now,
|
|
2156
|
+
updatedAt: now
|
|
2157
|
+
};
|
|
2158
|
+
this.providers.set(this.getProviderKey(tenantId2, id), entry);
|
|
2159
|
+
return entry;
|
|
2160
|
+
}
|
|
2161
|
+
/**
|
|
2162
|
+
* Update an existing provider configuration.
|
|
2163
|
+
* An omitted or empty `apiKey` leaves the stored key untouched.
|
|
2164
|
+
*/
|
|
2165
|
+
async updateProvider(tenantId2, id, updates) {
|
|
2166
|
+
const key5 = this.getProviderKey(tenantId2, id);
|
|
2167
|
+
const existing = this.providers.get(key5);
|
|
2168
|
+
if (!existing) {
|
|
2169
|
+
return null;
|
|
2170
|
+
}
|
|
2171
|
+
const hasNewApiKey = Boolean(updates.apiKey);
|
|
2172
|
+
const clearsApiKey = updates.clearApiKey === true;
|
|
2173
|
+
const updated = {
|
|
2174
|
+
...existing,
|
|
2175
|
+
name: updates.name ?? existing.name,
|
|
2176
|
+
displayName: updates.displayName !== void 0 ? updates.displayName : existing.displayName,
|
|
2177
|
+
protocol: updates.protocol ?? existing.protocol,
|
|
2178
|
+
apiStyle: updates.apiStyle ?? existing.apiStyle,
|
|
2179
|
+
baseURL: updates.baseURL ?? existing.baseURL,
|
|
2180
|
+
apiKey: clearsApiKey ? void 0 : hasNewApiKey ? updates.apiKey : existing.apiKey,
|
|
2181
|
+
apiKeyHint: clearsApiKey ? void 0 : hasNewApiKey ? updates.apiKey?.slice(-4) : existing.apiKeyHint,
|
|
2182
|
+
enabled: updates.enabled ?? existing.enabled,
|
|
2183
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
2184
|
+
};
|
|
2185
|
+
this.providers.set(key5, updated);
|
|
2186
|
+
return updated;
|
|
2187
|
+
}
|
|
2188
|
+
/**
|
|
2189
|
+
* Delete a provider configuration and its model snapshot
|
|
2190
|
+
*/
|
|
2191
|
+
async deleteProvider(tenantId2, id) {
|
|
2192
|
+
await this.deleteModelsByProvider(tenantId2, id);
|
|
2193
|
+
return this.providers.delete(this.getProviderKey(tenantId2, id));
|
|
2194
|
+
}
|
|
2195
|
+
/**
|
|
2196
|
+
* Record the outcome of a discovery attempt
|
|
2197
|
+
*/
|
|
2198
|
+
async markProviderStatus(tenantId2, id, status, lastError, discoveredAt) {
|
|
2199
|
+
const key5 = this.getProviderKey(tenantId2, id);
|
|
2200
|
+
const existing = this.providers.get(key5);
|
|
2201
|
+
if (!existing) {
|
|
2202
|
+
return;
|
|
2203
|
+
}
|
|
2204
|
+
this.providers.set(key5, {
|
|
2205
|
+
...existing,
|
|
2206
|
+
status,
|
|
2207
|
+
lastError: status === "ok" ? void 0 : lastError,
|
|
2208
|
+
lastDiscoveredAt: discoveredAt ?? existing.lastDiscoveredAt,
|
|
2209
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
2210
|
+
});
|
|
2211
|
+
}
|
|
2212
|
+
/**
|
|
2213
|
+
* List snapshot models for a tenant
|
|
2214
|
+
*/
|
|
2215
|
+
async listModels(tenantId2, providerId) {
|
|
2216
|
+
return Array.from(this.models.values()).filter(
|
|
2217
|
+
(model) => model.tenantId === tenantId2 && (providerId === void 0 || model.providerId === providerId)
|
|
2218
|
+
);
|
|
2219
|
+
}
|
|
2220
|
+
/**
|
|
2221
|
+
* Get a single snapshot model.
|
|
2222
|
+
* Keyed by provider as well as model id, since two providers in the same
|
|
2223
|
+
* tenant may expose the same upstream model id.
|
|
2224
|
+
*/
|
|
2225
|
+
async getModel(tenantId2, providerId, modelId) {
|
|
2226
|
+
return this.models.get(this.getModelKey(tenantId2, providerId, modelId)) || null;
|
|
2227
|
+
}
|
|
2228
|
+
/**
|
|
2229
|
+
* Replace a provider's model snapshot with the result of one discovery.
|
|
2230
|
+
*
|
|
2231
|
+
* Model ids are scoped per provider, so the same upstream id may appear
|
|
2232
|
+
* under several providers in one tenant — each is an independent model.
|
|
2233
|
+
*
|
|
2234
|
+
* Models the upstream no longer offers are removed; models that survive keep
|
|
2235
|
+
* the tenant's enable/disable choice rather than being reset.
|
|
2236
|
+
*/
|
|
2237
|
+
async replaceProviderModels(tenantId2, providerId, models) {
|
|
2238
|
+
const previous = await this.listModels(tenantId2, providerId);
|
|
2239
|
+
const previousById = new Map(
|
|
2240
|
+
previous.map((model) => [model.modelId, model])
|
|
2241
|
+
);
|
|
2242
|
+
const incomingIds = new Set(models.map((model) => model.id));
|
|
2243
|
+
for (const model of previous) {
|
|
2244
|
+
if (!incomingIds.has(model.modelId)) {
|
|
2245
|
+
this.models.delete(
|
|
2246
|
+
this.getModelKey(tenantId2, providerId, model.modelId)
|
|
2247
|
+
);
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
const now = /* @__PURE__ */ new Date();
|
|
2251
|
+
const upserted = [];
|
|
2252
|
+
for (const model of models) {
|
|
2253
|
+
const existing = previousById.get(model.id);
|
|
2254
|
+
const entry = {
|
|
2255
|
+
id: `${providerId}:${model.id}`,
|
|
2256
|
+
tenantId: tenantId2,
|
|
2257
|
+
providerId,
|
|
2258
|
+
modelId: model.id,
|
|
2259
|
+
displayName: model.displayName,
|
|
2260
|
+
ownedBy: model.ownedBy,
|
|
2261
|
+
upstreamCreatedAt: model.createdAt ? new Date(model.createdAt) : void 0,
|
|
2262
|
+
// An explicit `enabled` from the caller wins; discovery omits it and
|
|
2263
|
+
// the tenant's earlier choice is preserved.
|
|
2264
|
+
enabled: model.enabled ?? existing?.enabled ?? true,
|
|
2265
|
+
// Unlike `enabled`, this is not preserved: a model present in the list
|
|
2266
|
+
// the caller just read is, by definition, no longer stale. Only an
|
|
2267
|
+
// explicit flag marks one.
|
|
2268
|
+
stale: model.stale ?? false,
|
|
2269
|
+
discoveredAt: now
|
|
2270
|
+
};
|
|
2271
|
+
this.models.set(this.getModelKey(tenantId2, providerId, model.id), entry);
|
|
2272
|
+
upserted.push(model.id);
|
|
2273
|
+
}
|
|
2274
|
+
return upserted;
|
|
2275
|
+
}
|
|
2276
|
+
/**
|
|
2277
|
+
* Enable or disable a single snapshot model
|
|
2278
|
+
*/
|
|
2279
|
+
async setModelEnabled(tenantId2, providerId, modelId, enabled) {
|
|
2280
|
+
const key5 = this.getModelKey(tenantId2, providerId, modelId);
|
|
2281
|
+
const existing = this.models.get(key5);
|
|
2282
|
+
if (!existing) {
|
|
2283
|
+
return null;
|
|
2284
|
+
}
|
|
2285
|
+
const updated = {
|
|
2286
|
+
...existing,
|
|
2287
|
+
enabled
|
|
2288
|
+
};
|
|
2289
|
+
this.models.set(key5, updated);
|
|
2290
|
+
return updated;
|
|
2291
|
+
}
|
|
2292
|
+
/**
|
|
2293
|
+
* Delete every snapshot model belonging to a provider
|
|
2294
|
+
*/
|
|
2295
|
+
async deleteModelsByProvider(tenantId2, providerId) {
|
|
2296
|
+
let deleted = 0;
|
|
2297
|
+
for (const [key5, model] of Array.from(this.models.entries())) {
|
|
2298
|
+
if (model.tenantId === tenantId2 && model.providerId === providerId) {
|
|
2299
|
+
this.models.delete(key5);
|
|
2300
|
+
deleted += 1;
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
return deleted;
|
|
2304
|
+
}
|
|
2305
|
+
/**
|
|
2306
|
+
* Clear all providers and models (useful for testing)
|
|
2307
|
+
*/
|
|
2308
|
+
clear() {
|
|
2309
|
+
this.providers.clear();
|
|
2310
|
+
this.models.clear();
|
|
2311
|
+
}
|
|
2312
|
+
/**
|
|
2313
|
+
* Clear providers and models for a specific tenant
|
|
2314
|
+
*/
|
|
2315
|
+
clearByTenant(tenantId2) {
|
|
2316
|
+
for (const [key5, provider] of Array.from(this.providers.entries())) {
|
|
2317
|
+
if (provider.tenantId === tenantId2) {
|
|
2318
|
+
this.providers.delete(key5);
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
for (const [key5, model] of Array.from(this.models.entries())) {
|
|
2322
|
+
if (model.tenantId === tenantId2) {
|
|
2323
|
+
this.models.delete(key5);
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
};
|
|
2328
|
+
|
|
2016
2329
|
// src/store_lattice/InMemoryAgentWebAppStore.ts
|
|
2017
2330
|
import { randomUUID } from "crypto";
|
|
2018
2331
|
function cloneAppearance(appearance) {
|
|
@@ -4501,6 +4814,7 @@ var defaultProjectStore = new InMemoryProjectStore(defaultCapabilityBundleCoordi
|
|
|
4501
4814
|
var defaultDatabaseConfigStore = new InMemoryDatabaseConfigStore();
|
|
4502
4815
|
var defaultMetricsServerConfigStore = new InMemoryMetricsServerConfigStore();
|
|
4503
4816
|
var defaultMcpServerConfigStore = new InMemoryMcpServerConfigStore();
|
|
4817
|
+
var defaultModelProviderStore = new InMemoryModelProviderStore();
|
|
4504
4818
|
var defaultAgentWebAppStore = new InMemoryAgentWebAppStore();
|
|
4505
4819
|
var defaultCapabilityBundleStore = new InMemoryCapabilityBundleStore(defaultProjectStore, defaultCapabilityBundleCoordinator);
|
|
4506
4820
|
var defaultProjectRoomCoordinator = new InMemoryProjectRoomCoordinator();
|
|
@@ -4522,6 +4836,7 @@ storeLatticeManager.registerLattice("default", "project", defaultProjectStore);
|
|
|
4522
4836
|
storeLatticeManager.registerLattice("default", "database", defaultDatabaseConfigStore);
|
|
4523
4837
|
storeLatticeManager.registerLattice("default", "metrics", defaultMetricsServerConfigStore);
|
|
4524
4838
|
storeLatticeManager.registerLattice("default", "mcp", defaultMcpServerConfigStore);
|
|
4839
|
+
storeLatticeManager.registerLattice("default", "modelProvider", defaultModelProviderStore);
|
|
4525
4840
|
storeLatticeManager.registerLattice("default", "agentWebApp", defaultAgentWebAppStore);
|
|
4526
4841
|
storeLatticeManager.registerLattice("default", "capabilityBundle", defaultCapabilityBundleStore);
|
|
4527
4842
|
storeLatticeManager.registerLattice("default", "projectRoom", defaultProjectRoomStore);
|
|
@@ -11236,8 +11551,8 @@ function readLoopBreakerConfig(env = process.env) {
|
|
|
11236
11551
|
return Math.floor(parsed);
|
|
11237
11552
|
};
|
|
11238
11553
|
return {
|
|
11239
|
-
repeatWarn: parse(env.AGENT_REPEATED_TOOL_CALL_WARN,
|
|
11240
|
-
repeatStop: parse(env.AGENT_REPEATED_TOOL_CALL_STOP,
|
|
11554
|
+
repeatWarn: parse(env.AGENT_REPEATED_TOOL_CALL_WARN, 20),
|
|
11555
|
+
repeatStop: parse(env.AGENT_REPEATED_TOOL_CALL_STOP, 25),
|
|
11241
11556
|
runLimit: parse(env.AGENT_TOOL_CALL_RUN_LIMIT, 300),
|
|
11242
11557
|
skillRunLimit: parse(env.AGENT_SKILL_CALL_RUN_LIMIT, 8)
|
|
11243
11558
|
};
|
|
@@ -11260,9 +11575,9 @@ var BREAKER_STATE_SCHEMA = z41.object({
|
|
|
11260
11575
|
repeatedToolCallMemberSignatures: z41.array(z41.string()).default([])
|
|
11261
11576
|
});
|
|
11262
11577
|
function createRepeatedToolCallBreakerMiddleware(options = {}) {
|
|
11263
|
-
const rawWarn = options.warnThreshold ??
|
|
11578
|
+
const rawWarn = options.warnThreshold ?? 20;
|
|
11264
11579
|
const warnThreshold = rawWarn > 0 ? Math.max(2, rawWarn) : 0;
|
|
11265
|
-
const stopThreshold = Math.max(1, options.stopThreshold ??
|
|
11580
|
+
const stopThreshold = Math.max(1, options.stopThreshold ?? 25);
|
|
11266
11581
|
return createMiddleware10({
|
|
11267
11582
|
name: "RepeatedToolCallBreaker",
|
|
11268
11583
|
stateSchema: BREAKER_STATE_SCHEMA,
|
|
@@ -34372,13 +34687,16 @@ var LatticeEvalProject = class {
|
|
|
34372
34687
|
constructor(project, onCaseComplete) {
|
|
34373
34688
|
this.suites = /* @__PURE__ */ new Map();
|
|
34374
34689
|
this.project = project;
|
|
34375
|
-
const
|
|
34690
|
+
const tenantId2 = this.project.lattice_server_config.tenant_id || "default";
|
|
34691
|
+
const judgeModelKey = resolveJudgeModelKey(
|
|
34692
|
+
this.project.judge_agent_config.modelKey,
|
|
34693
|
+
modelLatticeManager
|
|
34694
|
+
);
|
|
34376
34695
|
if (!modelLatticeManager.hasLattice(judgeModelKey)) {
|
|
34377
34696
|
throw new Error(
|
|
34378
34697
|
`Judge model "${judgeModelKey}" not found. Register it first or provide a valid modelKey.`
|
|
34379
34698
|
);
|
|
34380
34699
|
}
|
|
34381
|
-
const tenantId2 = this.project.lattice_server_config.tenant_id || "default";
|
|
34382
34700
|
this.judgeAgentKey = `${this.project.projectName}_judge_agent`;
|
|
34383
34701
|
const judgeAgentConfig = {
|
|
34384
34702
|
key: this.judgeAgentKey,
|
|
@@ -38728,6 +39046,47 @@ function clearEncryptionKeyCache() {
|
|
|
38728
39046
|
keyValidated = false;
|
|
38729
39047
|
}
|
|
38730
39048
|
|
|
39049
|
+
// src/util/safeUpstreamUrl.ts
|
|
39050
|
+
var UnsafeUpstreamUrlError = class extends Error {
|
|
39051
|
+
constructor(reason, message, statusCode = 400) {
|
|
39052
|
+
super(message);
|
|
39053
|
+
this.reason = reason;
|
|
39054
|
+
this.statusCode = statusCode;
|
|
39055
|
+
this.name = "UnsafeUpstreamUrlError";
|
|
39056
|
+
}
|
|
39057
|
+
};
|
|
39058
|
+
async function assertSafeUpstreamUrl(raw) {
|
|
39059
|
+
let url;
|
|
39060
|
+
try {
|
|
39061
|
+
url = new URL(raw);
|
|
39062
|
+
} catch {
|
|
39063
|
+
throw new UnsafeUpstreamUrlError(
|
|
39064
|
+
"INVALID_BASE_URL",
|
|
39065
|
+
"Base URL is not a valid URL"
|
|
39066
|
+
);
|
|
39067
|
+
}
|
|
39068
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
39069
|
+
throw new UnsafeUpstreamUrlError(
|
|
39070
|
+
"UNSUPPORTED_SCHEME",
|
|
39071
|
+
"Base URL must use http or https"
|
|
39072
|
+
);
|
|
39073
|
+
}
|
|
39074
|
+
if (url.username.length > 0 || url.password.length > 0) {
|
|
39075
|
+
throw new UnsafeUpstreamUrlError(
|
|
39076
|
+
"CREDENTIALS_IN_URL",
|
|
39077
|
+
"Base URL must not embed credentials; configure the API key separately"
|
|
39078
|
+
);
|
|
39079
|
+
}
|
|
39080
|
+
const hostname = url.hostname.replace(/^\[/, "").replace(/\]$/, "");
|
|
39081
|
+
if (hostname.length === 0) {
|
|
39082
|
+
throw new UnsafeUpstreamUrlError(
|
|
39083
|
+
"INVALID_BASE_URL",
|
|
39084
|
+
"Base URL must include a host"
|
|
39085
|
+
);
|
|
39086
|
+
}
|
|
39087
|
+
return { url };
|
|
39088
|
+
}
|
|
39089
|
+
|
|
38731
39090
|
// src/middlewares/skillMiddleware.ts
|
|
38732
39091
|
import { createMiddleware as createMiddleware19 } from "langchain";
|
|
38733
39092
|
|
|
@@ -41718,7 +42077,7 @@ var manageTaskSchema = z70.object({
|
|
|
41718
42077
|
parentId: z70.string().optional().describe("Parent task ID for grouping subtasks"),
|
|
41719
42078
|
sourceId: z70.string().optional().describe("Source session/thread ID"),
|
|
41720
42079
|
context: z70.record(z70.unknown()).optional().describe("Additional context data"),
|
|
41721
|
-
ownerType: z70.enum(["user", "agent"]).optional().describe("Owner type. Defaults to
|
|
42080
|
+
ownerType: z70.enum(["user", "agent"]).optional().describe("Owner type. Defaults to the runtime actor: agent runtime (no user identity) -> 'agent', user runtime -> 'user'."),
|
|
41722
42081
|
ownerId: z70.string().optional().describe("Owner ID. Auto-filled from current user/agent if omitted"),
|
|
41723
42082
|
requireReview: z70.boolean().optional().describe("If true, agent completion pauses as interrupted(review_required) for HITL approval"),
|
|
41724
42083
|
dependencies: z70.array(z70.string()).optional().describe("List of task IDs that must be completed before this task can start"),
|
|
@@ -41905,7 +42264,9 @@ function createTaskMiddleware(options = {}) {
|
|
|
41905
42264
|
return projectPolicyError(error);
|
|
41906
42265
|
}
|
|
41907
42266
|
}
|
|
41908
|
-
const
|
|
42267
|
+
const runtimeOwnerType = rc.user_id ? "user" : rc.assistant_id ? "agent" : "user";
|
|
42268
|
+
const requestedOwnerType = input.ownerType ?? runtimeOwnerType;
|
|
42269
|
+
const ownerId = input.ownerId || trustedScope?.assistantId || (requestedOwnerType === "agent" ? rc.assistant_id : null) || rc.user_id;
|
|
41909
42270
|
const store = getTaskStore();
|
|
41910
42271
|
const deleteOneTask = async (id) => {
|
|
41911
42272
|
if (delegatedTaskId && id !== delegatedTaskId) {
|
|
@@ -41974,7 +42335,7 @@ function createTaskMiddleware(options = {}) {
|
|
|
41974
42335
|
createScopeProjectId = createScopeProjectId ?? parentTask.projectId;
|
|
41975
42336
|
}
|
|
41976
42337
|
}
|
|
41977
|
-
const effectiveOwnerType = delegatedTaskId ? "agent" : trustedProject ? "agent" :
|
|
42338
|
+
const effectiveOwnerType = delegatedTaskId ? "agent" : trustedProject ? "agent" : requestedOwnerType;
|
|
41978
42339
|
const effectiveOwnerId = delegatedTaskId ? rc.assistant_id : ownerId;
|
|
41979
42340
|
if (delegatedTaskId && !effectiveOwnerId) {
|
|
41980
42341
|
return delegatedTaskScopeError(delegatedTaskId);
|
|
@@ -42000,6 +42361,14 @@ function createTaskMiddleware(options = {}) {
|
|
|
42000
42361
|
}
|
|
42001
42362
|
}
|
|
42002
42363
|
}
|
|
42364
|
+
if (!delegatedTaskId && (typeof effectiveOwnerId !== "string" || effectiveOwnerId.length === 0)) {
|
|
42365
|
+
return JSON.stringify({
|
|
42366
|
+
success: false,
|
|
42367
|
+
code: "TASK_OWNER_REQUIRED",
|
|
42368
|
+
error: "Cannot resolve task owner: no user or agent identity in this run.",
|
|
42369
|
+
hint: 'Provide an explicit ownerId, or retry with ownerType:"agent" if this run has an agent identity.'
|
|
42370
|
+
});
|
|
42371
|
+
}
|
|
42003
42372
|
if (effectiveOwnerType === "agent" && (input.result !== void 0 || input.failureReason !== void 0)) {
|
|
42004
42373
|
return JSON.stringify({
|
|
42005
42374
|
success: false,
|
|
@@ -43054,13 +43423,22 @@ function createTaskMiddleware(options = {}) {
|
|
|
43054
43423
|
try {
|
|
43055
43424
|
response = await handleManageTaskAction(input, config, validateExecutionResult, markMutation);
|
|
43056
43425
|
} catch (error) {
|
|
43057
|
-
if (
|
|
43426
|
+
if (error instanceof GraphInterrupt3) throw error;
|
|
43427
|
+
if (error instanceof ExecutionResultNotPendingError) {
|
|
43428
|
+
return JSON.stringify({
|
|
43429
|
+
success: false,
|
|
43430
|
+
code: "EXECUTION_RESULT_NOT_PENDING",
|
|
43431
|
+
taskId: error.taskId,
|
|
43432
|
+
executionResultId: error.executionResultId,
|
|
43433
|
+
error: error.message
|
|
43434
|
+
});
|
|
43435
|
+
}
|
|
43436
|
+
if (input.executionResultId) throw error;
|
|
43058
43437
|
return JSON.stringify({
|
|
43059
43438
|
success: false,
|
|
43060
|
-
code: "
|
|
43061
|
-
|
|
43062
|
-
|
|
43063
|
-
error: error.message
|
|
43439
|
+
code: "TASK_ACTION_FAILED",
|
|
43440
|
+
error: error instanceof Error ? error.message : String(error),
|
|
43441
|
+
hint: "The action did not complete. Fix the input or retry; do not repeat the identical call."
|
|
43064
43442
|
});
|
|
43065
43443
|
}
|
|
43066
43444
|
return reconcileExplicitExecutionResult(
|
|
@@ -43226,8 +43604,8 @@ changes only when acceptance criteria are truly met.
|
|
|
43226
43604
|
${TASK_CONVERGENCE_GUIDANCE}
|
|
43227
43605
|
|
|
43228
43606
|
### Ownership defaults
|
|
43229
|
-
- No params: ownerType defaults to
|
|
43230
|
-
- ownerType="agent": auto-fills ownerId from current agent (subtask for yourself)
|
|
43607
|
+
- No params: ownerType defaults to the runtime actor (user runtime -> current user's ID; agent runtime -> current agent's ID)
|
|
43608
|
+
- ownerType="agent": auto-fills ownerId from the current agent (subtask for yourself)
|
|
43231
43609
|
- Explicit ownerId: assign to a specific agent or user`;
|
|
43232
43610
|
const boundTaskId = request.state?.taskId;
|
|
43233
43611
|
const binding = typeof boundTaskId === "string" && boundTaskId ? renderTaskBinding(boundTaskId) : "";
|
|
@@ -43246,7 +43624,7 @@ ${TASK_CONVERGENCE_GUIDANCE}
|
|
|
43246
43624
|
description: `Manage persistent tasks and their activity timelines for user and agent tasks.
|
|
43247
43625
|
|
|
43248
43626
|
## Owner defaults
|
|
43249
|
-
- No ownerType/ownerId: auto-assigned to current user
|
|
43627
|
+
- No ownerType/ownerId: auto-assigned to the runtime actor (user runtime -> current user; agent runtime -> current agent)
|
|
43250
43628
|
- ownerType="agent" without ownerId: auto-assigned to current agent
|
|
43251
43629
|
- Explicit ownerId: assign to a specific agent (cross-agent delegation)
|
|
43252
43630
|
|
|
@@ -46143,6 +46521,7 @@ export {
|
|
|
46143
46521
|
InMemoryDatabaseConfigStore,
|
|
46144
46522
|
InMemoryMailboxStore,
|
|
46145
46523
|
InMemoryMenuStore,
|
|
46524
|
+
InMemoryModelProviderStore,
|
|
46146
46525
|
InMemoryOpenAuditStore,
|
|
46147
46526
|
InMemoryProjectBotMembershipStore,
|
|
46148
46527
|
InMemoryProjectMembershipStore,
|
|
@@ -46236,6 +46615,7 @@ export {
|
|
|
46236
46615
|
ThreadStatus2 as ThreadStatus,
|
|
46237
46616
|
TokenCache,
|
|
46238
46617
|
ToolLatticeManager,
|
|
46618
|
+
UnsafeUpstreamUrlError,
|
|
46239
46619
|
VectorStoreLatticeManager,
|
|
46240
46620
|
VectorStoreProviderManager,
|
|
46241
46621
|
VolumeFilesystem,
|
|
@@ -46244,6 +46624,7 @@ export {
|
|
|
46244
46624
|
agentLatticeManager,
|
|
46245
46625
|
appendReconciliationWarning,
|
|
46246
46626
|
appendUiFence,
|
|
46627
|
+
assertSafeUpstreamUrl,
|
|
46247
46628
|
buildGrepResultsDict,
|
|
46248
46629
|
buildInput,
|
|
46249
46630
|
buildNamedVolumeName,
|
|
@@ -46426,6 +46807,7 @@ export {
|
|
|
46426
46807
|
registerExistingToolWithTenant,
|
|
46427
46808
|
registerLoggerLattice,
|
|
46428
46809
|
registerModelLattice,
|
|
46810
|
+
registerModelLatticeForTenant,
|
|
46429
46811
|
registerQueueLattice,
|
|
46430
46812
|
registerSTTModelLattice,
|
|
46431
46813
|
registerSandboxProviderType,
|