@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.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, 3),
11240
- repeatStop: parse(env.AGENT_REPEATED_TOOL_CALL_STOP, 5),
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 ?? 3;
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 ?? 5);
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 judgeModelKey = resolveJudgeModelKey(this.project.judge_agent_config.modelKey, modelLatticeManager);
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 'user' if omitted"),
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 ownerId = input.ownerId || trustedScope?.assistantId || (input.ownerType === "agent" ? rc.assistant_id : null) || rc.user_id;
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" : input.ownerType || "user";
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 (!(error instanceof ExecutionResultNotPendingError)) throw error;
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: "EXECUTION_RESULT_NOT_PENDING",
43061
- taskId: error.taskId,
43062
- executionResultId: error.executionResultId,
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 "user" with current user's ID
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,