@axiom-lattice/gateway 4.7.0 → 4.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/dist/{OrphanRecoveryRuntime-MQDEJX3M.mjs → OrphanRecoveryRuntime-BEFILJMU.mjs} +2 -2
- package/dist/{chunk-2POW27EI.mjs → chunk-7CG57LEF.mjs} +2 -2
- package/dist/{chunk-WKNZ7GBC.mjs → chunk-EXPERMZR.mjs} +1 -1
- package/dist/chunk-EXPERMZR.mjs.map +1 -0
- package/dist/{chunk-52SUWMOX.mjs → chunk-JUA3VJE7.mjs} +3 -2
- package/dist/chunk-JUA3VJE7.mjs.map +1 -0
- package/dist/{chunk-TJAUXMYJ.mjs → chunk-URXZPI2F.mjs} +8 -1
- package/dist/chunk-URXZPI2F.mjs.map +1 -0
- package/dist/{chunk-KDQKTU3N.mjs → chunk-ZBTG3T7K.mjs} +44 -8
- package/dist/chunk-ZBTG3T7K.mjs.map +1 -0
- package/dist/embed/{embed-page-AgentDetailSideApp-2C2ZR62Q.js → embed-page-AgentDetailSideApp-NTLAFO5C.js} +1 -1
- package/dist/embed/{embed-page-AgentGovernanceWorkbench-GG4ONSTS.js → embed-page-AgentGovernanceWorkbench-QPVBOMLH.js} +1 -1
- package/dist/embed/{embed-page-MessageGraph-WMYTVUUC.js → embed-page-MessageGraph-JAJGMYKH.js} +1 -1
- package/dist/embed/{embed-page-ReactChart-7XCMDMH6.js → embed-page-ReactChart-WUG6TEAZ.js} +1 -1
- package/dist/embed/{embed-page-SkillFlow-XMMHEHQL.js → embed-page-SkillFlow-TSBZ4V2P.js} +1 -1
- package/dist/embed/{embed-page-TasksSideApp-4ZJ4Q4CL.js → embed-page-TasksSideApp-TJI22YGD.js} +1 -1
- package/dist/embed/{embed-page-TeamWorkspace-H5OOEN3K.js → embed-page-TeamWorkspace-OJJLN5VI.js} +1 -1
- package/dist/embed/{embed-page-TopologyRuntimeView-QMXWERVC.js → embed-page-TopologyRuntimeView-ZFU4N6TV.js} +1 -1
- package/dist/embed/{embed-page-WorkflowAutomationView-L2OEGCA5.js → embed-page-WorkflowAutomationView-ALXV7VQQ.js} +1 -1
- package/dist/embed/{embed-page-chunk-CZE4IEB3.js → embed-page-chunk-DZQBVJ7Z.js} +1 -1
- package/dist/embed/{embed-page-chunk-N2ISCAS7.js → embed-page-chunk-IPIJ2SG6.js} +1 -1
- package/dist/embed/{embed-page-chunk-SUMYB6ZA.js → embed-page-chunk-N22EGQAJ.js} +1 -1
- package/dist/embed/{embed-page-chunk-OHDEKFTU.js → embed-page-chunk-O72XBKQH.js} +2 -2
- package/dist/embed/{embed-page-chunk-XIXSRYJY.js → embed-page-chunk-QMVIL4BJ.js} +190 -185
- package/dist/embed/{embed-page-chunk-2G54EIW2.js → embed-page-chunk-UT3WYBZH.js} +1 -1
- package/dist/embed/embed-page-chunk-YPNSOZYW.js +8 -0
- package/dist/embed/embed-page.js +1 -1
- package/dist/index.d.mts +146 -17
- package/dist/index.d.ts +146 -17
- package/dist/index.js +1190 -328
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +649 -97
- package/dist/index.mjs.map +1 -1
- package/dist/{open-STFMNRO5.mjs → open-UVKMONVE.mjs} +5 -4
- package/dist/open-UVKMONVE.mjs.map +1 -0
- package/dist/{open-files-NPNQQ6TY.mjs → open-files-X3HXVEEM.mjs} +4 -4
- package/dist/{open-session-IHDGAXL3.mjs → open-session-2Y7XJJW2.mjs} +3 -3
- package/dist/{resources-DXPXAXEZ.mjs → resources-2L3KSUUU.mjs} +2 -2
- package/dist/sandboxOpenCredentialProvider-USIU7Z7H.mjs +275 -0
- package/dist/sandboxOpenCredentialProvider-USIU7Z7H.mjs.map +1 -0
- package/dist/{sandboxProvider-I3P66VXT.mjs → sandboxProvider-DUYWHYJN.mjs} +2 -2
- package/package.json +14 -8
- package/dist/chunk-52SUWMOX.mjs.map +0 -1
- package/dist/chunk-KDQKTU3N.mjs.map +0 -1
- package/dist/chunk-TJAUXMYJ.mjs.map +0 -1
- package/dist/chunk-WKNZ7GBC.mjs.map +0 -1
- package/dist/embed/embed-page-chunk-HEMNMC4X.js +0 -7
- package/dist/open-STFMNRO5.mjs.map +0 -1
- /package/dist/{OrphanRecoveryRuntime-MQDEJX3M.mjs.map → OrphanRecoveryRuntime-BEFILJMU.mjs.map} +0 -0
- /package/dist/{chunk-2POW27EI.mjs.map → chunk-7CG57LEF.mjs.map} +0 -0
- /package/dist/{open-files-NPNQQ6TY.mjs.map → open-files-X3HXVEEM.mjs.map} +0 -0
- /package/dist/{open-session-IHDGAXL3.mjs.map → open-session-2Y7XJJW2.mjs.map} +0 -0
- /package/dist/{resources-DXPXAXEZ.mjs.map → resources-2L3KSUUU.mjs.map} +0 -0
- /package/dist/{sandboxProvider-I3P66VXT.mjs.map → sandboxProvider-DUYWHYJN.mjs.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -966,7 +966,7 @@ function outcome(task) {
|
|
|
966
966
|
});
|
|
967
967
|
}
|
|
968
968
|
async function backfillTopCallerGroup(tasks, top, deps) {
|
|
969
|
-
const registry = deps.registry ??
|
|
969
|
+
const registry = deps.registry ?? import_core70.taskRunRegistry;
|
|
970
970
|
const results = [];
|
|
971
971
|
const eligible = [];
|
|
972
972
|
for (const task of tasks) {
|
|
@@ -974,7 +974,7 @@ async function backfillTopCallerGroup(tasks, top, deps) {
|
|
|
974
974
|
results.push({ id: task.id, reason: "skipped:no_caller_link" });
|
|
975
975
|
continue;
|
|
976
976
|
}
|
|
977
|
-
if (registry.isLive(task.id)) {
|
|
977
|
+
if (registry.isLive(task.id) || deps.isTaskLive && await deps.isTaskLive(task)) {
|
|
978
978
|
results.push({ id: task.id, reason: "skipped:live" });
|
|
979
979
|
continue;
|
|
980
980
|
}
|
|
@@ -1020,15 +1020,16 @@ async function recoverTask(task, deps) {
|
|
|
1020
1020
|
if (task.status !== "in_progress") {
|
|
1021
1021
|
return { kind: "skipped", reason: "not_in_progress" };
|
|
1022
1022
|
}
|
|
1023
|
-
const registry = deps.registry ??
|
|
1024
|
-
if (registry.isLive(task.id)) {
|
|
1023
|
+
const registry = deps.registry ?? import_core70.taskRunRegistry;
|
|
1024
|
+
if (registry.isLive(task.id) || deps.isTaskLive && await deps.isTaskLive(task)) {
|
|
1025
1025
|
return { kind: "skipped", reason: "live" };
|
|
1026
1026
|
}
|
|
1027
|
-
const { convergedTasks } = await (0,
|
|
1027
|
+
const { convergedTasks } = await (0, import_core70.reconcileStaleTaskRuns)({
|
|
1028
1028
|
tasks: [task],
|
|
1029
1029
|
actor: "system:on-demand-recovery",
|
|
1030
1030
|
lifecycle: deps.lifecycle,
|
|
1031
|
-
...deps.registry ? { registry: deps.registry } : {}
|
|
1031
|
+
...deps.registry ? { registry: deps.registry } : {},
|
|
1032
|
+
...deps.isTaskLive ? { isTaskLive: deps.isTaskLive } : {}
|
|
1032
1033
|
});
|
|
1033
1034
|
const converged = convergedTasks[0];
|
|
1034
1035
|
if (!converged) {
|
|
@@ -1044,7 +1045,8 @@ async function recoverTask(task, deps) {
|
|
|
1044
1045
|
const reason = await recoverTopCaller(converged, top, {
|
|
1045
1046
|
callerFor: deps.callerFor,
|
|
1046
1047
|
resume: deps.resume,
|
|
1047
|
-
...deps.registry ? { registry: deps.registry } : {}
|
|
1048
|
+
...deps.registry ? { registry: deps.registry } : {},
|
|
1049
|
+
...deps.isTaskLive ? { isTaskLive: deps.isTaskLive } : {}
|
|
1048
1050
|
});
|
|
1049
1051
|
if (reason === "recovered") return { kind: "recovered" };
|
|
1050
1052
|
if (reason === "skipped:no_pending_task_call") return { kind: "converged_no_call" };
|
|
@@ -1101,7 +1103,8 @@ async function runOrphanRecovery(deps) {
|
|
|
1101
1103
|
try {
|
|
1102
1104
|
const results = await backfillTopCallerGroup(tasks, top, {
|
|
1103
1105
|
callerFor: deps.callerFor,
|
|
1104
|
-
resume: deps.resume
|
|
1106
|
+
resume: deps.resume,
|
|
1107
|
+
...deps.isTaskLive ? { isTaskLive: deps.isTaskLive } : {}
|
|
1105
1108
|
});
|
|
1106
1109
|
for (const { id: id3, reason } of results) {
|
|
1107
1110
|
(reason === "recovered" ? recovered : skipped).push(`${id3}:${reason}`);
|
|
@@ -1117,12 +1120,41 @@ async function runOrphanRecovery(deps) {
|
|
|
1117
1120
|
deps.log.info("Task orphan recovery complete", { recovered, skipped });
|
|
1118
1121
|
return { recovered, skipped };
|
|
1119
1122
|
}
|
|
1120
|
-
var import_messages,
|
|
1123
|
+
var import_messages, import_core70;
|
|
1121
1124
|
var init_TopCallerRecovery = __esm({
|
|
1122
1125
|
"src/services/collaboration/TopCallerRecovery.ts"() {
|
|
1123
1126
|
"use strict";
|
|
1124
1127
|
import_messages = require("@langchain/core/messages");
|
|
1125
|
-
|
|
1128
|
+
import_core70 = require("@axiom-lattice/core");
|
|
1129
|
+
}
|
|
1130
|
+
});
|
|
1131
|
+
|
|
1132
|
+
// src/services/collaboration/taskRunLiveness.ts
|
|
1133
|
+
function createTaskRunLiveness() {
|
|
1134
|
+
try {
|
|
1135
|
+
import_core71.storeLatticeManager.getStoreLattice("default", "lease");
|
|
1136
|
+
} catch {
|
|
1137
|
+
return void 0;
|
|
1138
|
+
}
|
|
1139
|
+
return async (task) => {
|
|
1140
|
+
try {
|
|
1141
|
+
const store2 = import_core71.storeLatticeManager.getStoreLattice("default", "lease").store;
|
|
1142
|
+
if (await store2.get((0, import_core71.taskRunLeaseKey)(task.id))) return true;
|
|
1143
|
+
const threadId = typeof task.context?.thread_id === "string" ? task.context.thread_id : void 0;
|
|
1144
|
+
if (threadId && task.ownerId) {
|
|
1145
|
+
if (await store2.get((0, import_core71.threadRunLeaseKey)(task.tenantId, task.ownerId, threadId))) return true;
|
|
1146
|
+
}
|
|
1147
|
+
return false;
|
|
1148
|
+
} catch {
|
|
1149
|
+
return true;
|
|
1150
|
+
}
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
var import_core71;
|
|
1154
|
+
var init_taskRunLiveness = __esm({
|
|
1155
|
+
"src/services/collaboration/taskRunLiveness.ts"() {
|
|
1156
|
+
"use strict";
|
|
1157
|
+
import_core71 = require("@axiom-lattice/core");
|
|
1126
1158
|
}
|
|
1127
1159
|
});
|
|
1128
1160
|
|
|
@@ -1132,24 +1164,27 @@ __export(OrphanRecoveryRuntime_exports, {
|
|
|
1132
1164
|
createOrphanRecoveryRuntime: () => createOrphanRecoveryRuntime
|
|
1133
1165
|
});
|
|
1134
1166
|
function createOrphanRecoveryRuntime(deps) {
|
|
1135
|
-
const lifecycle = deps.lifecycle ?? (0,
|
|
1167
|
+
const lifecycle = deps.lifecycle ?? (0, import_core72.createTaskLifecycleService)({
|
|
1136
1168
|
taskStore: deps.taskStore,
|
|
1137
1169
|
workItemStore: deps.workItemStore
|
|
1138
1170
|
});
|
|
1139
1171
|
return {
|
|
1140
1172
|
async recoverAll() {
|
|
1173
|
+
const isTaskLive = deps.isTaskLive ?? createTaskRunLiveness();
|
|
1141
1174
|
return runOrphanRecovery({
|
|
1142
|
-
reconcile: () => (0,
|
|
1175
|
+
reconcile: () => (0, import_core72.reconcileAllTenantTaskRuns)({
|
|
1143
1176
|
actor: "system:orphan-recovery",
|
|
1144
1177
|
tenantStore: {
|
|
1145
1178
|
listTenants: async () => (await deps.tenantStore.getAllTenants()).map((tenant2) => ({ id: tenant2.id }))
|
|
1146
1179
|
},
|
|
1147
1180
|
taskStore: deps.taskStore,
|
|
1148
1181
|
lifecycle,
|
|
1149
|
-
include: (t2) => !isProjectLifecycleTask(t2)
|
|
1182
|
+
include: (t2) => !isProjectLifecycleTask(t2),
|
|
1183
|
+
...isTaskLive ? { isTaskLive } : {}
|
|
1150
1184
|
}),
|
|
1151
1185
|
callerFor: deps.callerFor,
|
|
1152
1186
|
resume: deps.resume,
|
|
1187
|
+
...isTaskLive ? { isTaskLive } : {},
|
|
1153
1188
|
log: deps.log
|
|
1154
1189
|
});
|
|
1155
1190
|
},
|
|
@@ -1160,23 +1195,26 @@ function createOrphanRecoveryRuntime(deps) {
|
|
|
1160
1195
|
return { kind: "skipped", reason: "project_task" };
|
|
1161
1196
|
}
|
|
1162
1197
|
const orphans = await deps.taskStore.list({ tenantId: input.tenantId, status: "in_progress" });
|
|
1198
|
+
const isTaskLive = deps.isTaskLive ?? createTaskRunLiveness();
|
|
1163
1199
|
return recoverTask(task, {
|
|
1164
1200
|
lifecycle,
|
|
1165
|
-
registry:
|
|
1201
|
+
registry: import_core72.taskRunRegistry,
|
|
1166
1202
|
orphans,
|
|
1167
1203
|
callerFor: deps.callerFor,
|
|
1168
|
-
resume: deps.resume
|
|
1204
|
+
resume: deps.resume,
|
|
1205
|
+
...isTaskLive ? { isTaskLive } : {}
|
|
1169
1206
|
});
|
|
1170
1207
|
}
|
|
1171
1208
|
};
|
|
1172
1209
|
}
|
|
1173
|
-
var
|
|
1210
|
+
var import_core72;
|
|
1174
1211
|
var init_OrphanRecoveryRuntime = __esm({
|
|
1175
1212
|
"src/services/collaboration/OrphanRecoveryRuntime.ts"() {
|
|
1176
1213
|
"use strict";
|
|
1177
|
-
|
|
1214
|
+
import_core72 = require("@axiom-lattice/core");
|
|
1178
1215
|
init_TopCallerRecovery();
|
|
1179
1216
|
init_projectTaskScope();
|
|
1217
|
+
init_taskRunLiveness();
|
|
1180
1218
|
}
|
|
1181
1219
|
});
|
|
1182
1220
|
|
|
@@ -1189,12 +1227,12 @@ function createRecoveryCallerDeps() {
|
|
|
1189
1227
|
return {
|
|
1190
1228
|
callerFor: async (top, tenantId) => {
|
|
1191
1229
|
if (!top.assistantId) return void 0;
|
|
1192
|
-
const load =
|
|
1230
|
+
const load = import_core73.getAgentClientAsync ?? import_core73.getAgentClient;
|
|
1193
1231
|
const client = await load(tenantId, top.assistantId);
|
|
1194
1232
|
const config = { configurable: { thread_id: top.threadId, runConfig: { tenantId, assistant_id: top.assistantId } } };
|
|
1195
1233
|
let agent;
|
|
1196
1234
|
try {
|
|
1197
|
-
agent =
|
|
1235
|
+
agent = import_core73.agentInstanceManager.getAgent({ assistant_id: top.assistantId, thread_id: top.threadId, tenant_id: tenantId });
|
|
1198
1236
|
} catch {
|
|
1199
1237
|
}
|
|
1200
1238
|
return agent ? { client, config, agent } : { client, config };
|
|
@@ -1211,11 +1249,11 @@ function createRecoveryCallerDeps() {
|
|
|
1211
1249
|
}
|
|
1212
1250
|
};
|
|
1213
1251
|
}
|
|
1214
|
-
var
|
|
1252
|
+
var import_core73;
|
|
1215
1253
|
var init_RecoveryCallerDeps = __esm({
|
|
1216
1254
|
"src/services/collaboration/RecoveryCallerDeps.ts"() {
|
|
1217
1255
|
"use strict";
|
|
1218
|
-
|
|
1256
|
+
import_core73 = require("@axiom-lattice/core");
|
|
1219
1257
|
}
|
|
1220
1258
|
});
|
|
1221
1259
|
|
|
@@ -1805,13 +1843,13 @@ function isA2ATaskSnapshot(value) {
|
|
|
1805
1843
|
function snapshotSequence(value) {
|
|
1806
1844
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
1807
1845
|
}
|
|
1808
|
-
var import_node_crypto28, import_node_util,
|
|
1846
|
+
var import_node_crypto28, import_node_util, import_core74, TASK_STATUS_TO_A2A_STATE, TITLE_MAX_LENGTH, A2ATaskScopeConflictError, A2ATaskStoreAdapter;
|
|
1809
1847
|
var init_A2ATaskStoreAdapter = __esm({
|
|
1810
1848
|
"src/services/a2a/A2ATaskStoreAdapter.ts"() {
|
|
1811
1849
|
"use strict";
|
|
1812
1850
|
import_node_crypto28 = require("crypto");
|
|
1813
1851
|
import_node_util = require("util");
|
|
1814
|
-
|
|
1852
|
+
import_core74 = require("@axiom-lattice/core");
|
|
1815
1853
|
TASK_STATUS_TO_A2A_STATE = {
|
|
1816
1854
|
pending: "submitted",
|
|
1817
1855
|
in_progress: "working",
|
|
@@ -1837,7 +1875,7 @@ var init_A2ATaskStoreAdapter = __esm({
|
|
|
1837
1875
|
this.workItemStore = options.workItemStore;
|
|
1838
1876
|
this.lifecycle = options.lifecycle;
|
|
1839
1877
|
this.scope = options.scope;
|
|
1840
|
-
this.runBridge = (0,
|
|
1878
|
+
this.runBridge = (0, import_core74.createTaskRunBridge)({
|
|
1841
1879
|
lifecycle: this.lifecycle,
|
|
1842
1880
|
taskStore: this.taskStore,
|
|
1843
1881
|
workItemStore: this.workItemStore
|
|
@@ -2188,12 +2226,12 @@ function assistantHasGovernedTask(assistant) {
|
|
|
2188
2226
|
const allowedTools = taskMiddleware?.allowedTools;
|
|
2189
2227
|
return !!taskMiddleware && (allowedTools === void 0 || Array.isArray(allowedTools) && (allowedTools.length === 0 || allowedTools.includes("manage_task")));
|
|
2190
2228
|
}
|
|
2191
|
-
var import_uuid11,
|
|
2229
|
+
var import_uuid11, import_core75, import_protocols35, _AxiomAgentExecutor, AxiomAgentExecutor;
|
|
2192
2230
|
var init_AxiomAgentExecutor = __esm({
|
|
2193
2231
|
"src/services/a2a/AxiomAgentExecutor.ts"() {
|
|
2194
2232
|
"use strict";
|
|
2195
2233
|
import_uuid11 = require("uuid");
|
|
2196
|
-
|
|
2234
|
+
import_core75 = require("@axiom-lattice/core");
|
|
2197
2235
|
import_protocols35 = require("@axiom-lattice/protocols");
|
|
2198
2236
|
init_a2aFileRefs();
|
|
2199
2237
|
init_task_file_refs();
|
|
@@ -2290,7 +2328,7 @@ var init_AxiomAgentExecutor = __esm({
|
|
|
2290
2328
|
await this.taskStore.save(initialTask);
|
|
2291
2329
|
bus.publish(initialTask);
|
|
2292
2330
|
try {
|
|
2293
|
-
const agent =
|
|
2331
|
+
const agent = import_core75.agentInstanceManager.getAgent(this.agentParams(threadId));
|
|
2294
2332
|
const requestText = inputFiles.length > 0 ? `${text}
|
|
2295
2333
|
|
|
2296
2334
|
${formatFileRefsSection(inputFiles)}` : text;
|
|
@@ -2478,7 +2516,7 @@ ${formatFileRefsSection(inputFiles)}` : text;
|
|
|
2478
2516
|
const threadId = task ? asString2(task.metadata?.threadId) : void 0;
|
|
2479
2517
|
if (threadId) {
|
|
2480
2518
|
try {
|
|
2481
|
-
const agent =
|
|
2519
|
+
const agent = import_core75.agentInstanceManager.getAgent(this.agentParams(threadId));
|
|
2482
2520
|
await agent.abort();
|
|
2483
2521
|
} catch (err) {
|
|
2484
2522
|
console.warn({
|
|
@@ -2852,10 +2890,10 @@ function isAsyncGenerator(value) {
|
|
|
2852
2890
|
}
|
|
2853
2891
|
function registerA2AStandardRoutes(app2, deps) {
|
|
2854
2892
|
const authService = deps.authService;
|
|
2855
|
-
const resolveTasks = deps.getTaskStoreLattice ?? (() => (0,
|
|
2856
|
-
const resolveTaskWorkItems = deps.getTaskWorkItemStore ?? (() => (0,
|
|
2857
|
-
const getAssistantStore2 = deps.getAssistantStore ?? (() => (0,
|
|
2858
|
-
const getProjectStore2 = deps.getProjectStore ?? (() => (0,
|
|
2893
|
+
const resolveTasks = deps.getTaskStoreLattice ?? (() => (0, import_core76.getStoreLattice)("default", "task").store);
|
|
2894
|
+
const resolveTaskWorkItems = deps.getTaskWorkItemStore ?? (() => (0, import_core76.getStoreLattice)("default", "taskWorkItem").store);
|
|
2895
|
+
const getAssistantStore2 = deps.getAssistantStore ?? (() => (0, import_core76.getStoreLattice)("default", "assistant").store);
|
|
2896
|
+
const getProjectStore2 = deps.getProjectStore ?? (() => (0, import_core76.getStoreLattice)("default", "project").store);
|
|
2859
2897
|
const runtimeRegistry = deps.runtimeRegistry ?? new A2ARuntimeRegistry();
|
|
2860
2898
|
app2.addHook("onClose", async () => {
|
|
2861
2899
|
runtimeRegistry.close();
|
|
@@ -2938,7 +2976,7 @@ function registerA2AStandardRoutes(app2, deps) {
|
|
|
2938
2976
|
const taskStore = assistantHasGovernedTask(assistant) ? new A2ATaskStoreAdapter({
|
|
2939
2977
|
taskStore: internalTasks,
|
|
2940
2978
|
workItemStore: workItems,
|
|
2941
|
-
lifecycle: (0,
|
|
2979
|
+
lifecycle: (0, import_core76.createTaskLifecycleService)({
|
|
2942
2980
|
taskStore: internalTasks,
|
|
2943
2981
|
workItemStore: workItems
|
|
2944
2982
|
}),
|
|
@@ -3057,7 +3095,7 @@ data: ${JSON.stringify(errorResponse)}
|
|
|
3057
3095
|
const taskStore = assistantHasGovernedTask(assistant) ? new A2ATaskStoreAdapter({
|
|
3058
3096
|
taskStore: internalTasks,
|
|
3059
3097
|
workItemStore: workItems,
|
|
3060
|
-
lifecycle: (0,
|
|
3098
|
+
lifecycle: (0, import_core76.createTaskLifecycleService)({
|
|
3061
3099
|
taskStore: internalTasks,
|
|
3062
3100
|
workItemStore: workItems
|
|
3063
3101
|
}),
|
|
@@ -3112,13 +3150,13 @@ data: ${JSON.stringify(data)}
|
|
|
3112
3150
|
}
|
|
3113
3151
|
);
|
|
3114
3152
|
}
|
|
3115
|
-
var import_uuid12, import_server2,
|
|
3153
|
+
var import_uuid12, import_server2, import_core76, SSE_HEADERS;
|
|
3116
3154
|
var init_a2a_standard = __esm({
|
|
3117
3155
|
"src/routes/a2a-standard.ts"() {
|
|
3118
3156
|
"use strict";
|
|
3119
3157
|
import_uuid12 = require("uuid");
|
|
3120
3158
|
import_server2 = require("@a2a-js/sdk/server");
|
|
3121
|
-
|
|
3159
|
+
import_core76 = require("@axiom-lattice/core");
|
|
3122
3160
|
init_A2AAuthService();
|
|
3123
3161
|
init_A2AAgentCardBuilder();
|
|
3124
3162
|
init_A2ATaskStoreAdapter();
|
|
@@ -3376,6 +3414,7 @@ var init_openCredentialService = __esm({
|
|
|
3376
3414
|
projectId: token.projectId,
|
|
3377
3415
|
workspaceId: token.workspaceId,
|
|
3378
3416
|
sandboxName: token.sandboxName,
|
|
3417
|
+
depth: token.depth,
|
|
3379
3418
|
grants: token.grants
|
|
3380
3419
|
};
|
|
3381
3420
|
}
|
|
@@ -3869,8 +3908,8 @@ function exposedDeclarations(plugin) {
|
|
|
3869
3908
|
return (plugin.meta.tools ?? []).filter((t2) => t2.expose);
|
|
3870
3909
|
}
|
|
3871
3910
|
async function registerExposedPluginTools() {
|
|
3872
|
-
for (const key of
|
|
3873
|
-
const plugin =
|
|
3911
|
+
for (const key of import_core77.PluginRegistry.list()) {
|
|
3912
|
+
const plugin = import_core77.PluginRegistry.get(key);
|
|
3874
3913
|
if (!plugin?.middleware) continue;
|
|
3875
3914
|
const exposed = exposedDeclarations(plugin);
|
|
3876
3915
|
if (exposed.length === 0) continue;
|
|
@@ -3905,8 +3944,8 @@ async function registerExposedPluginTools() {
|
|
|
3905
3944
|
}
|
|
3906
3945
|
function collectExposedPluginUiResources(grants) {
|
|
3907
3946
|
const resources = /* @__PURE__ */ new Map();
|
|
3908
|
-
for (const type of
|
|
3909
|
-
const plugin =
|
|
3947
|
+
for (const type of import_core77.PluginRegistry.list()) {
|
|
3948
|
+
const plugin = import_core77.PluginRegistry.get(type);
|
|
3910
3949
|
if (!plugin?.middleware) continue;
|
|
3911
3950
|
const exposedNames = new Set(exposedDeclarations(plugin).map((d) => d.name));
|
|
3912
3951
|
if (exposedNames.size === 0) continue;
|
|
@@ -3930,11 +3969,11 @@ function collectExposedPluginUiResources(grants) {
|
|
|
3930
3969
|
}
|
|
3931
3970
|
return resources;
|
|
3932
3971
|
}
|
|
3933
|
-
var
|
|
3972
|
+
var import_core77;
|
|
3934
3973
|
var init_registerExposedPlugins = __esm({
|
|
3935
3974
|
"src/services/open/registerExposedPlugins.ts"() {
|
|
3936
3975
|
"use strict";
|
|
3937
|
-
|
|
3976
|
+
import_core77 = require("@axiom-lattice/core");
|
|
3938
3977
|
init_openLattice();
|
|
3939
3978
|
init_pluginExposeAdapter();
|
|
3940
3979
|
}
|
|
@@ -3949,14 +3988,14 @@ function toText(result) {
|
|
|
3949
3988
|
}
|
|
3950
3989
|
function defaultCatalog() {
|
|
3951
3990
|
return {
|
|
3952
|
-
getValidatedManifest: (tenantId, type) => (0,
|
|
3953
|
-
getExecutor: () => (0,
|
|
3954
|
-
readPluginFile: (tenantId, type, relPath) => (0,
|
|
3991
|
+
getValidatedManifest: (tenantId, type) => (0, import_core78.getSandboxPluginCatalog)().getValidatedManifest(tenantId, type),
|
|
3992
|
+
getExecutor: () => (0, import_core78.getSandboxPluginCatalog)().getExecutor(),
|
|
3993
|
+
readPluginFile: (tenantId, type, relPath) => (0, import_core78.getSandboxPluginCatalog)().readPluginFile(tenantId, type, relPath)
|
|
3955
3994
|
};
|
|
3956
3995
|
}
|
|
3957
3996
|
async function defaultResolveConnections(pluginType, ctx) {
|
|
3958
3997
|
try {
|
|
3959
|
-
return await (0,
|
|
3998
|
+
return await (0, import_core78.resolveSandboxPluginConnections)(
|
|
3960
3999
|
pluginType,
|
|
3961
4000
|
{ connectAll: true },
|
|
3962
4001
|
{
|
|
@@ -3985,7 +4024,7 @@ function mergeOpenCatalog(globalCatalog, tenantTools) {
|
|
|
3985
4024
|
async function buildTenantOpenPlugins(tenantId, grants, deps = {}) {
|
|
3986
4025
|
const catalog = deps.catalog ?? defaultCatalog();
|
|
3987
4026
|
const listPlugins = deps.listPlugins ?? (async (tenant2) => {
|
|
3988
|
-
const snapshot = await (0,
|
|
4027
|
+
const snapshot = await (0, import_core78.getSandboxPluginCatalog)().ensureLoaded(tenant2);
|
|
3989
4028
|
return { plugins: snapshot.plugins, diagnostics: snapshot.diagnostics };
|
|
3990
4029
|
});
|
|
3991
4030
|
const resolveConnections = deps.resolveConnections ?? defaultResolveConnections;
|
|
@@ -4027,7 +4066,7 @@ async function buildTenantOpenPlugins(tenantId, grants, deps = {}) {
|
|
|
4027
4066
|
domain,
|
|
4028
4067
|
action: tool.name,
|
|
4029
4068
|
description: tool.description,
|
|
4030
|
-
schema: (0,
|
|
4069
|
+
schema: (0, import_core78.jsonSchemaToZod)(tool.schema),
|
|
4031
4070
|
annotations: {
|
|
4032
4071
|
readOnlyHint: tool.readOnly ?? false,
|
|
4033
4072
|
destructiveHint: tool.destructive ?? false
|
|
@@ -4078,11 +4117,11 @@ async function buildTenantOpenPlugins(tenantId, grants, deps = {}) {
|
|
|
4078
4117
|
}
|
|
4079
4118
|
};
|
|
4080
4119
|
}
|
|
4081
|
-
var
|
|
4120
|
+
var import_core78;
|
|
4082
4121
|
var init_tenantOpenPlugins = __esm({
|
|
4083
4122
|
"src/services/open/tenantOpenPlugins.ts"() {
|
|
4084
4123
|
"use strict";
|
|
4085
|
-
|
|
4124
|
+
import_core78 = require("@axiom-lattice/core");
|
|
4086
4125
|
init_openLattice();
|
|
4087
4126
|
init_pluginToolExecution();
|
|
4088
4127
|
}
|
|
@@ -4119,13 +4158,13 @@ function emptyTenantPlugins() {
|
|
|
4119
4158
|
}
|
|
4120
4159
|
function registerOpenRoutes(app2, deps = {}) {
|
|
4121
4160
|
const openAuth = deps.openAuth ?? new OpenCredentialService(
|
|
4122
|
-
(0,
|
|
4123
|
-
(0,
|
|
4161
|
+
(0, import_core79.getStoreLattice)("default", "a2aApiKey").store,
|
|
4162
|
+
(0, import_core79.getStoreLattice)("default", "project").store
|
|
4124
4163
|
);
|
|
4125
4164
|
const grantsSource = deps.grantsSource ?? ((ctx) => ctx.grants);
|
|
4126
4165
|
const audit = deps.audit ?? (() => {
|
|
4127
4166
|
try {
|
|
4128
|
-
const store2 = (0,
|
|
4167
|
+
const store2 = (0, import_core79.getStoreLattice)("default", "openAudit").store;
|
|
4129
4168
|
return new OpenAuditService(store2);
|
|
4130
4169
|
} catch {
|
|
4131
4170
|
return void 0;
|
|
@@ -4211,7 +4250,8 @@ function registerOpenRoutes(app2, deps = {}) {
|
|
|
4211
4250
|
const isTenantRoute = tenant2.hasTool(toolName) && !globalToolNames.has(toolName);
|
|
4212
4251
|
const runConfig = {
|
|
4213
4252
|
sandboxName: context.sandboxName,
|
|
4214
|
-
credentialId: context.credentialId
|
|
4253
|
+
credentialId: context.credentialId,
|
|
4254
|
+
depth: context.depth
|
|
4215
4255
|
};
|
|
4216
4256
|
const result = isTenantRoute ? await tenant2.invoke(toolName, args, {
|
|
4217
4257
|
tenantId: context.tenantId,
|
|
@@ -4279,12 +4319,12 @@ function registerOpenRoutes(app2, deps = {}) {
|
|
|
4279
4319
|
}
|
|
4280
4320
|
);
|
|
4281
4321
|
}
|
|
4282
|
-
var import_types,
|
|
4322
|
+
var import_types, import_core79, RPC_ERROR;
|
|
4283
4323
|
var init_open = __esm({
|
|
4284
4324
|
"src/routes/open.ts"() {
|
|
4285
4325
|
"use strict";
|
|
4286
4326
|
import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
4287
|
-
|
|
4327
|
+
import_core79 = require("@axiom-lattice/core");
|
|
4288
4328
|
init_openCredentialService();
|
|
4289
4329
|
init_openAuditService();
|
|
4290
4330
|
init_openRateLimiter();
|
|
@@ -4317,7 +4357,7 @@ function registerOpenSessionRoutes(app2) {
|
|
|
4317
4357
|
if (typeof shareToken !== "string" || shareToken.length === 0) {
|
|
4318
4358
|
return reply.status(400).send({ error: "SHARE_TOKEN_REQUIRED" });
|
|
4319
4359
|
}
|
|
4320
|
-
const store2 = (0,
|
|
4360
|
+
const store2 = (0, import_core80.getStoreLattice)("default", "sharedResource").store;
|
|
4321
4361
|
const record = await store2.findByToken(shareToken);
|
|
4322
4362
|
if (!record || record.revoked) {
|
|
4323
4363
|
return reply.status(404).send({ error: "SHARE_NOT_FOUND" });
|
|
@@ -4342,11 +4382,11 @@ function registerOpenSessionRoutes(app2) {
|
|
|
4342
4382
|
}
|
|
4343
4383
|
);
|
|
4344
4384
|
}
|
|
4345
|
-
var
|
|
4385
|
+
var import_core80;
|
|
4346
4386
|
var init_open_session = __esm({
|
|
4347
4387
|
"src/routes/open-session.ts"() {
|
|
4348
4388
|
"use strict";
|
|
4349
|
-
|
|
4389
|
+
import_core80 = require("@axiom-lattice/core");
|
|
4350
4390
|
init_openToken();
|
|
4351
4391
|
init_previewToken();
|
|
4352
4392
|
init_openLattice();
|
|
@@ -4355,13 +4395,13 @@ var init_open_session = __esm({
|
|
|
4355
4395
|
|
|
4356
4396
|
// src/services/open/openCatalogService.ts
|
|
4357
4397
|
async function defaultListTenantPlugins(tenantId) {
|
|
4358
|
-
return (await (0,
|
|
4398
|
+
return (await (0, import_core81.getSandboxPluginCatalog)().ensureLoaded(tenantId)).plugins;
|
|
4359
4399
|
}
|
|
4360
|
-
var
|
|
4400
|
+
var import_core81, OpenCatalogService;
|
|
4361
4401
|
var init_openCatalogService = __esm({
|
|
4362
4402
|
"src/services/open/openCatalogService.ts"() {
|
|
4363
4403
|
"use strict";
|
|
4364
|
-
|
|
4404
|
+
import_core81 = require("@axiom-lattice/core");
|
|
4365
4405
|
init_openLattice();
|
|
4366
4406
|
OpenCatalogService = class {
|
|
4367
4407
|
constructor(assistantStore, lattice = openLattice, listTenantPlugins2 = defaultListTenantPlugins) {
|
|
@@ -4436,17 +4476,17 @@ function registerOpenCatalogRoutes(app2) {
|
|
|
4436
4476
|
if (!tenantId) {
|
|
4437
4477
|
return reply.status(401).send({ success: false, error: "Unauthorized" });
|
|
4438
4478
|
}
|
|
4439
|
-
const assistantStore = (0,
|
|
4479
|
+
const assistantStore = (0, import_core82.getStoreLattice)("default", "assistant").store;
|
|
4440
4480
|
const service2 = new OpenCatalogService(assistantStore);
|
|
4441
4481
|
const catalog = await service2.buildForTenant(tenantId);
|
|
4442
4482
|
return reply.status(200).send({ success: true, data: catalog });
|
|
4443
4483
|
});
|
|
4444
4484
|
}
|
|
4445
|
-
var
|
|
4485
|
+
var import_core82;
|
|
4446
4486
|
var init_open_catalog = __esm({
|
|
4447
4487
|
"src/routes/open-catalog.ts"() {
|
|
4448
4488
|
"use strict";
|
|
4449
|
-
|
|
4489
|
+
import_core82 = require("@axiom-lattice/core");
|
|
4450
4490
|
init_openCatalogService();
|
|
4451
4491
|
}
|
|
4452
4492
|
});
|
|
@@ -4458,7 +4498,14 @@ __export(sandboxProvider_exports, {
|
|
|
4458
4498
|
resolveContextSandbox: () => resolveContextSandbox
|
|
4459
4499
|
});
|
|
4460
4500
|
async function resolveContextSandbox(ctx) {
|
|
4461
|
-
|
|
4501
|
+
const sandboxName = ctx.runConfig?.sandboxName;
|
|
4502
|
+
if (typeof sandboxName === "string" && sandboxName.length > 0) {
|
|
4503
|
+
try {
|
|
4504
|
+
return await import_core83.sandboxLatticeManager.getSandbox(sandboxName);
|
|
4505
|
+
} catch {
|
|
4506
|
+
}
|
|
4507
|
+
}
|
|
4508
|
+
return import_core83.sandboxLatticeManager.getSandboxFromConfig({
|
|
4462
4509
|
assistant_id: "",
|
|
4463
4510
|
thread_id: "",
|
|
4464
4511
|
tenantId: ctx.tenantId,
|
|
@@ -4556,12 +4603,12 @@ ${truncated}`
|
|
|
4556
4603
|
}
|
|
4557
4604
|
};
|
|
4558
4605
|
}
|
|
4559
|
-
var import_zod21,
|
|
4606
|
+
var import_zod21, import_core83, MAX_OUTPUT_BYTES;
|
|
4560
4607
|
var init_sandboxProvider = __esm({
|
|
4561
4608
|
"src/services/open/providers/sandboxProvider.ts"() {
|
|
4562
4609
|
"use strict";
|
|
4563
4610
|
import_zod21 = require("zod");
|
|
4564
|
-
|
|
4611
|
+
import_core83 = require("@axiom-lattice/core");
|
|
4565
4612
|
MAX_OUTPUT_BYTES = 64e3;
|
|
4566
4613
|
}
|
|
4567
4614
|
});
|
|
@@ -4583,12 +4630,12 @@ function safePath(raw) {
|
|
|
4583
4630
|
}
|
|
4584
4631
|
function registerOpenFilesRoutes(app2, deps = {}) {
|
|
4585
4632
|
const openAuth = deps.openAuth ?? new OpenCredentialService(
|
|
4586
|
-
(0,
|
|
4587
|
-
(0,
|
|
4633
|
+
(0, import_core84.getStoreLattice)("default", "a2aApiKey").store,
|
|
4634
|
+
(0, import_core84.getStoreLattice)("default", "project").store
|
|
4588
4635
|
);
|
|
4589
4636
|
const audit = deps.audit ?? (() => {
|
|
4590
4637
|
try {
|
|
4591
|
-
const store2 = (0,
|
|
4638
|
+
const store2 = (0, import_core84.getStoreLattice)("default", "openAudit").store;
|
|
4592
4639
|
return new OpenAuditService(store2);
|
|
4593
4640
|
} catch {
|
|
4594
4641
|
return void 0;
|
|
@@ -4698,11 +4745,11 @@ function registerOpenFilesRoutes(app2, deps = {}) {
|
|
|
4698
4745
|
}
|
|
4699
4746
|
});
|
|
4700
4747
|
}
|
|
4701
|
-
var
|
|
4748
|
+
var import_core84;
|
|
4702
4749
|
var init_open_files = __esm({
|
|
4703
4750
|
"src/routes/open-files.ts"() {
|
|
4704
4751
|
"use strict";
|
|
4705
|
-
|
|
4752
|
+
import_core84 = require("@axiom-lattice/core");
|
|
4706
4753
|
init_openCredentialService();
|
|
4707
4754
|
init_openLattice();
|
|
4708
4755
|
init_sandboxProvider();
|
|
@@ -4724,7 +4771,7 @@ function registerOpenAuditRoutes(app2) {
|
|
|
4724
4771
|
return reply.status(401).send({ success: false, error: "Unauthorized" });
|
|
4725
4772
|
}
|
|
4726
4773
|
const status = request.query.status === "ok" || request.query.status === "error" ? request.query.status : void 0;
|
|
4727
|
-
const store2 = (0,
|
|
4774
|
+
const store2 = (0, import_core85.getStoreLattice)("default", "openAudit").store;
|
|
4728
4775
|
const records = await store2.query({
|
|
4729
4776
|
tenantId,
|
|
4730
4777
|
credentialId: request.query.credentialId,
|
|
@@ -4739,11 +4786,11 @@ function registerOpenAuditRoutes(app2) {
|
|
|
4739
4786
|
}
|
|
4740
4787
|
);
|
|
4741
4788
|
}
|
|
4742
|
-
var
|
|
4789
|
+
var import_core85;
|
|
4743
4790
|
var init_open_audit = __esm({
|
|
4744
4791
|
"src/routes/open-audit.ts"() {
|
|
4745
4792
|
"use strict";
|
|
4746
|
-
|
|
4793
|
+
import_core85 = require("@axiom-lattice/core");
|
|
4747
4794
|
}
|
|
4748
4795
|
});
|
|
4749
4796
|
|
|
@@ -4760,7 +4807,7 @@ function registerOpenExposureRoutes(app2, deps = {}) {
|
|
|
4760
4807
|
if (!tenantId) {
|
|
4761
4808
|
return reply.status(401).send({ success: false, error: "Unauthorized" });
|
|
4762
4809
|
}
|
|
4763
|
-
const keyStore = (0,
|
|
4810
|
+
const keyStore = (0, import_core86.getStoreLattice)("default", "a2aApiKey").store;
|
|
4764
4811
|
const record = await keyStore.findById(request.params.id);
|
|
4765
4812
|
if (!record || record.tenantId !== tenantId) {
|
|
4766
4813
|
return reply.status(404).send({ success: false, error: "Key not found" });
|
|
@@ -4794,7 +4841,7 @@ function registerOpenExposureRoutes(app2, deps = {}) {
|
|
|
4794
4841
|
hasUi: Boolean(t2.ui)
|
|
4795
4842
|
}));
|
|
4796
4843
|
const agentGrant = grants.find((g) => g.domain === "agent");
|
|
4797
|
-
const assistantStore = (0,
|
|
4844
|
+
const assistantStore = (0, import_core86.getStoreLattice)("default", "assistant").store;
|
|
4798
4845
|
const agents = [];
|
|
4799
4846
|
for (const assistantId of agentGrant?.items ?? []) {
|
|
4800
4847
|
const assistant = await assistantStore.getAssistantById(
|
|
@@ -4829,11 +4876,11 @@ function registerOpenExposureRoutes(app2, deps = {}) {
|
|
|
4829
4876
|
}
|
|
4830
4877
|
);
|
|
4831
4878
|
}
|
|
4832
|
-
var
|
|
4879
|
+
var import_core86, import_protocols38;
|
|
4833
4880
|
var init_open_exposure = __esm({
|
|
4834
4881
|
"src/routes/open-exposure.ts"() {
|
|
4835
4882
|
"use strict";
|
|
4836
|
-
|
|
4883
|
+
import_core86 = require("@axiom-lattice/core");
|
|
4837
4884
|
import_protocols38 = require("@axiom-lattice/protocols");
|
|
4838
4885
|
init_openLattice();
|
|
4839
4886
|
init_tenantOpenPlugins();
|
|
@@ -4953,7 +5000,7 @@ function createAgentProvider(deps = {}) {
|
|
|
4953
5000
|
} catch {
|
|
4954
5001
|
}
|
|
4955
5002
|
}
|
|
4956
|
-
const agent =
|
|
5003
|
+
const agent = import_core87.agentInstanceManager.getAgent({
|
|
4957
5004
|
tenant_id: ctx.tenantId,
|
|
4958
5005
|
assistant_id: assistantId,
|
|
4959
5006
|
thread_id: threadId,
|
|
@@ -4978,17 +5025,292 @@ function createAgentProvider(deps = {}) {
|
|
|
4978
5025
|
}
|
|
4979
5026
|
};
|
|
4980
5027
|
}
|
|
4981
|
-
var import_zod23,
|
|
5028
|
+
var import_zod23, import_core87, import_protocols39, STOP_TYPES;
|
|
4982
5029
|
var init_agentProvider = __esm({
|
|
4983
5030
|
"src/services/open/providers/agentProvider.ts"() {
|
|
4984
5031
|
"use strict";
|
|
4985
5032
|
import_zod23 = require("zod");
|
|
4986
|
-
|
|
5033
|
+
import_core87 = require("@axiom-lattice/core");
|
|
4987
5034
|
import_protocols39 = require("@axiom-lattice/protocols");
|
|
4988
5035
|
STOP_TYPES = [import_protocols39.MessageChunkTypes.MESSAGE_COMPLETED];
|
|
4989
5036
|
}
|
|
4990
5037
|
});
|
|
4991
5038
|
|
|
5039
|
+
// src/services/open/sandboxOpenReflection.ts
|
|
5040
|
+
function cloneGrants(grants) {
|
|
5041
|
+
return grants.map((grant) => ({
|
|
5042
|
+
...grant,
|
|
5043
|
+
items: grant.items ? [...grant.items] : void 0
|
|
5044
|
+
}));
|
|
5045
|
+
}
|
|
5046
|
+
function normalizeOpenExpose(value) {
|
|
5047
|
+
if (!Array.isArray(value)) return [];
|
|
5048
|
+
const out = [];
|
|
5049
|
+
for (const entry of value) {
|
|
5050
|
+
if (typeof entry === "string") {
|
|
5051
|
+
if (entry) out.push(entry);
|
|
5052
|
+
} else if (entry && typeof entry === "object") {
|
|
5053
|
+
const name = entry.name;
|
|
5054
|
+
if (typeof name === "string" && name) out.push(name);
|
|
5055
|
+
}
|
|
5056
|
+
}
|
|
5057
|
+
return out;
|
|
5058
|
+
}
|
|
5059
|
+
function extractMiddleware(container) {
|
|
5060
|
+
if (!container || typeof container !== "object") return void 0;
|
|
5061
|
+
const raw = container.middleware;
|
|
5062
|
+
if (!Array.isArray(raw)) return void 0;
|
|
5063
|
+
const out = [];
|
|
5064
|
+
for (const entry of raw) {
|
|
5065
|
+
if (!entry || typeof entry !== "object") continue;
|
|
5066
|
+
const type = entry.type;
|
|
5067
|
+
if (typeof type !== "string" || type.length === 0) continue;
|
|
5068
|
+
const enabled = entry.enabled;
|
|
5069
|
+
const rawAllowed = entry.allowedTools;
|
|
5070
|
+
const allowedTools = Array.isArray(rawAllowed) ? rawAllowed.filter((t2) => typeof t2 === "string" && t2.length > 0) : void 0;
|
|
5071
|
+
out.push({ type, enabled: typeof enabled === "boolean" ? enabled : void 0, allowedTools });
|
|
5072
|
+
}
|
|
5073
|
+
return out;
|
|
5074
|
+
}
|
|
5075
|
+
function extractSubAgents(config) {
|
|
5076
|
+
if (!config || typeof config !== "object") return void 0;
|
|
5077
|
+
const raw = config.subAgents;
|
|
5078
|
+
if (!Array.isArray(raw)) return void 0;
|
|
5079
|
+
const out = raw.filter((id3) => typeof id3 === "string" && id3.length > 0);
|
|
5080
|
+
return out.length > 0 ? out : void 0;
|
|
5081
|
+
}
|
|
5082
|
+
async function computeGrants(tenantId, assistantId, deps) {
|
|
5083
|
+
await deps.ensure?.(tenantId);
|
|
5084
|
+
let context = await deps.getAgentConfig?.(tenantId, assistantId);
|
|
5085
|
+
if (context === void 0) {
|
|
5086
|
+
const middleware = await deps.getAssistantMiddleware?.(tenantId, assistantId);
|
|
5087
|
+
if (middleware === void 0) return [];
|
|
5088
|
+
context = { middleware };
|
|
5089
|
+
}
|
|
5090
|
+
const byDomain = /* @__PURE__ */ new Map();
|
|
5091
|
+
const add = (domain, items) => {
|
|
5092
|
+
let bucket = byDomain.get(domain);
|
|
5093
|
+
if (!bucket) {
|
|
5094
|
+
bucket = /* @__PURE__ */ new Set();
|
|
5095
|
+
byDomain.set(domain, bucket);
|
|
5096
|
+
}
|
|
5097
|
+
for (const item of items) bucket.add(item);
|
|
5098
|
+
};
|
|
5099
|
+
for (const entry of context.middleware ?? []) {
|
|
5100
|
+
if (!entry || entry.enabled === false) continue;
|
|
5101
|
+
if (typeof entry.type !== "string" || entry.type.length === 0) continue;
|
|
5102
|
+
let actions = deps.exposedActionsByType(entry.type);
|
|
5103
|
+
if (actions.length === 0) continue;
|
|
5104
|
+
const allowedTools = entry.allowedTools;
|
|
5105
|
+
if (Array.isArray(allowedTools) && allowedTools.length > 0) {
|
|
5106
|
+
const allowed = new Set(allowedTools);
|
|
5107
|
+
actions = actions.filter((action) => allowed.has(action));
|
|
5108
|
+
if (actions.length === 0) continue;
|
|
5109
|
+
}
|
|
5110
|
+
add(entry.type, actions);
|
|
5111
|
+
}
|
|
5112
|
+
const subAgents = context.subAgents ?? [];
|
|
5113
|
+
if (subAgents.length > 0 && deps.resolvableAssistants) {
|
|
5114
|
+
const resolvable = await deps.resolvableAssistants(tenantId);
|
|
5115
|
+
const kept = subAgents.filter(
|
|
5116
|
+
(id3) => typeof id3 === "string" && id3.length > 0 && resolvable.has(id3)
|
|
5117
|
+
);
|
|
5118
|
+
if (kept.length > 0) add("agent", kept);
|
|
5119
|
+
}
|
|
5120
|
+
return [...byDomain].map(([domain, items]) => ({ domain, items: [...items] }));
|
|
5121
|
+
}
|
|
5122
|
+
async function resolveAgentOpenGrants(tenantId, assistantId, deps) {
|
|
5123
|
+
try {
|
|
5124
|
+
const key = `${tenantId}:${assistantId}`;
|
|
5125
|
+
const now = deps.now ? deps.now() : Date.now();
|
|
5126
|
+
const hit = cache.get(key);
|
|
5127
|
+
if (hit && hit.expiresAt > now) return cloneGrants(hit.grants);
|
|
5128
|
+
const grants = await computeGrants(tenantId, assistantId, deps);
|
|
5129
|
+
cache.set(key, { grants, expiresAt: now + AGENT_REFLECTION_CACHE_TTL_MS });
|
|
5130
|
+
return cloneGrants(grants);
|
|
5131
|
+
} catch {
|
|
5132
|
+
return [];
|
|
5133
|
+
}
|
|
5134
|
+
}
|
|
5135
|
+
function createDefaultAgentReflectionDeps(tenantId) {
|
|
5136
|
+
(0, import_core88.ensureBuiltinAgentsForTenant)(tenantId);
|
|
5137
|
+
return {
|
|
5138
|
+
ensure: (t2) => import_core88.agentLatticeManager.initializeStoredAssistantsForTenant(t2),
|
|
5139
|
+
getAgentConfig: (t2, assistantId) => {
|
|
5140
|
+
const config = import_core88.agentLatticeManager.getAgentConfigWithTenant(t2, assistantId);
|
|
5141
|
+
if (!config) return void 0;
|
|
5142
|
+
return {
|
|
5143
|
+
middleware: extractMiddleware(config),
|
|
5144
|
+
subAgents: extractSubAgents(config)
|
|
5145
|
+
};
|
|
5146
|
+
},
|
|
5147
|
+
getAssistantMiddleware: async (t2, assistantId) => {
|
|
5148
|
+
const store2 = (0, import_core88.getStoreLattice)("default", "assistant").store;
|
|
5149
|
+
const assistant = await store2.getAssistantById(t2, assistantId);
|
|
5150
|
+
return extractMiddleware(assistant?.graphDefinition);
|
|
5151
|
+
},
|
|
5152
|
+
exposedActionsByType: (type) => {
|
|
5153
|
+
const plugin = import_core88.PluginRegistry.get(type);
|
|
5154
|
+
return plugin ? normalizeOpenExpose(plugin.meta.openExpose) : [];
|
|
5155
|
+
},
|
|
5156
|
+
resolvableAssistants: async (t2) => new Set(
|
|
5157
|
+
import_core88.agentLatticeManager.getAllAgentLatticesByTenant(t2).map((lattice) => lattice.config.key)
|
|
5158
|
+
)
|
|
5159
|
+
};
|
|
5160
|
+
}
|
|
5161
|
+
function mergeGrantsByDomain(grants) {
|
|
5162
|
+
const order = [];
|
|
5163
|
+
const items = /* @__PURE__ */ new Map();
|
|
5164
|
+
const unrestricted = /* @__PURE__ */ new Set();
|
|
5165
|
+
for (const grant of grants) {
|
|
5166
|
+
if (!grant || typeof grant.domain !== "string" || grant.domain.length === 0) continue;
|
|
5167
|
+
if (!items.has(grant.domain)) {
|
|
5168
|
+
items.set(grant.domain, /* @__PURE__ */ new Set());
|
|
5169
|
+
order.push(grant.domain);
|
|
5170
|
+
}
|
|
5171
|
+
if (!grant.items || grant.items.length === 0) {
|
|
5172
|
+
unrestricted.add(grant.domain);
|
|
5173
|
+
continue;
|
|
5174
|
+
}
|
|
5175
|
+
const bucket = items.get(grant.domain);
|
|
5176
|
+
if (!bucket) continue;
|
|
5177
|
+
for (const item of grant.items) {
|
|
5178
|
+
if (typeof item === "string" && item.length > 0) bucket.add(item);
|
|
5179
|
+
}
|
|
5180
|
+
}
|
|
5181
|
+
return order.map((domain) => {
|
|
5182
|
+
if (unrestricted.has(domain)) return { domain };
|
|
5183
|
+
return { domain, items: [...items.get(domain) ?? []] };
|
|
5184
|
+
});
|
|
5185
|
+
}
|
|
5186
|
+
async function computePluginGrants(tenantId, deps) {
|
|
5187
|
+
const grants = [...deps.globalExposedDomains?.() ?? []];
|
|
5188
|
+
if (deps.tenantExposedDomains) {
|
|
5189
|
+
grants.push(...await deps.tenantExposedDomains(tenantId));
|
|
5190
|
+
}
|
|
5191
|
+
if (deps.resolvableAssistants) {
|
|
5192
|
+
const resolvable = await deps.resolvableAssistants(tenantId);
|
|
5193
|
+
if (resolvable.size > 0) {
|
|
5194
|
+
grants.push({ domain: "agent", items: [...resolvable] });
|
|
5195
|
+
}
|
|
5196
|
+
}
|
|
5197
|
+
return mergeGrantsByDomain(grants);
|
|
5198
|
+
}
|
|
5199
|
+
async function resolvePluginOpenGrants(tenantId, deps) {
|
|
5200
|
+
try {
|
|
5201
|
+
const now = deps.now ? deps.now() : Date.now();
|
|
5202
|
+
const hit = pluginCache.get(tenantId);
|
|
5203
|
+
if (hit && hit.expiresAt > now) return cloneGrants(hit.grants);
|
|
5204
|
+
await deps.ensure?.(tenantId);
|
|
5205
|
+
const grants = await computePluginGrants(tenantId, deps);
|
|
5206
|
+
pluginCache.set(tenantId, { grants, expiresAt: now + PLUGIN_REFLECTION_CACHE_TTL_MS });
|
|
5207
|
+
return cloneGrants(grants);
|
|
5208
|
+
} catch {
|
|
5209
|
+
return [];
|
|
5210
|
+
}
|
|
5211
|
+
}
|
|
5212
|
+
function buildTenantExposedGrants(manifests) {
|
|
5213
|
+
const grants = [];
|
|
5214
|
+
for (const manifest of manifests) {
|
|
5215
|
+
const items = (manifest.tools ?? []).filter((tool) => tool.expose === true).map((tool) => tool.name);
|
|
5216
|
+
if (items.length > 0) grants.push({ domain: manifest.type, items });
|
|
5217
|
+
}
|
|
5218
|
+
return grants;
|
|
5219
|
+
}
|
|
5220
|
+
function createDefaultPluginReflectionDeps() {
|
|
5221
|
+
return {
|
|
5222
|
+
ensure: (tenantId) => import_core88.agentLatticeManager.initializeStoredAssistantsForTenant(tenantId),
|
|
5223
|
+
globalExposedDomains: () => {
|
|
5224
|
+
const grants = [];
|
|
5225
|
+
for (const type of import_core88.PluginRegistry.list()) {
|
|
5226
|
+
const plugin = import_core88.PluginRegistry.get(type);
|
|
5227
|
+
const items = normalizeOpenExpose(plugin?.meta.openExpose);
|
|
5228
|
+
if (items.length > 0) grants.push({ domain: type, items });
|
|
5229
|
+
}
|
|
5230
|
+
return grants;
|
|
5231
|
+
},
|
|
5232
|
+
tenantExposedDomains: async (tenantId) => {
|
|
5233
|
+
const { manifests } = await (0, import_core88.getSandboxPluginCatalog)().ensureLoaded(tenantId);
|
|
5234
|
+
return buildTenantExposedGrants(Object.values(manifests));
|
|
5235
|
+
},
|
|
5236
|
+
resolvableAssistants: async (tenantId) => new Set(
|
|
5237
|
+
import_core88.agentLatticeManager.getAllAgentLatticesByTenant(tenantId).map((lattice) => lattice.config.key)
|
|
5238
|
+
)
|
|
5239
|
+
};
|
|
5240
|
+
}
|
|
5241
|
+
var import_core88, AGENT_REFLECTION_CACHE_TTL_MS, cache, PLUGIN_REFLECTION_CACHE_TTL_MS, pluginCache;
|
|
5242
|
+
var init_sandboxOpenReflection = __esm({
|
|
5243
|
+
"src/services/open/sandboxOpenReflection.ts"() {
|
|
5244
|
+
"use strict";
|
|
5245
|
+
import_core88 = require("@axiom-lattice/core");
|
|
5246
|
+
AGENT_REFLECTION_CACHE_TTL_MS = 6e4;
|
|
5247
|
+
cache = /* @__PURE__ */ new Map();
|
|
5248
|
+
PLUGIN_REFLECTION_CACHE_TTL_MS = 6e4;
|
|
5249
|
+
pluginCache = /* @__PURE__ */ new Map();
|
|
5250
|
+
}
|
|
5251
|
+
});
|
|
5252
|
+
|
|
5253
|
+
// src/services/open/sandboxOpenCredentialProvider.ts
|
|
5254
|
+
var sandboxOpenCredentialProvider_exports = {};
|
|
5255
|
+
__export(sandboxOpenCredentialProvider_exports, {
|
|
5256
|
+
DEFAULT_SANDBOX_OPEN_GRANTS: () => DEFAULT_SANDBOX_OPEN_GRANTS,
|
|
5257
|
+
MAX_SANDBOX_OPEN_DEPTH: () => MAX_SANDBOX_OPEN_DEPTH,
|
|
5258
|
+
createSandboxOpenCredentialProvider: () => createSandboxOpenCredentialProvider,
|
|
5259
|
+
registerGatewaySandboxOpenCredentialProvider: () => registerGatewaySandboxOpenCredentialProvider
|
|
5260
|
+
});
|
|
5261
|
+
function defaultReflection() {
|
|
5262
|
+
return {
|
|
5263
|
+
agent: (tenantId, assistantId) => resolveAgentOpenGrants(tenantId, assistantId, createDefaultAgentReflectionDeps(tenantId)),
|
|
5264
|
+
plugin: (tenantId) => resolvePluginOpenGrants(tenantId, createDefaultPluginReflectionDeps())
|
|
5265
|
+
};
|
|
5266
|
+
}
|
|
5267
|
+
function createSandboxOpenCredentialProvider(options) {
|
|
5268
|
+
const reflection = options.reflection ?? defaultReflection();
|
|
5269
|
+
return async (context) => {
|
|
5270
|
+
if (!options.gatewayUrl) return void 0;
|
|
5271
|
+
const depth = (context.depth ?? 0) + 1;
|
|
5272
|
+
if (depth > MAX_SANDBOX_OPEN_DEPTH) {
|
|
5273
|
+
options.onError?.(new Error("sandbox open credential depth exceeded"));
|
|
5274
|
+
return void 0;
|
|
5275
|
+
}
|
|
5276
|
+
const reflected = context.assistantId ? await reflection.agent(context.tenantId, context.assistantId) : await reflection.plugin(context.tenantId);
|
|
5277
|
+
const grants = mergeGrantsByDomain([...DEFAULT_SANDBOX_OPEN_GRANTS, ...reflected]);
|
|
5278
|
+
const token = signOpenToken({
|
|
5279
|
+
kind: "sandbox_token",
|
|
5280
|
+
tenantId: context.tenantId,
|
|
5281
|
+
workspaceId: context.workspaceId ?? "",
|
|
5282
|
+
projectId: context.projectId ?? "",
|
|
5283
|
+
sandboxName: context.sandboxName,
|
|
5284
|
+
grants,
|
|
5285
|
+
depth
|
|
5286
|
+
});
|
|
5287
|
+
return { gatewayUrl: options.gatewayUrl, token };
|
|
5288
|
+
};
|
|
5289
|
+
}
|
|
5290
|
+
function registerGatewaySandboxOpenCredentialProvider(onError) {
|
|
5291
|
+
return (0, import_core89.registerSandboxOpenCredentialProvider)(
|
|
5292
|
+
createSandboxOpenCredentialProvider({
|
|
5293
|
+
gatewayUrl: process.env.PUBLIC_GATEWAY_URL?.trim() || void 0,
|
|
5294
|
+
onError
|
|
5295
|
+
}),
|
|
5296
|
+
{ onError }
|
|
5297
|
+
);
|
|
5298
|
+
}
|
|
5299
|
+
var import_core89, DEFAULT_SANDBOX_OPEN_GRANTS, MAX_SANDBOX_OPEN_DEPTH;
|
|
5300
|
+
var init_sandboxOpenCredentialProvider = __esm({
|
|
5301
|
+
"src/services/open/sandboxOpenCredentialProvider.ts"() {
|
|
5302
|
+
"use strict";
|
|
5303
|
+
import_core89 = require("@axiom-lattice/core");
|
|
5304
|
+
init_openToken();
|
|
5305
|
+
init_sandboxOpenReflection();
|
|
5306
|
+
DEFAULT_SANDBOX_OPEN_GRANTS = [
|
|
5307
|
+
{ domain: "sandbox", items: ["files_read", "files_list", "files_write", "shell_exec"] },
|
|
5308
|
+
{ domain: "kb", items: ["search", "entries_read"] }
|
|
5309
|
+
];
|
|
5310
|
+
MAX_SANDBOX_OPEN_DEPTH = 5;
|
|
5311
|
+
}
|
|
5312
|
+
});
|
|
5313
|
+
|
|
4992
5314
|
// src/services/open/sandboxGrants.ts
|
|
4993
5315
|
function sanitizeShareOpenGrants(grants) {
|
|
4994
5316
|
const out = [];
|
|
@@ -5015,12 +5337,12 @@ var resources_exports = {};
|
|
|
5015
5337
|
__export(resources_exports, {
|
|
5016
5338
|
ResourceController: () => ResourceController
|
|
5017
5339
|
});
|
|
5018
|
-
var import_bcryptjs,
|
|
5340
|
+
var import_bcryptjs, import_core90, ResourceController;
|
|
5019
5341
|
var init_resources = __esm({
|
|
5020
5342
|
"src/controllers/resources.ts"() {
|
|
5021
5343
|
"use strict";
|
|
5022
5344
|
import_bcryptjs = __toESM(require("bcryptjs"));
|
|
5023
|
-
|
|
5345
|
+
import_core90 = require("@axiom-lattice/core");
|
|
5024
5346
|
init_mime();
|
|
5025
5347
|
init_http_range();
|
|
5026
5348
|
init_sandboxGrants();
|
|
@@ -5037,14 +5359,14 @@ var init_resources = __esm({
|
|
|
5037
5359
|
if (!workspaceId || !projectId) {
|
|
5038
5360
|
return reply.status(400).send({ error: "x-workspace-id and x-project-id headers required" });
|
|
5039
5361
|
}
|
|
5040
|
-
const payload = (0,
|
|
5362
|
+
const payload = (0, import_core90.createSharePayload)(
|
|
5041
5363
|
tenantId,
|
|
5042
5364
|
workspaceId,
|
|
5043
5365
|
projectId,
|
|
5044
5366
|
userId,
|
|
5045
5367
|
body
|
|
5046
5368
|
);
|
|
5047
|
-
const token = (0,
|
|
5369
|
+
const token = (0, import_core90.generateToken)();
|
|
5048
5370
|
try {
|
|
5049
5371
|
await this.deps.store.create({ ...payload, token });
|
|
5050
5372
|
this.deps.logger.info(
|
|
@@ -5196,7 +5518,7 @@ var init_resources = __esm({
|
|
|
5196
5518
|
resourcePath: subPath
|
|
5197
5519
|
}, subPath, ext, request, reply);
|
|
5198
5520
|
}
|
|
5199
|
-
const volume = (0,
|
|
5521
|
+
const volume = (0, import_core90.buildNamedVolumeName)("p", "project", tenantId, workspaceId, projectId);
|
|
5200
5522
|
return this._resolveAndServe(
|
|
5201
5523
|
volume,
|
|
5202
5524
|
subPath,
|
|
@@ -5408,8 +5730,13 @@ var init_resources = __esm({
|
|
|
5408
5730
|
var index_exports = {};
|
|
5409
5731
|
__export(index_exports, {
|
|
5410
5732
|
LatticeGateway: () => LatticeGateway,
|
|
5733
|
+
ProjectRoomEventBroker: () => ProjectRoomEventBroker,
|
|
5734
|
+
ROOM_EVENT_TOPIC: () => ROOM_EVENT_TOPIC,
|
|
5411
5735
|
createOrphanRecoveryRuntime: () => createOrphanRecoveryRuntime,
|
|
5412
5736
|
createRecoveryCallerDeps: () => createRecoveryCallerDeps,
|
|
5737
|
+
createTaskRunLiveness: () => createTaskRunLiveness,
|
|
5738
|
+
ingestRoomEvent: () => ingestRoomEvent,
|
|
5739
|
+
publishRoomEvent: () => publishRoomEvent,
|
|
5413
5740
|
recoverTask: () => recoverTask,
|
|
5414
5741
|
recoverTopCaller: () => recoverTopCaller,
|
|
5415
5742
|
resolveTopCaller: () => resolveTopCaller,
|
|
@@ -6324,6 +6651,24 @@ async function writeSse(raw, value, closed) {
|
|
|
6324
6651
|
}
|
|
6325
6652
|
|
|
6326
6653
|
// src/controllers/run.ts
|
|
6654
|
+
var replicaHeader = () => ({ [import_protocols2.REPLICA_HEADER]: (0, import_core3.getReplicaId)() });
|
|
6655
|
+
var exposeHeaders = `${import_protocols2.REPLICA_HEADER}, ${import_protocols2.AFFINITY_ECHO_HEADER}`;
|
|
6656
|
+
function applyAffinityEcho(request, reply) {
|
|
6657
|
+
for (const [name, value] of Object.entries((0, import_protocols2.affinityEchoHeaders)(request.headers[import_protocols2.AGENT_AFFINITY_HEADER]))) {
|
|
6658
|
+
reply.header(name, value);
|
|
6659
|
+
}
|
|
6660
|
+
}
|
|
6661
|
+
var AFFINITY_GRACE_MS = Number.isFinite(Number(process.env.AXIOM_AFFINITY_GRACE_MS)) ? Number(process.env.AXIOM_AFFINITY_GRACE_MS) : 500;
|
|
6662
|
+
async function peerOwnsThread(input) {
|
|
6663
|
+
if (!process.env.AXIOM_REPLICA_ID) return null;
|
|
6664
|
+
if (!input.tenant_id || !input.assistant_id || !input.thread_id) return null;
|
|
6665
|
+
const owner = await (0, import_core3.getThreadRunOwner)({
|
|
6666
|
+
tenantId: input.tenant_id,
|
|
6667
|
+
assistantId: input.assistant_id,
|
|
6668
|
+
threadId: input.thread_id
|
|
6669
|
+
});
|
|
6670
|
+
return owner && owner !== (0, import_core3.getReplicaId)() ? owner : null;
|
|
6671
|
+
}
|
|
6327
6672
|
function getUserId2(request) {
|
|
6328
6673
|
const authUser = request.user;
|
|
6329
6674
|
if (authUser?.id) return authUser.id;
|
|
@@ -6350,6 +6695,7 @@ var createRun = async (request, reply) => {
|
|
|
6350
6695
|
...user_id && { user_id }
|
|
6351
6696
|
};
|
|
6352
6697
|
if (!assistant_id) {
|
|
6698
|
+
applyAffinityEcho(request, reply);
|
|
6353
6699
|
reply.status(400).send({
|
|
6354
6700
|
success: false,
|
|
6355
6701
|
error: "\u52A9\u624BID\u662F\u5FC5\u9700\u7684"
|
|
@@ -6371,6 +6717,8 @@ var createRun = async (request, reply) => {
|
|
|
6371
6717
|
command,
|
|
6372
6718
|
custom_run_config: mergedConfig
|
|
6373
6719
|
}, mode);
|
|
6720
|
+
reply.header(import_protocols2.REPLICA_HEADER, (0, import_core3.getReplicaId)());
|
|
6721
|
+
applyAffinityEcho(request, reply);
|
|
6374
6722
|
reply.status(202).send({
|
|
6375
6723
|
success: true,
|
|
6376
6724
|
messageId: result.messageId,
|
|
@@ -6384,7 +6732,10 @@ var createRun = async (request, reply) => {
|
|
|
6384
6732
|
"Content-Type": "text/event-stream",
|
|
6385
6733
|
"Cache-Control": "no-cache",
|
|
6386
6734
|
Connection: "keep-alive",
|
|
6387
|
-
"Access-Control-Allow-Origin": "*"
|
|
6735
|
+
"Access-Control-Allow-Origin": "*",
|
|
6736
|
+
"Access-Control-Expose-Headers": exposeHeaders,
|
|
6737
|
+
...replicaHeader(),
|
|
6738
|
+
...(0, import_protocols2.affinityEchoHeaders)(request.headers[import_protocols2.AGENT_AFFINITY_HEADER])
|
|
6388
6739
|
});
|
|
6389
6740
|
try {
|
|
6390
6741
|
const messageInput = message_id ? { ...input, id: message_id } : input;
|
|
@@ -6395,6 +6746,18 @@ var createRun = async (request, reply) => {
|
|
|
6395
6746
|
}, [import_protocols2.MessageChunkTypes.MESSAGE_COMPLETED, import_protocols2.MessageChunkTypes.INTERRUPT, import_protocols2.MessageChunkTypes.MESSAGE_FAILED], {
|
|
6396
6747
|
queueMode: mode
|
|
6397
6748
|
});
|
|
6749
|
+
let peer = await peerOwnsThread({ tenant_id, assistant_id, thread_id });
|
|
6750
|
+
if (peer) {
|
|
6751
|
+
await new Promise((resolve4) => setTimeout(resolve4, AFFINITY_GRACE_MS));
|
|
6752
|
+
peer = await peerOwnsThread({ tenant_id, assistant_id, thread_id });
|
|
6753
|
+
}
|
|
6754
|
+
if (peer) {
|
|
6755
|
+
reply.raw.write(`data: ${JSON.stringify((0, import_protocols2.buildAffinityMissChunk)(peer, thread_id))}
|
|
6756
|
+
|
|
6757
|
+
`);
|
|
6758
|
+
reply.raw.end();
|
|
6759
|
+
return;
|
|
6760
|
+
}
|
|
6398
6761
|
await pipeAsyncIterableToSse(reply.raw, result.stream, {
|
|
6399
6762
|
onError: (error) => [{
|
|
6400
6763
|
type: "error",
|
|
@@ -6426,12 +6789,15 @@ var createRun = async (request, reply) => {
|
|
|
6426
6789
|
command,
|
|
6427
6790
|
custom_run_config: mergedConfig
|
|
6428
6791
|
});
|
|
6792
|
+
reply.header(import_protocols2.REPLICA_HEADER, (0, import_core3.getReplicaId)());
|
|
6793
|
+
applyAffinityEcho(request, reply);
|
|
6429
6794
|
reply.status(200).send({
|
|
6430
6795
|
success: true,
|
|
6431
6796
|
...result
|
|
6432
6797
|
});
|
|
6433
6798
|
}
|
|
6434
6799
|
} catch (error) {
|
|
6800
|
+
applyAffinityEcho(request, reply);
|
|
6435
6801
|
reply.status(500).send({
|
|
6436
6802
|
success: false,
|
|
6437
6803
|
error: `\u521B\u5EFA\u8FD0\u884C\u65F6\u53D1\u751F\u9519\u8BEF: ${error.message}`
|
|
@@ -6454,9 +6820,20 @@ var resumeStream = async (request, reply) => {
|
|
|
6454
6820
|
"Content-Type": "text/event-stream",
|
|
6455
6821
|
"Cache-Control": "no-cache",
|
|
6456
6822
|
Connection: "keep-alive",
|
|
6457
|
-
"Access-Control-Allow-Origin": "*"
|
|
6823
|
+
"Access-Control-Allow-Origin": "*",
|
|
6824
|
+
"Access-Control-Expose-Headers": exposeHeaders,
|
|
6825
|
+
...replicaHeader(),
|
|
6826
|
+
...(0, import_protocols2.affinityEchoHeaders)(request.headers[import_protocols2.AGENT_AFFINITY_HEADER])
|
|
6458
6827
|
});
|
|
6459
6828
|
try {
|
|
6829
|
+
const peer = await peerOwnsThread({ tenant_id, assistant_id, thread_id });
|
|
6830
|
+
if (peer) {
|
|
6831
|
+
reply.raw.write(`data: ${JSON.stringify((0, import_protocols2.buildAffinityMissChunk)(peer, thread_id))}
|
|
6832
|
+
|
|
6833
|
+
`);
|
|
6834
|
+
reply.raw.end();
|
|
6835
|
+
return;
|
|
6836
|
+
}
|
|
6460
6837
|
const agent = import_core3.agentInstanceManager.getAgent({
|
|
6461
6838
|
assistant_id,
|
|
6462
6839
|
thread_id,
|
|
@@ -6507,12 +6884,22 @@ var abortRun = async (request, reply) => {
|
|
|
6507
6884
|
workspace_id,
|
|
6508
6885
|
project_id
|
|
6509
6886
|
});
|
|
6887
|
+
const peer = await peerOwnsThread({ tenant_id, assistant_id: assistantId, thread_id: threadId });
|
|
6888
|
+
if (peer) {
|
|
6889
|
+
reply.header(import_protocols2.REPLICA_HEADER, (0, import_core3.getReplicaId)());
|
|
6890
|
+
applyAffinityEcho(request, reply);
|
|
6891
|
+
reply.status(409).send({ success: false, code: import_protocols2.AFFINITY_MISS_CODE, owner: peer, threadId });
|
|
6892
|
+
return;
|
|
6893
|
+
}
|
|
6510
6894
|
await agent.abort();
|
|
6895
|
+
reply.header(import_protocols2.REPLICA_HEADER, (0, import_core3.getReplicaId)());
|
|
6896
|
+
applyAffinityEcho(request, reply);
|
|
6511
6897
|
reply.status(200).send({
|
|
6512
6898
|
success: true,
|
|
6513
6899
|
message: "Agent aborted"
|
|
6514
6900
|
});
|
|
6515
6901
|
} catch (error) {
|
|
6902
|
+
applyAffinityEcho(request, reply);
|
|
6516
6903
|
reply.status(500).send({
|
|
6517
6904
|
success: false,
|
|
6518
6905
|
error: `Abort failed: ${error.message}`
|
|
@@ -6530,13 +6917,17 @@ var recoverRun = async (request, reply) => {
|
|
|
6530
6917
|
workspace_id,
|
|
6531
6918
|
project_id
|
|
6532
6919
|
});
|
|
6533
|
-
const { status } = await agent.resumeTask();
|
|
6920
|
+
const { status, leaseContended } = await agent.resumeTask();
|
|
6921
|
+
reply.header(import_protocols2.REPLICA_HEADER, (0, import_core3.getReplicaId)());
|
|
6922
|
+
applyAffinityEcho(request, reply);
|
|
6534
6923
|
reply.status(200).send({
|
|
6535
6924
|
success: true,
|
|
6536
6925
|
threadId,
|
|
6537
|
-
status
|
|
6926
|
+
status,
|
|
6927
|
+
...leaseContended ? { code: import_protocols2.AFFINITY_MISS_CODE } : {}
|
|
6538
6928
|
});
|
|
6539
6929
|
} catch (error) {
|
|
6930
|
+
applyAffinityEcho(request, reply);
|
|
6540
6931
|
reply.status(500).send({
|
|
6541
6932
|
success: false,
|
|
6542
6933
|
error: `Recover failed: ${error.message}`
|
|
@@ -13101,6 +13492,43 @@ function connectionRoutes(fastify2) {
|
|
|
13101
13492
|
// src/controllers/mcp-configs.ts
|
|
13102
13493
|
var import_core33 = require("@axiom-lattice/core");
|
|
13103
13494
|
var import_crypto8 = require("crypto");
|
|
13495
|
+
|
|
13496
|
+
// src/services/mcpConfigSync.ts
|
|
13497
|
+
var MCP_CONFIG_CHANGED_TOPIC = "mcp-config-changed";
|
|
13498
|
+
async function publishMcpConfigChanged(outbox, owner, tenantId, serverKey) {
|
|
13499
|
+
if (!tenantId || !serverKey) return;
|
|
13500
|
+
try {
|
|
13501
|
+
await outbox.append({
|
|
13502
|
+
topic: MCP_CONFIG_CHANGED_TOPIC,
|
|
13503
|
+
payload: { tenantId, serverKey },
|
|
13504
|
+
originReplicaId: owner
|
|
13505
|
+
});
|
|
13506
|
+
} catch {
|
|
13507
|
+
}
|
|
13508
|
+
}
|
|
13509
|
+
async function reconcileMcpConfigChange(payload, deps) {
|
|
13510
|
+
const tenantId = payload?.tenantId;
|
|
13511
|
+
const serverKey = payload?.serverKey;
|
|
13512
|
+
if (typeof tenantId !== "string" || tenantId.length === 0) return;
|
|
13513
|
+
if (typeof serverKey !== "string" || serverKey.length === 0) return;
|
|
13514
|
+
const config = await deps.store.getConfigByKey(tenantId, serverKey);
|
|
13515
|
+
if (!config || config.status !== "connected") {
|
|
13516
|
+
if (deps.manager.hasServer(tenantId, serverKey)) {
|
|
13517
|
+
await deps.manager.removeServer(tenantId, serverKey);
|
|
13518
|
+
}
|
|
13519
|
+
return;
|
|
13520
|
+
}
|
|
13521
|
+
const connection = deps.convertToConnection(config.config);
|
|
13522
|
+
deps.manager.registerServer(tenantId, serverKey, connection, {
|
|
13523
|
+
timeoutMs: config.config.timeout,
|
|
13524
|
+
maxAttempts: config.config.retryAttempts,
|
|
13525
|
+
selectedTools: config.selectedTools
|
|
13526
|
+
});
|
|
13527
|
+
await deps.manager.ensureConnected(tenantId, serverKey);
|
|
13528
|
+
await deps.manager.registerToolsToToolLattice(tenantId, serverKey, config.selectedTools);
|
|
13529
|
+
}
|
|
13530
|
+
|
|
13531
|
+
// src/controllers/mcp-configs.ts
|
|
13104
13532
|
function getTenantId11(request) {
|
|
13105
13533
|
const userTenantId = request.user?.tenantId;
|
|
13106
13534
|
if (userTenantId) {
|
|
@@ -13108,6 +13536,14 @@ function getTenantId11(request) {
|
|
|
13108
13536
|
}
|
|
13109
13537
|
return request.headers["x-tenant-id"] || "default";
|
|
13110
13538
|
}
|
|
13539
|
+
function broadcastMcpConfigChanged(tenantId, serverKey) {
|
|
13540
|
+
if (!tenantId || !serverKey) return;
|
|
13541
|
+
try {
|
|
13542
|
+
const outbox = (0, import_core33.getStoreLattice)("default", "outbox").store;
|
|
13543
|
+
void publishMcpConfigChanged(outbox, (0, import_core33.getReplicaId)(), tenantId, serverKey);
|
|
13544
|
+
} catch {
|
|
13545
|
+
}
|
|
13546
|
+
}
|
|
13111
13547
|
async function getMcpServerConfigList(request, reply) {
|
|
13112
13548
|
const tenantId = getTenantId11(request);
|
|
13113
13549
|
try {
|
|
@@ -13185,6 +13621,7 @@ async function createMcpServerConfig(request, reply) {
|
|
|
13185
13621
|
await store2.updateConfig(tenantId, id3, { status: "error" });
|
|
13186
13622
|
config.status = "error";
|
|
13187
13623
|
}
|
|
13624
|
+
broadcastMcpConfigChanged(tenantId, config.key);
|
|
13188
13625
|
reply.code(201);
|
|
13189
13626
|
return {
|
|
13190
13627
|
success: true,
|
|
@@ -13214,7 +13651,9 @@ async function updateMcpServerConfig(request, reply) {
|
|
|
13214
13651
|
message: "MCP server configuration not found"
|
|
13215
13652
|
};
|
|
13216
13653
|
}
|
|
13217
|
-
const
|
|
13654
|
+
const configChanged = updates.config !== void 0;
|
|
13655
|
+
const toolsChanged = updates.selectedTools !== void 0;
|
|
13656
|
+
const statusChanged = updates.status !== void 0;
|
|
13218
13657
|
const updated = await store2.updateConfig(tenantId, existing.id, updates);
|
|
13219
13658
|
if (!updated) {
|
|
13220
13659
|
return {
|
|
@@ -13222,7 +13661,7 @@ async function updateMcpServerConfig(request, reply) {
|
|
|
13222
13661
|
message: "Failed to update MCP server configuration"
|
|
13223
13662
|
};
|
|
13224
13663
|
}
|
|
13225
|
-
if (
|
|
13664
|
+
if (configChanged) {
|
|
13226
13665
|
try {
|
|
13227
13666
|
const connection = (0, import_core33.convertToConnection)(updated.config);
|
|
13228
13667
|
import_core33.mcpManager.registerServer(tenantId, key, connection, {
|
|
@@ -13238,6 +13677,22 @@ async function updateMcpServerConfig(request, reply) {
|
|
|
13238
13677
|
await store2.updateConfig(tenantId, existing.id, { status: "error" });
|
|
13239
13678
|
updated.status = "error";
|
|
13240
13679
|
}
|
|
13680
|
+
} else if (toolsChanged && import_core33.mcpManager.hasServer(tenantId, key)) {
|
|
13681
|
+
try {
|
|
13682
|
+
await import_core33.mcpManager.registerToolsToToolLattice(tenantId, key, updated.selectedTools);
|
|
13683
|
+
} catch (error) {
|
|
13684
|
+
console.warn("Failed to re-register MCP tools:", error);
|
|
13685
|
+
}
|
|
13686
|
+
}
|
|
13687
|
+
if (statusChanged && updated.status !== "connected" && import_core33.mcpManager.hasServer(tenantId, key)) {
|
|
13688
|
+
try {
|
|
13689
|
+
await import_core33.mcpManager.removeServer(tenantId, key);
|
|
13690
|
+
} catch (error) {
|
|
13691
|
+
console.warn("Failed to remove MCP server:", error);
|
|
13692
|
+
}
|
|
13693
|
+
}
|
|
13694
|
+
if (configChanged || toolsChanged || statusChanged) {
|
|
13695
|
+
broadcastMcpConfigChanged(tenantId, key);
|
|
13241
13696
|
}
|
|
13242
13697
|
return {
|
|
13243
13698
|
success: true,
|
|
@@ -13287,6 +13742,7 @@ async function deleteMcpServerConfig(request, reply) {
|
|
|
13287
13742
|
message: "Failed to delete MCP server configuration"
|
|
13288
13743
|
};
|
|
13289
13744
|
}
|
|
13745
|
+
broadcastMcpConfigChanged(tenantId, configKey);
|
|
13290
13746
|
return {
|
|
13291
13747
|
success: true,
|
|
13292
13748
|
message: "MCP server configuration deleted successfully"
|
|
@@ -13361,12 +13817,17 @@ async function listMcpServerTools(request, reply) {
|
|
|
13361
13817
|
message: "MCP server configuration not found"
|
|
13362
13818
|
};
|
|
13363
13819
|
}
|
|
13364
|
-
|
|
13820
|
+
const wasConnected = import_core33.mcpManager.isServerConnected(tenantId, key);
|
|
13821
|
+
if (!wasConnected) {
|
|
13365
13822
|
await connectAndRegisterTools(config);
|
|
13366
13823
|
}
|
|
13367
|
-
|
|
13824
|
+
const statusStale = config.status !== "connected";
|
|
13825
|
+
if (statusStale) {
|
|
13368
13826
|
await store2.updateConfig(tenantId, config.id, { status: "connected" });
|
|
13369
13827
|
}
|
|
13828
|
+
if (!wasConnected || statusStale) {
|
|
13829
|
+
broadcastMcpConfigChanged(tenantId, key);
|
|
13830
|
+
}
|
|
13370
13831
|
const tools = await import_core33.mcpManager.getServerTools(tenantId, key);
|
|
13371
13832
|
return {
|
|
13372
13833
|
success: true,
|
|
@@ -13401,6 +13862,7 @@ async function connectMcpServer(request, reply) {
|
|
|
13401
13862
|
const updated = await store2.updateConfig(tenantId, config.id, {
|
|
13402
13863
|
status: "connected"
|
|
13403
13864
|
});
|
|
13865
|
+
broadcastMcpConfigChanged(tenantId, key);
|
|
13404
13866
|
return {
|
|
13405
13867
|
success: true,
|
|
13406
13868
|
message: "MCP server connected successfully",
|
|
@@ -13414,6 +13876,7 @@ async function connectMcpServer(request, reply) {
|
|
|
13414
13876
|
if (config) {
|
|
13415
13877
|
await store2.updateConfig(tenantId, config.id, { status: "error" });
|
|
13416
13878
|
}
|
|
13879
|
+
broadcastMcpConfigChanged(tenantId, key);
|
|
13417
13880
|
return {
|
|
13418
13881
|
success: false,
|
|
13419
13882
|
message: `Failed to connect MCP server: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -13440,6 +13903,7 @@ async function disconnectMcpServer(request, reply) {
|
|
|
13440
13903
|
const updated = await store2.updateConfig(tenantId, config.id, {
|
|
13441
13904
|
status: "disconnected"
|
|
13442
13905
|
});
|
|
13906
|
+
broadcastMcpConfigChanged(tenantId, key);
|
|
13443
13907
|
return {
|
|
13444
13908
|
success: true,
|
|
13445
13909
|
message: "MCP server disconnected successfully",
|
|
@@ -15958,8 +16422,8 @@ function snapshotPlainObject(value) {
|
|
|
15958
16422
|
}
|
|
15959
16423
|
}
|
|
15960
16424
|
async function getInstallationStore() {
|
|
15961
|
-
const { getStoreLattice:
|
|
15962
|
-
const store2 =
|
|
16425
|
+
const { getStoreLattice: getStoreLattice39 } = await import("@axiom-lattice/core");
|
|
16426
|
+
const store2 = getStoreLattice39("default", "channelInstallation").store;
|
|
15963
16427
|
if (store2) return store2;
|
|
15964
16428
|
const { PostgreSQLChannelInstallationStore } = await import("@axiom-lattice/pg-stores");
|
|
15965
16429
|
const databaseUrl = process.env.DATABASE_URL;
|
|
@@ -17101,7 +17565,7 @@ function registerTaskRoutes(app2, controller) {
|
|
|
17101
17565
|
}
|
|
17102
17566
|
|
|
17103
17567
|
// src/routes/index.ts
|
|
17104
|
-
var
|
|
17568
|
+
var import_core54 = require("@axiom-lattice/core");
|
|
17105
17569
|
|
|
17106
17570
|
// src/controllers/tasks.ts
|
|
17107
17571
|
var import_protocols13 = require("@axiom-lattice/protocols");
|
|
@@ -17680,6 +18144,10 @@ var ProjectTaskExecutionService = class {
|
|
|
17680
18144
|
input.inputMessageId,
|
|
17681
18145
|
true
|
|
17682
18146
|
);
|
|
18147
|
+
if (resumed.leaseContended) {
|
|
18148
|
+
settlement.cleanup();
|
|
18149
|
+
return { kind: "deferred", task: input.task, thread: input.thread, messageId: input.inputMessageId };
|
|
18150
|
+
}
|
|
17683
18151
|
if (resumed.status === import_core44.ThreadStatus.INTERRUPTED && settlement.tryClaim()) {
|
|
17684
18152
|
settlement.cleanup();
|
|
17685
18153
|
const outcome2 = await this.settleInterruptedEvent(input.task, input.thread, input.inputMessageId);
|
|
@@ -19368,6 +19836,7 @@ var import_zod6 = require("zod");
|
|
|
19368
19836
|
// src/services/agent-web-app/AgentWebAppRuntimeService.ts
|
|
19369
19837
|
var import_node_crypto10 = require("crypto");
|
|
19370
19838
|
var import_protocols14 = require("@axiom-lattice/protocols");
|
|
19839
|
+
var import_core46 = require("@axiom-lattice/core");
|
|
19371
19840
|
init_task_file_refs();
|
|
19372
19841
|
function isRecord2(value) {
|
|
19373
19842
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -19530,6 +19999,20 @@ var AgentWebAppRuntimeService = class {
|
|
|
19530
19999
|
async resumeStream(webAppId, userId, threadId, messageId, selection) {
|
|
19531
20000
|
const runtime = await this.resolveRuntime(webAppId, selection);
|
|
19532
20001
|
await this.requireOwnedThread(runtime, userId, threadId);
|
|
20002
|
+
if (process.env.AXIOM_REPLICA_ID) {
|
|
20003
|
+
const owner = await (0, import_core46.getThreadRunOwner)({
|
|
20004
|
+
tenantId: runtime.webApp.tenantId,
|
|
20005
|
+
assistantId: runtime.webApp.assistantId,
|
|
20006
|
+
threadId
|
|
20007
|
+
});
|
|
20008
|
+
if (owner && owner !== (0, import_core46.getReplicaId)()) {
|
|
20009
|
+
return {
|
|
20010
|
+
stream: (async function* () {
|
|
20011
|
+
yield (0, import_protocols14.buildAffinityMissChunk)(owner, threadId);
|
|
20012
|
+
})()
|
|
20013
|
+
};
|
|
20014
|
+
}
|
|
20015
|
+
}
|
|
19533
20016
|
const agent = this.resolveAgent(runtime, threadId);
|
|
19534
20017
|
return { stream: agent.chunkStream(messageId, []) };
|
|
19535
20018
|
}
|
|
@@ -19875,6 +20358,7 @@ async function verifyWebAppToken(token, issuer, options = {}) {
|
|
|
19875
20358
|
|
|
19876
20359
|
// src/routes/agent-web-app-runtime.ts
|
|
19877
20360
|
var import_protocols15 = require("@axiom-lattice/protocols");
|
|
20361
|
+
var import_core47 = require("@axiom-lattice/core");
|
|
19878
20362
|
var idSchema = import_zod6.z.string().min(1).max(128);
|
|
19879
20363
|
var paramsSchema = import_zod6.z.object({ webAppId: idSchema }).strict();
|
|
19880
20364
|
var threadParamsSchema = import_zod6.z.object({ webAppId: idSchema, threadId: idSchema }).strict();
|
|
@@ -20023,7 +20507,7 @@ function registerAgentWebAppRuntimeRoutes(app2, deps) {
|
|
|
20023
20507
|
const identity = await resolveRuntimeIdentity(request, webAppId, identities);
|
|
20024
20508
|
const input = streamBodySchema.parse(request.body);
|
|
20025
20509
|
const result = await deps.service.streamMessage(webAppId, identity.userId, threadId, withPreview(input, identity.preview));
|
|
20026
|
-
beginSse(reply);
|
|
20510
|
+
beginSse(reply, request);
|
|
20027
20511
|
await pipeNativeWebAppStream(reply.raw, result.stream);
|
|
20028
20512
|
} catch (error) {
|
|
20029
20513
|
return normalizeError2(reply, error);
|
|
@@ -20035,7 +20519,7 @@ function registerAgentWebAppRuntimeRoutes(app2, deps) {
|
|
|
20035
20519
|
const identity = await resolveRuntimeIdentity(request, webAppId, identities);
|
|
20036
20520
|
const input = streamBodySchema.parse(request.body);
|
|
20037
20521
|
const result = await deps.service.streamMessage(webAppId, identity.userId, threadId, withPreview(input, identity.preview));
|
|
20038
|
-
beginSse(reply);
|
|
20522
|
+
beginSse(reply, request);
|
|
20039
20523
|
await pipeAgentWebAppStream(reply.raw, result.stream, result);
|
|
20040
20524
|
} catch (error) {
|
|
20041
20525
|
return normalizeError2(reply, error);
|
|
@@ -20047,7 +20531,7 @@ function registerAgentWebAppRuntimeRoutes(app2, deps) {
|
|
|
20047
20531
|
const identity = await resolveRuntimeIdentity(request, webAppId, identities);
|
|
20048
20532
|
const { messageId, projectId, modelKey: modelKey2 } = resumeSchema.parse(request.body);
|
|
20049
20533
|
const result = await deps.service.resumeStream(webAppId, identity.userId, threadId, messageId, withPreview({ projectId, modelKey: modelKey2 }, identity.preview));
|
|
20050
|
-
beginSse(reply);
|
|
20534
|
+
beginSse(reply, request);
|
|
20051
20535
|
await pipeNativeWebAppStream(reply.raw, result.stream);
|
|
20052
20536
|
} catch (error) {
|
|
20053
20537
|
return normalizeError2(reply, error);
|
|
@@ -20080,7 +20564,7 @@ function registerAgentWebAppRuntimeRoutes(app2, deps) {
|
|
|
20080
20564
|
const identity = await resolveRuntimeIdentity(request, webAppId, identities);
|
|
20081
20565
|
const { projectId, modelKey: modelKey2, message, response } = resumeBodySchema.parse(request.body);
|
|
20082
20566
|
const result = await deps.service.resumeInterrupt(webAppId, identity.userId, threadId, interruptId, withPreview({ projectId, modelKey: modelKey2 }, identity.preview), { message, response });
|
|
20083
|
-
beginSse(reply);
|
|
20567
|
+
beginSse(reply, request);
|
|
20084
20568
|
await pipeAgentWebAppStream(reply.raw, result.stream, result);
|
|
20085
20569
|
} catch (error) {
|
|
20086
20570
|
return normalizeError2(reply, error);
|
|
@@ -20308,6 +20792,10 @@ function registerAgentWebAppRuntimeRoutes(app2, deps) {
|
|
|
20308
20792
|
if (!threadId) throw new AgentWebAppRuntimeError("INVALID_REQUEST", 400, "thread_id is required");
|
|
20309
20793
|
const content = body.messages.map((message) => message.content).join("\n");
|
|
20310
20794
|
const { messageId } = await deps.service.enqueueMessage(webAppId, identity.userId, threadId, content, { projectId: body.projectId, modelKey: body.modelKey });
|
|
20795
|
+
reply.header(import_protocols15.REPLICA_HEADER, (0, import_core47.getReplicaId)());
|
|
20796
|
+
for (const [name, value] of Object.entries((0, import_protocols15.affinityEchoHeaders)(request.headers[import_protocols15.AGENT_AFFINITY_HEADER]))) {
|
|
20797
|
+
reply.header(name, value);
|
|
20798
|
+
}
|
|
20311
20799
|
return reply.code(202).send({ success: true, messageId, queued: true });
|
|
20312
20800
|
} catch (error) {
|
|
20313
20801
|
return normalizeError2(reply, error);
|
|
@@ -20328,7 +20816,7 @@ function registerAgentWebAppRuntimeRoutes(app2, deps) {
|
|
|
20328
20816
|
const identity = await resolveRuntimeIdentity(request, webAppId, identities);
|
|
20329
20817
|
const body = resumeStreamSchema2.parse(request.body ?? {});
|
|
20330
20818
|
const result = await deps.service.resumeStream(webAppId, identity.userId, body.thread_id, body.message_id, { projectId: body.projectId, modelKey: body.modelKey });
|
|
20331
|
-
beginSse(reply);
|
|
20819
|
+
beginSse(reply, request);
|
|
20332
20820
|
await pipeNativeWebAppStream(reply.raw, result.stream);
|
|
20333
20821
|
} catch (error) {
|
|
20334
20822
|
return normalizeError2(reply, error);
|
|
@@ -20381,14 +20869,17 @@ async function pipeNativeWebAppStream(raw, stream) {
|
|
|
20381
20869
|
}]
|
|
20382
20870
|
});
|
|
20383
20871
|
}
|
|
20384
|
-
function beginSse(reply) {
|
|
20872
|
+
function beginSse(reply, request) {
|
|
20385
20873
|
reply.hijack();
|
|
20386
20874
|
reply.raw.writeHead(200, {
|
|
20387
20875
|
"Content-Type": "text/event-stream; charset=utf-8",
|
|
20388
20876
|
"Cache-Control": "no-cache, no-transform",
|
|
20389
20877
|
Connection: "keep-alive",
|
|
20390
20878
|
"X-Accel-Buffering": "no",
|
|
20391
|
-
"Access-Control-Allow-Origin": "*"
|
|
20879
|
+
"Access-Control-Allow-Origin": "*",
|
|
20880
|
+
"Access-Control-Expose-Headers": `${import_protocols15.REPLICA_HEADER}, ${import_protocols15.AFFINITY_ECHO_HEADER}`,
|
|
20881
|
+
[import_protocols15.REPLICA_HEADER]: (0, import_core47.getReplicaId)(),
|
|
20882
|
+
...(0, import_protocols15.affinityEchoHeaders)(request.headers[import_protocols15.AGENT_AFFINITY_HEADER])
|
|
20392
20883
|
});
|
|
20393
20884
|
}
|
|
20394
20885
|
async function handle2(reply, operation) {
|
|
@@ -20624,7 +21115,7 @@ var import_zod9 = require("zod");
|
|
|
20624
21115
|
|
|
20625
21116
|
// src/services/capability/CapabilityBundleService.ts
|
|
20626
21117
|
var import_zod8 = require("zod");
|
|
20627
|
-
var
|
|
21118
|
+
var import_core48 = require("@axiom-lattice/core");
|
|
20628
21119
|
var CapabilityBundleServiceError = class extends Error {
|
|
20629
21120
|
constructor(code, message, statusCode) {
|
|
20630
21121
|
super(message);
|
|
@@ -20665,7 +21156,7 @@ function projectBundleIds(config) {
|
|
|
20665
21156
|
return [...value];
|
|
20666
21157
|
}
|
|
20667
21158
|
function issue(error) {
|
|
20668
|
-
if (error instanceof
|
|
21159
|
+
if (error instanceof import_core48.CapabilityBundleMergeError || error instanceof import_core48.CapabilityBundleValidationError) return { code: error instanceof import_core48.CapabilityBundleValidationError && error.code === "CAPABILITY_BUNDLE_INVALID_CONFIG" ? "INVALID_BUNDLE_CONFIG" : error.code, message: error.message, bundleId: error instanceof import_core48.CapabilityBundleMergeError ? error.bundleId : void 0, capabilityType: error.capabilityType, fieldPath: error.fieldPath };
|
|
20669
21160
|
return { code: "CAPABILITY_BUNDLE_CONFIGURATION_ERROR", message: error instanceof Error ? error.message : "Invalid capability bundle configuration" };
|
|
20670
21161
|
}
|
|
20671
21162
|
var CapabilityBundleService = class {
|
|
@@ -20678,7 +21169,7 @@ var CapabilityBundleService = class {
|
|
|
20678
21169
|
const errors = [];
|
|
20679
21170
|
for (const value of values) {
|
|
20680
21171
|
try {
|
|
20681
|
-
(0,
|
|
21172
|
+
(0, import_core48.validateCapabilityBundleInput)(value);
|
|
20682
21173
|
bundles.push(value);
|
|
20683
21174
|
} catch {
|
|
20684
21175
|
errors.push({ bundleId: value.id, code: "INVALID_BUNDLE_CONFIG", message: "Capability bundle record is invalid" });
|
|
@@ -20690,7 +21181,7 @@ var CapabilityBundleService = class {
|
|
|
20690
21181
|
const value = await this.deps.bundleStore.getById(tenantId, id3);
|
|
20691
21182
|
if (!value) throw new CapabilityBundleServiceError("BUNDLE_NOT_FOUND", "Capability bundle not found", 404);
|
|
20692
21183
|
try {
|
|
20693
|
-
(0,
|
|
21184
|
+
(0, import_core48.validateCapabilityBundleInput)(value);
|
|
20694
21185
|
} catch {
|
|
20695
21186
|
throw new CapabilityBundleServiceError("INVALID_BUNDLE_CONFIG", "Capability bundle record is invalid", 422);
|
|
20696
21187
|
}
|
|
@@ -20698,7 +21189,7 @@ var CapabilityBundleService = class {
|
|
|
20698
21189
|
}
|
|
20699
21190
|
async create(tenantId, input) {
|
|
20700
21191
|
rejectStableKey(input);
|
|
20701
|
-
(0,
|
|
21192
|
+
(0, import_core48.validateCapabilityBundleInput)(input);
|
|
20702
21193
|
const value = input;
|
|
20703
21194
|
const name = value.name.trim();
|
|
20704
21195
|
const base = slugify(name);
|
|
@@ -20709,10 +21200,10 @@ var CapabilityBundleService = class {
|
|
|
20709
21200
|
let suffix = 2;
|
|
20710
21201
|
while (keys2.has(key)) key = `${base}-${suffix++}`;
|
|
20711
21202
|
const normalized = { ...value, key, name };
|
|
20712
|
-
(0,
|
|
21203
|
+
(0, import_core48.validateCapabilityBundleInput)(normalized);
|
|
20713
21204
|
try {
|
|
20714
21205
|
const result = await this.deps.bundleStore.create(tenantId, normalized);
|
|
20715
|
-
(0,
|
|
21206
|
+
(0, import_core48.validateCapabilityBundleInput)(result);
|
|
20716
21207
|
return result;
|
|
20717
21208
|
} catch (error) {
|
|
20718
21209
|
if (!isDuplicate(error)) throw error;
|
|
@@ -20723,16 +21214,16 @@ var CapabilityBundleService = class {
|
|
|
20723
21214
|
}
|
|
20724
21215
|
async update(tenantId, id3, input) {
|
|
20725
21216
|
rejectStableKey(input);
|
|
20726
|
-
(0,
|
|
21217
|
+
(0, import_core48.validateCapabilityBundleInput)(input, { partial: true });
|
|
20727
21218
|
if (!input || typeof input !== "object" || Array.isArray(input) || typeof input.expectedUpdatedAt !== "string" || !input.expectedUpdatedAt.trim()) throw new CapabilityBundleServiceError("INVALID_BUNDLE_CONFIG", "expectedUpdatedAt is required for capability bundle updates", 400);
|
|
20728
21219
|
const value = input;
|
|
20729
21220
|
const normalized = { ...value, ...value.name === void 0 ? {} : { name: value.name.trim() }, ...Object.prototype.hasOwnProperty.call(value, "description") ? { description: value.description?.trim() || void 0 } : {} };
|
|
20730
|
-
(0,
|
|
21221
|
+
(0, import_core48.validateCapabilityBundleInput)(normalized, { partial: true });
|
|
20731
21222
|
try {
|
|
20732
21223
|
const result = await this.deps.bundleStore.update(tenantId, id3, normalized);
|
|
20733
21224
|
if (!result) throw new CapabilityBundleServiceError("BUNDLE_NOT_FOUND", "Capability bundle not found", 404);
|
|
20734
21225
|
if ("status" in result && result.status === "conflict") throw new CapabilityBundleServiceError("BUNDLE_CONFLICT", "Capability bundle changed after it was loaded; reload before saving", 409);
|
|
20735
|
-
(0,
|
|
21226
|
+
(0, import_core48.validateCapabilityBundleInput)(result);
|
|
20736
21227
|
return result;
|
|
20737
21228
|
} catch (error) {
|
|
20738
21229
|
if (error instanceof CapabilityBundleServiceError) throw error;
|
|
@@ -20767,8 +21258,8 @@ var CapabilityBundleService = class {
|
|
|
20767
21258
|
if (missing.length > 0) return { bundleIds: ids, capabilities: [], overrides: [], sources: [], warnings: [], errors: missing.map((id3) => ({ code: "BUNDLE_NOT_FOUND", message: `Persisted capability bundle '${id3}' is missing`, bundleId: id3 })), revision: "" };
|
|
20768
21259
|
try {
|
|
20769
21260
|
const ordered = ids.map((id3) => byId.get(id3));
|
|
20770
|
-
ordered.forEach((bundle) => (0,
|
|
20771
|
-
return (0,
|
|
21261
|
+
ordered.forEach((bundle) => (0, import_core48.validateCapabilityBundleInput)(bundle));
|
|
21262
|
+
return (0, import_core48.mergeCapabilityBundles)(ordered);
|
|
20772
21263
|
} catch (error) {
|
|
20773
21264
|
return { bundleIds: ids, capabilities: [], overrides: [], sources: [], warnings: [], errors: [issue(error)], revision: "" };
|
|
20774
21265
|
}
|
|
@@ -20801,7 +21292,7 @@ var CapabilityBundleService = class {
|
|
|
20801
21292
|
return ids.map((id3) => {
|
|
20802
21293
|
const value = byId.get(id3);
|
|
20803
21294
|
if (!value) throw new CapabilityBundleServiceError("BUNDLE_NOT_FOUND", "Capability bundle not found", 404);
|
|
20804
|
-
(0,
|
|
21295
|
+
(0, import_core48.validateCapabilityBundleInput)(value);
|
|
20805
21296
|
return value;
|
|
20806
21297
|
});
|
|
20807
21298
|
}
|
|
@@ -20816,7 +21307,7 @@ var CapabilityBundleService = class {
|
|
|
20816
21307
|
continue;
|
|
20817
21308
|
}
|
|
20818
21309
|
try {
|
|
20819
|
-
(0,
|
|
21310
|
+
(0, import_core48.validateCapabilityBundleInput)(bundle);
|
|
20820
21311
|
valid.push(bundle);
|
|
20821
21312
|
} catch (error) {
|
|
20822
21313
|
errors.push({ ...issue(error), bundleId: id3 });
|
|
@@ -20824,7 +21315,7 @@ var CapabilityBundleService = class {
|
|
|
20824
21315
|
}
|
|
20825
21316
|
let preview;
|
|
20826
21317
|
try {
|
|
20827
|
-
preview = (0,
|
|
21318
|
+
preview = (0, import_core48.mergeCapabilityBundles)(valid);
|
|
20828
21319
|
} catch (error) {
|
|
20829
21320
|
preview = { bundleIds: ids, capabilities: [], overrides: [], sources: [], warnings: [], errors: [issue(error)], revision: "" };
|
|
20830
21321
|
}
|
|
@@ -20976,7 +21467,7 @@ var import_zod11 = require("zod");
|
|
|
20976
21467
|
// src/services/model-provider/ModelProviderService.ts
|
|
20977
21468
|
var import_node_crypto14 = require("crypto");
|
|
20978
21469
|
var import_protocols16 = require("@axiom-lattice/protocols");
|
|
20979
|
-
var
|
|
21470
|
+
var import_core49 = require("@axiom-lattice/core");
|
|
20980
21471
|
|
|
20981
21472
|
// src/services/model-provider/errors.ts
|
|
20982
21473
|
var ModelProviderServiceError = class extends Error {
|
|
@@ -20989,6 +21480,17 @@ var ModelProviderServiceError = class extends Error {
|
|
|
20989
21480
|
this.name = "ModelProviderServiceError";
|
|
20990
21481
|
}
|
|
20991
21482
|
};
|
|
21483
|
+
var UPSTREAM_ERROR_CODES = {
|
|
21484
|
+
UPSTREAM_UNREACHABLE: true,
|
|
21485
|
+
UPSTREAM_AUTH_FAILED: true,
|
|
21486
|
+
UPSTREAM_REDIRECT_BLOCKED: true,
|
|
21487
|
+
UPSTREAM_INVALID_RESPONSE: true,
|
|
21488
|
+
UPSTREAM_RATE_LIMITED: true,
|
|
21489
|
+
UPSTREAM_TIMEOUT: true
|
|
21490
|
+
};
|
|
21491
|
+
function isUpstreamErrorCode(code) {
|
|
21492
|
+
return Object.prototype.hasOwnProperty.call(UPSTREAM_ERROR_CODES, code);
|
|
21493
|
+
}
|
|
20992
21494
|
|
|
20993
21495
|
// src/services/model-provider/discovery.ts
|
|
20994
21496
|
var MAX_DISCOVERED_MODELS = 1e3;
|
|
@@ -21264,6 +21766,33 @@ var ModelProviderService = class {
|
|
|
21264
21766
|
models
|
|
21265
21767
|
};
|
|
21266
21768
|
}
|
|
21769
|
+
/**
|
|
21770
|
+
* Hydrates the runtime model registry from the persisted provider catalog.
|
|
21771
|
+
*
|
|
21772
|
+
* @returns The model keys registered in this process.
|
|
21773
|
+
* @remarks Registers the Phase-1 (default tenant) enabled provider models so a
|
|
21774
|
+
* replica that did not perform discovery — or that restarted — can execute
|
|
21775
|
+
* them. Best-effort; the caller logs failures.
|
|
21776
|
+
*/
|
|
21777
|
+
async hydrateRegistry() {
|
|
21778
|
+
const tenantId = PHASE1_REGISTRY_TENANT;
|
|
21779
|
+
if (!this.shouldRegister(tenantId)) {
|
|
21780
|
+
return [];
|
|
21781
|
+
}
|
|
21782
|
+
const providers = await this.deps.providerStore.listProviders(tenantId);
|
|
21783
|
+
const registered = [];
|
|
21784
|
+
for (const provider of providers) {
|
|
21785
|
+
if (!provider.enabled) {
|
|
21786
|
+
continue;
|
|
21787
|
+
}
|
|
21788
|
+
const models = await this.deps.providerStore.listModels(
|
|
21789
|
+
tenantId,
|
|
21790
|
+
provider.id
|
|
21791
|
+
);
|
|
21792
|
+
registered.push(...this.syncRegistry(tenantId, provider, models));
|
|
21793
|
+
}
|
|
21794
|
+
return registered;
|
|
21795
|
+
}
|
|
21267
21796
|
/**
|
|
21268
21797
|
* Create a provider configuration. Does not run discovery.
|
|
21269
21798
|
*/
|
|
@@ -21503,7 +22032,7 @@ var ModelProviderService = class {
|
|
|
21503
22032
|
models
|
|
21504
22033
|
};
|
|
21505
22034
|
} catch (error) {
|
|
21506
|
-
if (error instanceof ModelProviderServiceError) {
|
|
22035
|
+
if (error instanceof ModelProviderServiceError && isUpstreamErrorCode(error.code)) {
|
|
21507
22036
|
return {
|
|
21508
22037
|
reachable: false,
|
|
21509
22038
|
latencyMs: Date.now() - startedAt,
|
|
@@ -21742,9 +22271,9 @@ var ModelProviderService = class {
|
|
|
21742
22271
|
*/
|
|
21743
22272
|
async assertSafeUrl(baseURL) {
|
|
21744
22273
|
try {
|
|
21745
|
-
await (0,
|
|
22274
|
+
await (0, import_core49.assertSafeUpstreamUrl)(baseURL);
|
|
21746
22275
|
} catch (error) {
|
|
21747
|
-
if (error instanceof
|
|
22276
|
+
if (error instanceof import_core49.UnsafeUpstreamUrlError) {
|
|
21748
22277
|
throw new ModelProviderServiceError(
|
|
21749
22278
|
unsafeReasonToErrorCode[error.reason],
|
|
21750
22279
|
400,
|
|
@@ -21920,6 +22449,10 @@ var ModelProviderController = class {
|
|
|
21920
22449
|
return sendError2(reply, error);
|
|
21921
22450
|
}
|
|
21922
22451
|
}
|
|
22452
|
+
/** Hydrates the runtime model registry from persisted providers (startup). */
|
|
22453
|
+
async hydrateRegistry() {
|
|
22454
|
+
return this.service.hydrateRegistry();
|
|
22455
|
+
}
|
|
21923
22456
|
/** GET /api/model-providers */
|
|
21924
22457
|
async listProviders(request, reply) {
|
|
21925
22458
|
try {
|
|
@@ -23206,7 +23739,7 @@ async function execute(reply, operation) {
|
|
|
23206
23739
|
// src/routes/cospace.ts
|
|
23207
23740
|
var import_node_crypto20 = require("crypto");
|
|
23208
23741
|
var import_zod15 = require("zod");
|
|
23209
|
-
var
|
|
23742
|
+
var import_core50 = require("@axiom-lattice/core");
|
|
23210
23743
|
var import_protocols19 = require("@axiom-lattice/protocols");
|
|
23211
23744
|
var CoSpaceAuthError = class extends Error {
|
|
23212
23745
|
constructor() {
|
|
@@ -23391,14 +23924,14 @@ function registerCoSpaceRoutes(app2, deps) {
|
|
|
23391
23924
|
}
|
|
23392
23925
|
let projectId;
|
|
23393
23926
|
if (body.type === "human") {
|
|
23394
|
-
projectId = (0,
|
|
23927
|
+
projectId = (0, import_core50.generateDirectHumanProjectId)(
|
|
23395
23928
|
actor3.tenantId,
|
|
23396
23929
|
params.workspaceId,
|
|
23397
23930
|
actor3.userId,
|
|
23398
23931
|
body.targetUserId
|
|
23399
23932
|
);
|
|
23400
23933
|
} else {
|
|
23401
|
-
projectId = (0,
|
|
23934
|
+
projectId = (0, import_core50.generateDirectBotProjectId)(
|
|
23402
23935
|
actor3.tenantId,
|
|
23403
23936
|
params.workspaceId,
|
|
23404
23937
|
actor3.userId,
|
|
@@ -23605,7 +24138,7 @@ function registerCoSpaceRoutes(app2, deps) {
|
|
|
23605
24138
|
);
|
|
23606
24139
|
const bots = [];
|
|
23607
24140
|
for (const assistant of assistants) {
|
|
23608
|
-
const directProjectId = (0,
|
|
24141
|
+
const directProjectId = (0, import_core50.generateDirectBotProjectId)(
|
|
23609
24142
|
actor3.tenantId,
|
|
23610
24143
|
params.workspaceId,
|
|
23611
24144
|
actor3.userId,
|
|
@@ -23667,7 +24200,7 @@ function registerCoSpaceRoutes(app2, deps) {
|
|
|
23667
24200
|
if (link.userId === actor3.userId) continue;
|
|
23668
24201
|
const user = await deps.userStore.getUserById(link.userId);
|
|
23669
24202
|
if (!user) continue;
|
|
23670
|
-
const directProjectId = (0,
|
|
24203
|
+
const directProjectId = (0, import_core50.generateDirectHumanProjectId)(
|
|
23671
24204
|
actor3.tenantId,
|
|
23672
24205
|
params.workspaceId,
|
|
23673
24206
|
actor3.userId,
|
|
@@ -24484,6 +25017,8 @@ function createRoomMessageRetentionJob(input) {
|
|
|
24484
25017
|
|
|
24485
25018
|
// src/services/collaboration/ProjectTaskExecutionMutex.ts
|
|
24486
25019
|
var import_protocols22 = require("@axiom-lattice/protocols");
|
|
25020
|
+
var import_core51 = require("@axiom-lattice/core");
|
|
25021
|
+
var MACHINE_LEASE_OPTIONS = { ttlMs: 6e4, acquireTimeoutMs: 9e4, retryDelayMs: 100 };
|
|
24487
25022
|
function machineKey(scope) {
|
|
24488
25023
|
const snapshot = (0, import_protocols22.snapshotExactRecord)(scope, ["tenantId", "assistantId", "projectId"]);
|
|
24489
25024
|
if (!snapshot) throw new Error("Invalid Project task machine scope");
|
|
@@ -24507,9 +25042,12 @@ var ProjectTaskExecutionMutex = class {
|
|
|
24507
25042
|
*/
|
|
24508
25043
|
async runExclusive(scope, operation, signal) {
|
|
24509
25044
|
const key = machineKey(scope);
|
|
25045
|
+
const leaseKey = `project-task-machine:${encodeURIComponent(scope.tenantId)}:${encodeURIComponent(scope.assistantId)}:${encodeURIComponent(scope.projectId)}`;
|
|
24510
25046
|
await this.acquire(key, signal);
|
|
24511
25047
|
try {
|
|
24512
|
-
|
|
25048
|
+
const store2 = (0, import_core51.getCoordinationLeaseStore)();
|
|
25049
|
+
if (!store2) return await operation();
|
|
25050
|
+
return await (0, import_core51.withLease)(store2, leaseKey, (0, import_core51.getReplicaId)(), operation, MACHINE_LEASE_OPTIONS);
|
|
24513
25051
|
} finally {
|
|
24514
25052
|
this.release(key);
|
|
24515
25053
|
}
|
|
@@ -24562,8 +25100,22 @@ var ProjectTaskExecutionMutex = class {
|
|
|
24562
25100
|
|
|
24563
25101
|
// src/services/collaboration/ProjectTaskObserver.ts
|
|
24564
25102
|
var import_node_crypto22 = require("crypto");
|
|
24565
|
-
var
|
|
25103
|
+
var import_core52 = require("@axiom-lattice/core");
|
|
24566
25104
|
var import_protocols23 = require("@axiom-lattice/protocols");
|
|
25105
|
+
|
|
25106
|
+
// src/services/collaboration/projectTaskDispatchMarker.ts
|
|
25107
|
+
var EXECUTION_REQUESTED_AT_KEY = "execution_requested_at";
|
|
25108
|
+
function hasExecutionRequest(task) {
|
|
25109
|
+
const value = task.context?.[EXECUTION_REQUESTED_AT_KEY];
|
|
25110
|
+
if (typeof value !== "string" || value.length === 0) return false;
|
|
25111
|
+
const parsed = new Date(value);
|
|
25112
|
+
return Number.isFinite(parsed.getTime()) && parsed.toISOString() === value;
|
|
25113
|
+
}
|
|
25114
|
+
function withExecutionRequest(context, nowIso) {
|
|
25115
|
+
return { ...context ?? {}, [EXECUTION_REQUESTED_AT_KEY]: nowIso };
|
|
25116
|
+
}
|
|
25117
|
+
|
|
25118
|
+
// src/services/collaboration/ProjectTaskObserver.ts
|
|
24567
25119
|
init_projectTaskScope();
|
|
24568
25120
|
var SYSTEM_ACTOR2 = "system";
|
|
24569
25121
|
var TERMINAL_ACTIONS = ["completed", "failed", "interrupted", "cancelled"];
|
|
@@ -24585,7 +25137,7 @@ var ProjectTaskObserver = class {
|
|
|
24585
25137
|
throw new Error(`Invalid Project task observer bound: ${name}`);
|
|
24586
25138
|
}
|
|
24587
25139
|
}
|
|
24588
|
-
this.runBridge = (0,
|
|
25140
|
+
this.runBridge = (0, import_core52.createTaskRunBridge)({ lifecycle: this.deps.lifecycle });
|
|
24589
25141
|
}
|
|
24590
25142
|
/** Fire-and-forget notifier adapter that never waits for observer work or machine acquisition. */
|
|
24591
25143
|
async listener(event) {
|
|
@@ -24768,7 +25320,7 @@ var ProjectTaskObserver = class {
|
|
|
24768
25320
|
return;
|
|
24769
25321
|
}
|
|
24770
25322
|
}
|
|
24771
|
-
if (intent === "dispatch" && await this.isReady(task) && !signal?.aborted && !this.disposed) {
|
|
25323
|
+
if ((intent === "dispatch" || hasExecutionRequest(task)) && await this.isReady(task) && !signal?.aborted && !this.disposed) {
|
|
24772
25324
|
await this.runStart(task, signal);
|
|
24773
25325
|
}
|
|
24774
25326
|
return;
|
|
@@ -24885,7 +25437,7 @@ var ProjectTaskObserver = class {
|
|
|
24885
25437
|
}, signal);
|
|
24886
25438
|
}
|
|
24887
25439
|
async mapOutcome(outcome2) {
|
|
24888
|
-
if (outcome2.kind === "aborted") return;
|
|
25440
|
+
if (outcome2.kind === "aborted" || outcome2.kind === "deferred") return;
|
|
24889
25441
|
const current = snapshotTaskItem(await this.deps.tasks.getById(outcome2.task.tenantId, outcome2.task.id));
|
|
24890
25442
|
if (!current || current.ownerId !== outcome2.thread.assistantId || current.context?.thread_id !== outcome2.thread.id) return;
|
|
24891
25443
|
if (isTerminal(current.status) || current.status === "review") return;
|
|
@@ -25801,7 +26353,7 @@ function isRecord3(value) {
|
|
|
25801
26353
|
init_projectTaskScope();
|
|
25802
26354
|
|
|
25803
26355
|
// src/services/collaboration/ProjectRoomRealtimeRuntime.ts
|
|
25804
|
-
var
|
|
26356
|
+
var import_core53 = require("@axiom-lattice/core");
|
|
25805
26357
|
|
|
25806
26358
|
// src/services/collaboration/ProjectRoomEventBroker.ts
|
|
25807
26359
|
var import_node_crypto24 = require("crypto");
|
|
@@ -25811,6 +26363,7 @@ var DEFAULT_MAX_EVENT_AGE_MS = 10 * 60 * 1e3;
|
|
|
25811
26363
|
var DEFAULT_MAX_ROOMS = 1e3;
|
|
25812
26364
|
var DEFAULT_MAX_GLOBAL_EVENTS = 1e5;
|
|
25813
26365
|
var DEFAULT_MAX_GLOBAL_BYTES = 64 * 1024 * 1024;
|
|
26366
|
+
var DEFAULT_SOURCE_KEY_LIMIT = 2e3;
|
|
25814
26367
|
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
25815
26368
|
var ProjectRoomBrokerResourceCapacityError = class extends Error {
|
|
25816
26369
|
constructor(resource) {
|
|
@@ -25824,6 +26377,7 @@ var ProjectRoomEventBroker = class {
|
|
|
25824
26377
|
constructor(options = {}) {
|
|
25825
26378
|
this.rooms = /* @__PURE__ */ new Map();
|
|
25826
26379
|
this.sequenceScopes = /* @__PURE__ */ new Map();
|
|
26380
|
+
this.seenSourceKeys = /* @__PURE__ */ new Map();
|
|
25827
26381
|
this.eventCount = 0;
|
|
25828
26382
|
this.byteCount = 0;
|
|
25829
26383
|
this.subscriberCount = 0;
|
|
@@ -25851,6 +26405,10 @@ var ProjectRoomEventBroker = class {
|
|
|
25851
26405
|
options.maxGlobalBytes ?? DEFAULT_MAX_GLOBAL_BYTES,
|
|
25852
26406
|
"maxGlobalBytes"
|
|
25853
26407
|
);
|
|
26408
|
+
this.sourceKeyLimit = positiveSafeInteger(
|
|
26409
|
+
options.sourceKeyLimit ?? DEFAULT_SOURCE_KEY_LIMIT,
|
|
26410
|
+
"sourceKeyLimit"
|
|
26411
|
+
);
|
|
25854
26412
|
this.sequence = nonnegativeSafeInteger(options.initialSequence ?? 0, "initialSequence");
|
|
25855
26413
|
this.log = options.log ?? { warn: () => void 0 };
|
|
25856
26414
|
}
|
|
@@ -25862,8 +26420,22 @@ var ProjectRoomEventBroker = class {
|
|
|
25862
26420
|
get retainedBytes() {
|
|
25863
26421
|
return this.byteCount;
|
|
25864
26422
|
}
|
|
25865
|
-
/**
|
|
25866
|
-
|
|
26423
|
+
/**
|
|
26424
|
+
* Installs (or clears) a hook invoked after a locally published event is stored
|
|
26425
|
+
* and queued to local subscribers. Used to mirror events to other replicas via
|
|
26426
|
+
* a shared transport. Best-effort: a throwing hook never affects `publish`.
|
|
26427
|
+
*/
|
|
26428
|
+
setBroadcastHook(hook) {
|
|
26429
|
+
this.broadcast = hook;
|
|
26430
|
+
}
|
|
26431
|
+
/**
|
|
26432
|
+
* Atomically stores an immutable event before queueing detached listener callbacks.
|
|
26433
|
+
*
|
|
26434
|
+
* @param sourceKey Optional caller-owned fact key; when present it is retained
|
|
26435
|
+
* for bounded cross-replica duplicate suppression so a later foreign copy of the
|
|
26436
|
+
* same fact (or a local publish) is dropped by {@link ingestForeignEvent}.
|
|
26437
|
+
*/
|
|
26438
|
+
publish(scope, draft, sourceKey) {
|
|
25867
26439
|
this.assertOpen();
|
|
25868
26440
|
const canonicalScope = snapshotScope(scope);
|
|
25869
26441
|
const key = scopeKey2(canonicalScope);
|
|
@@ -25898,9 +26470,52 @@ var ProjectRoomEventBroker = class {
|
|
|
25898
26470
|
this.sequence = nextSequence;
|
|
25899
26471
|
this.eventCount += 1;
|
|
25900
26472
|
this.byteCount += bytes;
|
|
26473
|
+
if (sourceKey !== void 0) this.rememberSourceKey(sourceKey);
|
|
25901
26474
|
for (const subscription of [...room.subscriptions]) this.queueCallback(subscription, serialized);
|
|
26475
|
+
if (this.broadcast) {
|
|
26476
|
+
try {
|
|
26477
|
+
this.broadcast(canonicalScope, serialized, sourceKey);
|
|
26478
|
+
} catch {
|
|
26479
|
+
}
|
|
26480
|
+
}
|
|
25902
26481
|
return parseScopedEvent(serialized);
|
|
25903
26482
|
}
|
|
26483
|
+
/**
|
|
26484
|
+
* Delivers one event published by ANOTHER replica to this process's local
|
|
26485
|
+
* subscribers for its room, without adding it to the local replay ring or
|
|
26486
|
+
* consuming a local sequence (its id carries the origin replica's epoch).
|
|
26487
|
+
*
|
|
26488
|
+
* @param serializedEvent A serialized scoped business event produced by a peer.
|
|
26489
|
+
* @param sourceKey Optional caller-owned fact key shared by every replica's copy
|
|
26490
|
+
* of the same committed fact. When it was already seen (locally published or
|
|
26491
|
+
* ingested from a peer) the event is dropped to avoid N× duplicate delivery.
|
|
26492
|
+
* @returns True when it was queued to at least one local subscription.
|
|
26493
|
+
* @remarks Source-key deduplication is process-local and bounded, so it caps
|
|
26494
|
+
* duplicate fan-out within the retention window without replacing REST, which
|
|
26495
|
+
* remains the authority. A malformed payload or a room with no local
|
|
26496
|
+
* subscribers is ignored.
|
|
26497
|
+
*/
|
|
26498
|
+
ingestForeignEvent(serializedEvent, sourceKey) {
|
|
26499
|
+
this.assertOpen();
|
|
26500
|
+
if (sourceKey !== void 0 && this.seenSourceKeys.has(sourceKey)) return false;
|
|
26501
|
+
let key;
|
|
26502
|
+
try {
|
|
26503
|
+
const event = parseScopedEvent(serializedEvent);
|
|
26504
|
+
key = scopeKey2(snapshotScope(event.scope));
|
|
26505
|
+
} catch {
|
|
26506
|
+
return false;
|
|
26507
|
+
}
|
|
26508
|
+
if (sourceKey !== void 0) this.rememberSourceKey(sourceKey);
|
|
26509
|
+
const room = this.rooms.get(key);
|
|
26510
|
+
if (!room || room.subscriptions.size === 0) return false;
|
|
26511
|
+
this.touch(room);
|
|
26512
|
+
let queued = false;
|
|
26513
|
+
for (const subscription of [...room.subscriptions]) {
|
|
26514
|
+
this.queueCallback(subscription, serializedEvent);
|
|
26515
|
+
queued = true;
|
|
26516
|
+
}
|
|
26517
|
+
return queued;
|
|
26518
|
+
}
|
|
25904
26519
|
/** Atomically resolves replay and registers a distinct subscription for live events. */
|
|
25905
26520
|
subscribe(scope, afterEventId, listener) {
|
|
25906
26521
|
this.assertOpen();
|
|
@@ -25940,6 +26555,7 @@ var ProjectRoomEventBroker = class {
|
|
|
25940
26555
|
}
|
|
25941
26556
|
this.rooms.clear();
|
|
25942
26557
|
this.sequenceScopes.clear();
|
|
26558
|
+
this.seenSourceKeys.clear();
|
|
25943
26559
|
this.eventCount = 0;
|
|
25944
26560
|
this.byteCount = 0;
|
|
25945
26561
|
this.subscriberCount = 0;
|
|
@@ -26074,6 +26690,14 @@ var ProjectRoomEventBroker = class {
|
|
|
26074
26690
|
this.usageClock += 1;
|
|
26075
26691
|
room.lastUsed = this.usageClock;
|
|
26076
26692
|
}
|
|
26693
|
+
rememberSourceKey(key) {
|
|
26694
|
+
this.seenSourceKeys.set(key, true);
|
|
26695
|
+
while (this.seenSourceKeys.size > this.sourceKeyLimit) {
|
|
26696
|
+
const oldest = this.seenSourceKeys.keys().next().value;
|
|
26697
|
+
if (oldest === void 0) break;
|
|
26698
|
+
this.seenSourceKeys.delete(oldest);
|
|
26699
|
+
}
|
|
26700
|
+
}
|
|
26077
26701
|
};
|
|
26078
26702
|
function positiveSafeInteger(value, name) {
|
|
26079
26703
|
if (!Number.isSafeInteger(value) || value <= 0) throw new RangeError(`${name} must be a positive safe integer`);
|
|
@@ -26265,7 +26889,7 @@ var BrokerProjectRoomRealtimePublisher = class {
|
|
|
26265
26889
|
if (!event) throw new Error("Invalid Project Room realtime projection");
|
|
26266
26890
|
const dedupeKey = (0, import_node_crypto25.createHash)("sha256").update(JSON.stringify([type, event.scope.tenantId, event.scope.projectId, event.scope.roomId, event.sourceKey])).digest("hex");
|
|
26267
26891
|
if (this.sourceKeys.has(dedupeKey)) return;
|
|
26268
|
-
this.deps.broker.publish(event.scope, event.draft);
|
|
26892
|
+
this.deps.broker.publish(event.scope, event.draft, event.sourceKey);
|
|
26269
26893
|
this.sourceKeys.set(dedupeKey, true);
|
|
26270
26894
|
while (this.sourceKeys.size > this.dedupeLimit) {
|
|
26271
26895
|
const oldest = this.sourceKeys.keys().next().value;
|
|
@@ -26504,7 +27128,7 @@ function createProjectRoomRealtimeRuntime(deps) {
|
|
|
26504
27128
|
broker,
|
|
26505
27129
|
publisher,
|
|
26506
27130
|
subscriber,
|
|
26507
|
-
subscribe: (listener) =>
|
|
27131
|
+
subscribe: (listener) => import_core53.taskLifecycleNotifier.subscribe(listener),
|
|
26508
27132
|
log: deps.log,
|
|
26509
27133
|
shutdownTimeoutMs: deps.shutdownTimeoutMs
|
|
26510
27134
|
});
|
|
@@ -27242,35 +27866,35 @@ function hookErrorMessage(error) {
|
|
|
27242
27866
|
function wrapReassignmentThreadError(error) {
|
|
27243
27867
|
if (error instanceof ProjectTaskThreadError) {
|
|
27244
27868
|
if (error.code === "PROJECT_TASK_THREAD_SCOPE_INVALID") {
|
|
27245
|
-
return new
|
|
27869
|
+
return new import_core54.ManagedTaskStartError("PROJECT_TASK_CONTEXT_INVALID", error.message, {
|
|
27246
27870
|
hint: "Project task, room, or roster scope changed; re-read the task and retry."
|
|
27247
27871
|
});
|
|
27248
27872
|
}
|
|
27249
27873
|
if (error.code === "PROJECT_TASK_THREAD_OWNER_INVALID") {
|
|
27250
|
-
return new
|
|
27874
|
+
return new import_core54.ManagedTaskStartError("TASK_REASSIGN_NO_CHANGE", error.message, {
|
|
27251
27875
|
hint: "The target already owns this task; re-read before dispatching."
|
|
27252
27876
|
});
|
|
27253
27877
|
}
|
|
27254
|
-
return new
|
|
27878
|
+
return new import_core54.ManagedTaskStartError("TASK_THREAD_CONFLICT", error.message, {
|
|
27255
27879
|
hint: "Task Thread changed concurrently; re-read the task and retry."
|
|
27256
27880
|
});
|
|
27257
27881
|
}
|
|
27258
|
-
return new
|
|
27882
|
+
return new import_core54.ManagedTaskStartError("TASK_EXECUTION_ENQUEUE_FAILED", hookErrorMessage(error), {
|
|
27259
27883
|
hint: "Re-read the task and retry the dispatch."
|
|
27260
27884
|
});
|
|
27261
27885
|
}
|
|
27262
27886
|
function wrapReassignmentAuthorizationError(error) {
|
|
27263
|
-
if (error instanceof
|
|
27887
|
+
if (error instanceof import_core54.ProjectTaskOwnerPolicyError) {
|
|
27264
27888
|
if (error.code === "PROJECT_TASK_CALLER_INACTIVE") {
|
|
27265
|
-
return new
|
|
27889
|
+
return new import_core54.ManagedTaskStartError("PROJECT_TASK_CALLER_INACTIVE", error.message, {
|
|
27266
27890
|
hint: "Dispatch from an active Project Room member bot."
|
|
27267
27891
|
});
|
|
27268
27892
|
}
|
|
27269
|
-
return new
|
|
27893
|
+
return new import_core54.ManagedTaskStartError("PROJECT_TASK_OWNER_INACTIVE", error.message, {
|
|
27270
27894
|
hint: "Dispatch to an active bot in this Project's roster."
|
|
27271
27895
|
});
|
|
27272
27896
|
}
|
|
27273
|
-
return new
|
|
27897
|
+
return new import_core54.ManagedTaskStartError("PROJECT_TASK_CONTEXT_INVALID", hookErrorMessage(error), {
|
|
27274
27898
|
hint: "Re-read the task and roster, then retry the dispatch."
|
|
27275
27899
|
});
|
|
27276
27900
|
}
|
|
@@ -27299,43 +27923,43 @@ async function transferGovernedDispatchOwner(task, options, deps) {
|
|
|
27299
27923
|
const agentId = options?.agentId;
|
|
27300
27924
|
if (!agentId || agentId === task.ownerId) return void 0;
|
|
27301
27925
|
if (!task.workspaceId || !task.projectId) {
|
|
27302
|
-
throw new
|
|
27926
|
+
throw new import_core54.ManagedTaskStartError("PROJECT_TASK_CONTEXT_INVALID", "Task is not governed by a Project lifecycle.", {
|
|
27303
27927
|
hint: "Dispatch governed tasks from a trusted Project run; ordinary tasks execute immediately."
|
|
27304
27928
|
});
|
|
27305
27929
|
}
|
|
27306
27930
|
return deps.mutex.runExclusive({ tenantId: task.tenantId, projectId: task.projectId }, async () => {
|
|
27307
27931
|
const current = await deps.tasks.getById(task.tenantId, task.id);
|
|
27308
27932
|
if (!current || !isProjectLifecycleTask(current) || current.workspaceId !== task.workspaceId || current.projectId !== task.projectId) {
|
|
27309
|
-
throw new
|
|
27933
|
+
throw new import_core54.ManagedTaskStartError("PROJECT_TASK_CONTEXT_INVALID", "Task is no longer a Project lifecycle task.", {
|
|
27310
27934
|
hint: "Re-read the task and confirm it still belongs to this Project before dispatching."
|
|
27311
27935
|
});
|
|
27312
27936
|
}
|
|
27313
27937
|
if (current.ownerType !== "agent") {
|
|
27314
|
-
throw new
|
|
27938
|
+
throw new import_core54.ManagedTaskStartError("AGENT_TASK_REQUIRED", "Project task owner must be an Agent.", {
|
|
27315
27939
|
hint: "Assign the task to an Agent before dispatching."
|
|
27316
27940
|
});
|
|
27317
27941
|
}
|
|
27318
27942
|
if (current.status !== "pending") {
|
|
27319
|
-
throw new
|
|
27943
|
+
throw new import_core54.ManagedTaskStartError("TASK_NOT_DISPATCHABLE", "Only a `pending` Project task can be dispatched.", {
|
|
27320
27944
|
hint: `This task is '${current.status}'. Resolve it or create a new task before dispatching.`
|
|
27321
27945
|
});
|
|
27322
27946
|
}
|
|
27323
27947
|
if (agentId === current.ownerId) return current;
|
|
27324
27948
|
const room = await deps.rooms.getMainRoom(current.tenantId, current.projectId);
|
|
27325
27949
|
if (!room || room.tenantId !== current.tenantId || room.workspaceId !== current.workspaceId || room.projectId !== current.projectId || room.type !== "main") {
|
|
27326
|
-
throw new
|
|
27950
|
+
throw new import_core54.ManagedTaskStartError("PROJECT_TASK_CONTEXT_INVALID", "Project main room is unavailable.", {
|
|
27327
27951
|
hint: "Open or repair the Project Room before dispatching."
|
|
27328
27952
|
});
|
|
27329
27953
|
}
|
|
27330
27954
|
const target = await deps.botMemberships.findByAssistant(current.tenantId, current.projectId, agentId);
|
|
27331
27955
|
if (!target || target.status !== "active" || target.tenantId !== current.tenantId || target.workspaceId !== current.workspaceId || target.projectId !== current.projectId || target.assistantId !== agentId || target.roomId !== room.id) {
|
|
27332
|
-
throw new
|
|
27956
|
+
throw new import_core54.ManagedTaskStartError("PROJECT_TASK_OWNER_INACTIVE", "Target Project task owner is not active in the exact roster.", {
|
|
27333
27957
|
hint: "Dispatch to an active bot in this Project's roster."
|
|
27334
27958
|
});
|
|
27335
27959
|
}
|
|
27336
27960
|
const caller = options?.callerMembershipId ? await deps.botMemberships.findById(current.tenantId, options.callerMembershipId) : null;
|
|
27337
27961
|
if (!caller || !options?.callerAssistantId || caller.id !== options.callerMembershipId || caller.assistantId !== options.callerAssistantId || caller.status !== "active" || caller.tenantId !== current.tenantId || caller.workspaceId !== current.workspaceId || caller.projectId !== current.projectId || caller.roomId !== room.id) {
|
|
27338
|
-
throw new
|
|
27962
|
+
throw new import_core54.ManagedTaskStartError("PROJECT_TASK_CALLER_INACTIVE", "Current Project task caller is not active in the exact roster.", {
|
|
27339
27963
|
hint: "Dispatch from an active Project Room member bot."
|
|
27340
27964
|
});
|
|
27341
27965
|
}
|
|
@@ -27370,7 +27994,7 @@ async function transferGovernedDispatchOwner(task, options, deps) {
|
|
|
27370
27994
|
actor: `agent:${caller.assistantId}`
|
|
27371
27995
|
});
|
|
27372
27996
|
if (!result.success) {
|
|
27373
|
-
throw new
|
|
27997
|
+
throw new import_core54.ManagedTaskStartError(result.code, result.error, {
|
|
27374
27998
|
hint: result.hint ?? reassignmentFailureHint(result.code),
|
|
27375
27999
|
...result.retryable !== void 0 ? { retryable: result.retryable } : {}
|
|
27376
28000
|
});
|
|
@@ -27379,19 +28003,19 @@ async function transferGovernedDispatchOwner(task, options, deps) {
|
|
|
27379
28003
|
});
|
|
27380
28004
|
}
|
|
27381
28005
|
var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
27382
|
-
const webAppStore = (0,
|
|
27383
|
-
const assistantStore = (0,
|
|
27384
|
-
const projectStore = (0,
|
|
27385
|
-
const projectMembershipStore = (0,
|
|
27386
|
-
const userTenantLinkStore = (0,
|
|
27387
|
-
const projectRoomStore = (0,
|
|
27388
|
-
const projectBotMembershipStore = (0,
|
|
27389
|
-
const projectRoomMessageStore = (0,
|
|
27390
|
-
const projectRoomReadStateStore = (0,
|
|
27391
|
-
const userPushSubscriptionStore = (0,
|
|
27392
|
-
const threadStore = (0,
|
|
27393
|
-
const taskStore = (0,
|
|
27394
|
-
const taskWorkItemStore = (0,
|
|
28006
|
+
const webAppStore = (0, import_core54.getStoreLattice)("default", "agentWebApp").store;
|
|
28007
|
+
const assistantStore = (0, import_core54.getStoreLattice)("default", "assistant").store;
|
|
28008
|
+
const projectStore = (0, import_core54.getStoreLattice)("default", "project").store;
|
|
28009
|
+
const projectMembershipStore = (0, import_core54.getStoreLattice)("default", "projectMembership").store;
|
|
28010
|
+
const userTenantLinkStore = (0, import_core54.getStoreLattice)("default", "userTenantLink").store;
|
|
28011
|
+
const projectRoomStore = (0, import_core54.getStoreLattice)("default", "projectRoom").store;
|
|
28012
|
+
const projectBotMembershipStore = (0, import_core54.getStoreLattice)("default", "projectBotMembership").store;
|
|
28013
|
+
const projectRoomMessageStore = (0, import_core54.getStoreLattice)("default", "projectRoomMessage").store;
|
|
28014
|
+
const projectRoomReadStateStore = (0, import_core54.getStoreLattice)("default", "projectRoomReadState").store;
|
|
28015
|
+
const userPushSubscriptionStore = (0, import_core54.getStoreLattice)("default", "userPushSubscription").store;
|
|
28016
|
+
const threadStore = (0, import_core54.getStoreLattice)("default", "thread").store;
|
|
28017
|
+
const taskStore = (0, import_core54.getStoreLattice)("default", "task").store;
|
|
28018
|
+
const taskWorkItemStore = (0, import_core54.getStoreLattice)("default", "taskWorkItem").store;
|
|
27395
28019
|
const projectTaskEnabled = options.projectTaskEnabled ?? process.env.AXIOM_PROJECT_TASK_EXECUTION_ENABLED !== "false";
|
|
27396
28020
|
const accessService = new ProjectAccessService({ projectStore, membershipStore: projectMembershipStore, userTenantLinkStore });
|
|
27397
28021
|
const realtimeMode = resolveProjectRoomRealtimeMode();
|
|
@@ -27457,7 +28081,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27457
28081
|
updateAssistant: assistantStore.updateAssistant.bind(assistantStore)
|
|
27458
28082
|
});
|
|
27459
28083
|
const resolveCoordinatorMentionName = async (tenantId) => {
|
|
27460
|
-
const tenant2 = await (0,
|
|
28084
|
+
const tenant2 = await (0, import_core54.getStoreLattice)("default", "tenant").store.getTenantById(tenantId);
|
|
27461
28085
|
const value = tenant2?.metadata?.coordinatorMentionName;
|
|
27462
28086
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
27463
28087
|
};
|
|
@@ -27484,7 +28108,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27484
28108
|
return membership !== null && membership.projectId === projectId ? membership : null;
|
|
27485
28109
|
},
|
|
27486
28110
|
getThreadStatus: async ({ tenantId, assistantId, threadId, workspaceId, projectId }) => {
|
|
27487
|
-
const agent =
|
|
28111
|
+
const agent = import_core54.agentInstanceManager.getAgent({
|
|
27488
28112
|
tenant_id: tenantId,
|
|
27489
28113
|
assistant_id: assistantId,
|
|
27490
28114
|
thread_id: threadId,
|
|
@@ -27493,9 +28117,9 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27493
28117
|
});
|
|
27494
28118
|
return String(await agent.getRunStatus());
|
|
27495
28119
|
},
|
|
27496
|
-
dispatcher: (0,
|
|
28120
|
+
dispatcher: (0, import_core54.createTrustedAgentMessageDispatcher)((scope) => import_core54.agentInstanceManager.getAgent(scope))
|
|
27497
28121
|
});
|
|
27498
|
-
const membershipService = new ProjectMembershipService({ membershipStore: projectMembershipStore, userTenantLinkStore, accessService, projectMutationMutex:
|
|
28122
|
+
const membershipService = new ProjectMembershipService({ membershipStore: projectMembershipStore, userTenantLinkStore, accessService, projectMutationMutex: import_core54.projectMutationMutex, roomStore: projectRoomStore, realtime, onRealtimeFailure: realtime && channelDeps?.warn ? ({ code, membershipId }) => channelDeps.warn?.("project-room:membership-realtime-failed", { code, membershipId }) : void 0 });
|
|
27499
28123
|
const rosterService = new ProjectRosterService({
|
|
27500
28124
|
accessService,
|
|
27501
28125
|
roomService,
|
|
@@ -27506,7 +28130,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27506
28130
|
assistantStore,
|
|
27507
28131
|
taskStore,
|
|
27508
28132
|
bindingLifecycle,
|
|
27509
|
-
projectMutationMutex:
|
|
28133
|
+
projectMutationMutex: import_core54.projectMutationMutex,
|
|
27510
28134
|
realtime,
|
|
27511
28135
|
onRealtimeFailure: realtime && channelDeps?.warn ? ({ code, membershipId }) => channelDeps.warn?.("project-room:roster-realtime-failed", { code, membershipId }) : void 0
|
|
27512
28136
|
});
|
|
@@ -27562,9 +28186,9 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27562
28186
|
}
|
|
27563
28187
|
if (projectTaskComposition) app2.addHook("onClose", async () => projectTaskComposition.lease.release());
|
|
27564
28188
|
const taskThreadService = projectTaskComposition?.lease.runtime.threads ?? new ProjectTaskThreadService({ threads: threadStore, idFactory: import_node_crypto26.randomUUID });
|
|
27565
|
-
const taskLifecycle = projectTaskComposition?.lease.runtime.lifecycle ?? (0,
|
|
27566
|
-
const reassignmentAuthorizer = (0,
|
|
27567
|
-
new
|
|
28189
|
+
const taskLifecycle = projectTaskComposition?.lease.runtime.lifecycle ?? (0, import_core54.createTaskLifecycleService)({ taskStore, workItemStore: taskWorkItemStore });
|
|
28190
|
+
const reassignmentAuthorizer = (0, import_core54.createProjectTaskReassignmentAuthorizer)(
|
|
28191
|
+
new import_core54.ProjectTaskOwnerPolicy(projectBotMembershipStore),
|
|
27568
28192
|
(input) => validateReassignmentThread(threadStore, input)
|
|
27569
28193
|
);
|
|
27570
28194
|
const taskCommandService = new TaskCommandService({
|
|
@@ -27573,7 +28197,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27573
28197
|
lifecycle: taskLifecycle,
|
|
27574
28198
|
execution: projectTaskComposition?.lease.runtime.execution,
|
|
27575
28199
|
threads: taskThreadService,
|
|
27576
|
-
agents: { getAgent: (params) =>
|
|
28200
|
+
agents: { getAgent: (params) => import_core54.agentInstanceManager.getAgent(params) },
|
|
27577
28201
|
taskScope: (task) => resolveCommandTaskScope(task, {
|
|
27578
28202
|
rooms: projectRoomStore,
|
|
27579
28203
|
bots: projectBotMembershipStore,
|
|
@@ -27611,7 +28235,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27611
28235
|
readStateService,
|
|
27612
28236
|
interruptService: roomInterruptService,
|
|
27613
28237
|
userDirectory: {
|
|
27614
|
-
getUserById: (id3) => (0,
|
|
28238
|
+
getUserById: (id3) => (0, import_core54.getStoreLattice)("default", "user").store.getUserById(id3).then((u) => u ? { name: u.name } : null)
|
|
27615
28239
|
}
|
|
27616
28240
|
});
|
|
27617
28241
|
registerProjectRosterRoutes(app2, { service: rosterService });
|
|
@@ -27622,7 +28246,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27622
28246
|
createProject: projectStore.createProject.bind(projectStore)
|
|
27623
28247
|
},
|
|
27624
28248
|
workspaceStore: {
|
|
27625
|
-
getWorkspaceById: (tenantId, id3) => (0,
|
|
28249
|
+
getWorkspaceById: (tenantId, id3) => (0, import_core54.getStoreLattice)("default", "workspace").store.getWorkspaceById(tenantId, id3)
|
|
27626
28250
|
},
|
|
27627
28251
|
membershipStore: {
|
|
27628
28252
|
list: projectMembershipStore.list.bind(projectMembershipStore),
|
|
@@ -27645,7 +28269,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27645
28269
|
getUsersByTenant: userTenantLinkStore.getUsersByTenant.bind(userTenantLinkStore)
|
|
27646
28270
|
},
|
|
27647
28271
|
userStore: {
|
|
27648
|
-
getUserById: (id3) => (0,
|
|
28272
|
+
getUserById: (id3) => (0, import_core54.getStoreLattice)("default", "user").store.getUserById(id3).then((u) => u ? { id: u.id, name: u.name, email: u.email } : null)
|
|
27649
28273
|
},
|
|
27650
28274
|
assistantStore: {
|
|
27651
28275
|
getAssistantById: assistantStore.getAssistantById.bind(assistantStore),
|
|
@@ -27667,28 +28291,30 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27667
28291
|
}
|
|
27668
28292
|
});
|
|
27669
28293
|
registerCapabilityBundleRoutes(app2, new CapabilityBundleController({
|
|
27670
|
-
bundleStore: (0,
|
|
28294
|
+
bundleStore: (0, import_core54.getStoreLattice)("default", "capabilityBundle").store,
|
|
27671
28295
|
projectStore
|
|
27672
28296
|
}, { authRequired: process.env.AUTH_REQUIRED === "true" }));
|
|
27673
|
-
|
|
27674
|
-
providerStore: (0,
|
|
28297
|
+
const modelProviderController = new ModelProviderController({
|
|
28298
|
+
providerStore: (0, import_core54.getStoreLattice)("default", "modelProvider").store,
|
|
27675
28299
|
userTenantLinkStore,
|
|
27676
28300
|
registry: {
|
|
27677
|
-
register: (tenantId, modelKey2, config) =>
|
|
27678
|
-
has: (tenantId, modelKey2) =>
|
|
27679
|
-
remove: (tenantId, modelKey2) =>
|
|
27680
|
-
listRegistered: (tenantId) =>
|
|
27681
|
-
}
|
|
27682
|
-
}, { authRequired: process.env.AUTH_REQUIRED === "true" })
|
|
28301
|
+
register: (tenantId, modelKey2, config) => import_core54.modelLatticeManager.registerLatticeWithTenant(tenantId, modelKey2, config),
|
|
28302
|
+
has: (tenantId, modelKey2) => import_core54.modelLatticeManager.hasLatticeWithTenant(tenantId, modelKey2),
|
|
28303
|
+
remove: (tenantId, modelKey2) => import_core54.modelLatticeManager.removeLatticeWithTenant(tenantId, modelKey2),
|
|
28304
|
+
listRegistered: (tenantId) => import_core54.modelLatticeManager.getLatticeKeysByTenant(tenantId)
|
|
28305
|
+
}
|
|
28306
|
+
}, { authRequired: process.env.AUTH_REQUIRED === "true" });
|
|
28307
|
+
registerModelProviderRoutes(app2, modelProviderController);
|
|
28308
|
+
void modelProviderController.hydrateRegistry().catch(() => void 0);
|
|
27683
28309
|
registerAgentWebAppRoutes(app2, {
|
|
27684
28310
|
service: new AgentWebAppService({
|
|
27685
28311
|
webAppStore,
|
|
27686
28312
|
assistantStore,
|
|
27687
28313
|
projectStore,
|
|
27688
|
-
modelRegistry: { has: (key) =>
|
|
28314
|
+
modelRegistry: { has: (key) => import_core54.modelLatticeManager.hasLattice(key) },
|
|
27689
28315
|
configuredAgentResolver: createConfiguredAgentResolver({
|
|
27690
|
-
hydrate: (tenantId) =>
|
|
27691
|
-
has: (tenantId, assistantId) =>
|
|
28316
|
+
hydrate: (tenantId) => import_core54.agentLatticeManager.initializeStoredAssistantsForTenant(tenantId),
|
|
28317
|
+
has: (tenantId, assistantId) => import_core54.agentLatticeManager.hasAgentLatticeWithTenant(tenantId, assistantId)
|
|
27692
28318
|
})
|
|
27693
28319
|
})
|
|
27694
28320
|
});
|
|
@@ -27725,28 +28351,28 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27725
28351
|
},
|
|
27726
28352
|
tasks: taskStore,
|
|
27727
28353
|
workItems: taskWorkItemStore,
|
|
27728
|
-
projectMutationMutex:
|
|
28354
|
+
projectMutationMutex: import_core54.projectMutationMutex,
|
|
27729
28355
|
...projectTaskComposition ? { commands: taskCommandService } : {}
|
|
27730
28356
|
}),
|
|
27731
28357
|
service: new AgentWebAppRuntimeService({
|
|
27732
28358
|
webAppStore,
|
|
27733
|
-
threadStore: (0,
|
|
28359
|
+
threadStore: (0, import_core54.getStoreLattice)("default", "thread").store,
|
|
27734
28360
|
projectStore,
|
|
27735
28361
|
assistantResolver: {
|
|
27736
28362
|
resolve: async (tenantId, assistantId) => {
|
|
27737
28363
|
const stored = await assistantStore.getAssistantById(tenantId, assistantId);
|
|
27738
28364
|
if (stored) return { id: stored.id, name: stored.name, description: stored.description };
|
|
27739
|
-
await
|
|
27740
|
-
const config =
|
|
28365
|
+
await import_core54.agentLatticeManager.initializeStoredAssistantsForTenant(tenantId);
|
|
28366
|
+
const config = import_core54.agentLatticeManager.getAgentConfigWithTenant(tenantId, assistantId);
|
|
27741
28367
|
return config ? { id: assistantId, name: config.name, description: config.description } : null;
|
|
27742
28368
|
}
|
|
27743
28369
|
},
|
|
27744
28370
|
modelRegistry: {
|
|
27745
|
-
has: (key) =>
|
|
28371
|
+
has: (key) => import_core54.modelLatticeManager.hasLattice(key),
|
|
27746
28372
|
label: (key) => key
|
|
27747
28373
|
},
|
|
27748
28374
|
messageReader: {
|
|
27749
|
-
getCurrentMessages: ({ tenantId, assistantId, threadId, workspaceId, projectId }) =>
|
|
28375
|
+
getCurrentMessages: ({ tenantId, assistantId, threadId, workspaceId, projectId }) => import_core54.agentInstanceManager.getAgentForRead({
|
|
27750
28376
|
tenant_id: tenantId,
|
|
27751
28377
|
assistant_id: assistantId,
|
|
27752
28378
|
thread_id: threadId,
|
|
@@ -27755,7 +28381,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27755
28381
|
}).getCurrentMessages()
|
|
27756
28382
|
},
|
|
27757
28383
|
agentResolver: {
|
|
27758
|
-
getAgent: ({ tenantId, assistantId, threadId, workspaceId, projectId }) =>
|
|
28384
|
+
getAgent: ({ tenantId, assistantId, threadId, workspaceId, projectId }) => import_core54.agentInstanceManager.getAgent({
|
|
27759
28385
|
tenant_id: tenantId,
|
|
27760
28386
|
assistant_id: assistantId,
|
|
27761
28387
|
thread_id: threadId,
|
|
@@ -27773,8 +28399,8 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27773
28399
|
if (webApp.tenantId !== preview.tenantId) return false;
|
|
27774
28400
|
const assistant = await assistantStore.getAssistantById(preview.tenantId, webApp.assistantId);
|
|
27775
28401
|
if (assistant) return !assistant.ownerUserId || assistant.ownerUserId === preview.userId;
|
|
27776
|
-
await
|
|
27777
|
-
return
|
|
28402
|
+
await import_core54.agentLatticeManager.initializeStoredAssistantsForTenant(preview.tenantId);
|
|
28403
|
+
return import_core54.agentLatticeManager.hasAgentLatticeWithTenant(preview.tenantId, webApp.assistantId);
|
|
27778
28404
|
}
|
|
27779
28405
|
})
|
|
27780
28406
|
});
|
|
@@ -27831,14 +28457,14 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27831
28457
|
app2.post("/api/personal-assistant", createPersonalAssistant);
|
|
27832
28458
|
app2.get("/api/personal-assistant", getPersonalAssistant);
|
|
27833
28459
|
app2.delete("/api/personal-assistant", deletePersonalAssistant);
|
|
27834
|
-
|
|
28460
|
+
import_core54.executionAuthorityRegistry.register({
|
|
27835
28461
|
id: "project-lifecycle",
|
|
27836
28462
|
matches: isProjectLifecycleTask,
|
|
27837
28463
|
code: "PROJECT_TASK_EXECUTION_MANAGED",
|
|
27838
28464
|
message: "Project tasks are executed by the durable Project queue runtime",
|
|
27839
28465
|
onManagedStart: async (task, options2) => {
|
|
27840
28466
|
if (!projectTaskComposition && options2?.agentId && options2.agentId !== task.ownerId) {
|
|
27841
|
-
throw new
|
|
28467
|
+
throw new import_core54.ManagedTaskStartError(
|
|
27842
28468
|
"PROJECT_TASK_RUNTIME_UNAVAILABLE",
|
|
27843
28469
|
"Project task ownership transfer requires the Project task runtime.",
|
|
27844
28470
|
{ hint: "Project task execution is disabled; enable the Project task runtime or dispatch to the current owner." }
|
|
@@ -27851,17 +28477,21 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27851
28477
|
threads: taskThreadService,
|
|
27852
28478
|
reassignmentAuthorizer,
|
|
27853
28479
|
lifecycle: taskLifecycle,
|
|
27854
|
-
mutex:
|
|
28480
|
+
mutex: import_core54.projectMutationMutex
|
|
27855
28481
|
}) : void 0;
|
|
27856
28482
|
const admitted = transferred ?? task;
|
|
27857
28483
|
if (!admitted.workspaceId || !admitted.projectId) return;
|
|
27858
|
-
|
|
27859
|
-
|
|
27860
|
-
|
|
27861
|
-
|
|
27862
|
-
|
|
27863
|
-
|
|
27864
|
-
|
|
28484
|
+
const markerUpdated = await taskStore.update(admitted.tenantId, admitted.id, {
|
|
28485
|
+
context: withExecutionRequest(admitted.context, (/* @__PURE__ */ new Date()).toISOString())
|
|
28486
|
+
}).catch(() => null);
|
|
28487
|
+
const eventTask = markerUpdated ?? admitted;
|
|
28488
|
+
void import_core54.projectTaskAdmissionNotifier.publish({
|
|
28489
|
+
tenantId: eventTask.tenantId,
|
|
28490
|
+
workspaceId: eventTask.workspaceId,
|
|
28491
|
+
projectId: eventTask.projectId,
|
|
28492
|
+
taskId: eventTask.id,
|
|
28493
|
+
ownerId: eventTask.ownerId,
|
|
28494
|
+
updatedAt: eventTask.updatedAt.toISOString()
|
|
27865
28495
|
});
|
|
27866
28496
|
}
|
|
27867
28497
|
});
|
|
@@ -27869,7 +28499,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
27869
28499
|
access: accessService,
|
|
27870
28500
|
tasks: taskStore,
|
|
27871
28501
|
workItems: taskWorkItemStore,
|
|
27872
|
-
projectMutationMutex:
|
|
28502
|
+
projectMutationMutex: import_core54.projectMutationMutex,
|
|
27873
28503
|
commands: taskCommandService,
|
|
27874
28504
|
readableProjects: async ({ tenantId, userId, workspaceId }) => {
|
|
27875
28505
|
const projects = await projectStore.getProjectsByWorkspace(tenantId, workspaceId);
|
|
@@ -28151,9 +28781,9 @@ function tryCreateProjectTaskRuntime(input) {
|
|
|
28151
28781
|
let stores;
|
|
28152
28782
|
try {
|
|
28153
28783
|
stores = {
|
|
28154
|
-
tenants: (0,
|
|
28155
|
-
workspaces: (0,
|
|
28156
|
-
queue: (0,
|
|
28784
|
+
tenants: (0, import_core54.getStoreLattice)("default", "tenant").store,
|
|
28785
|
+
workspaces: (0, import_core54.getStoreLattice)("default", "workspace").store,
|
|
28786
|
+
queue: (0, import_core54.getStoreLattice)("default", "threadMessageQueue").store
|
|
28157
28787
|
};
|
|
28158
28788
|
const missing = missingRuntimeMethod(input, stores);
|
|
28159
28789
|
if (missing) return { reason: missing };
|
|
@@ -28185,7 +28815,7 @@ function createRuntime(input, stores, log2) {
|
|
|
28185
28815
|
const controller = new AbortController();
|
|
28186
28816
|
const mutex = new ProjectTaskExecutionMutex();
|
|
28187
28817
|
const threads = new ProjectTaskThreadService({ threads: input.threadStore, idFactory: import_node_crypto26.randomUUID });
|
|
28188
|
-
const lifecycle = (0,
|
|
28818
|
+
const lifecycle = (0, import_core54.createTaskLifecycleService)({ taskStore: input.taskStore, workItemStore: input.taskWorkItemStore });
|
|
28189
28819
|
const projection = new RoomProjectionService({
|
|
28190
28820
|
messages: input.projectRoomMessageStore,
|
|
28191
28821
|
events: input.taskWorkItemStore,
|
|
@@ -28195,7 +28825,7 @@ function createRuntime(input, stores, log2) {
|
|
|
28195
28825
|
realtime: input.realtime,
|
|
28196
28826
|
idFactory: import_node_crypto26.randomUUID
|
|
28197
28827
|
});
|
|
28198
|
-
const agentFor = (task, thread) =>
|
|
28828
|
+
const agentFor = (task, thread) => import_core54.agentInstanceManager.getAgent({
|
|
28199
28829
|
tenant_id: task.tenantId,
|
|
28200
28830
|
assistant_id: task.ownerId,
|
|
28201
28831
|
thread_id: thread.id,
|
|
@@ -28209,7 +28839,7 @@ function createRuntime(input, stores, log2) {
|
|
|
28209
28839
|
bots: input.projectBotMembershipStore,
|
|
28210
28840
|
threads,
|
|
28211
28841
|
lifecycle,
|
|
28212
|
-
dispatcher: (0,
|
|
28842
|
+
dispatcher: (0, import_core54.createTrustedAgentMessageDispatcher)((scope) => import_core54.agentInstanceManager.getAgent(scope)),
|
|
28213
28843
|
queue: stores.queue,
|
|
28214
28844
|
agentFor
|
|
28215
28845
|
}, {
|
|
@@ -28236,8 +28866,8 @@ function createRuntime(input, stores, log2) {
|
|
|
28236
28866
|
const taskLifecycleListener = ((event) => {
|
|
28237
28867
|
void observer.listener(event);
|
|
28238
28868
|
});
|
|
28239
|
-
const unsubscribe =
|
|
28240
|
-
const unsubscribeAdmission =
|
|
28869
|
+
const unsubscribe = import_core54.taskLifecycleNotifier.subscribe(taskLifecycleListener);
|
|
28870
|
+
const unsubscribeAdmission = import_core54.projectTaskAdmissionNotifier.subscribe((event, signal) => {
|
|
28241
28871
|
observer.admit(event, signal);
|
|
28242
28872
|
});
|
|
28243
28873
|
let reconciliationWork;
|
|
@@ -28384,12 +29014,12 @@ function registerResourceRoutes(app2, controller) {
|
|
|
28384
29014
|
}
|
|
28385
29015
|
|
|
28386
29016
|
// src/export_registrations/index.ts
|
|
28387
|
-
var
|
|
29017
|
+
var import_core65 = require("@axiom-lattice/core");
|
|
28388
29018
|
|
|
28389
29019
|
// src/export_registrations/skill.registration.ts
|
|
28390
|
-
var
|
|
29020
|
+
var import_core55 = require("@axiom-lattice/core");
|
|
28391
29021
|
function getStore(context) {
|
|
28392
|
-
return new
|
|
29022
|
+
return new import_core55.SandboxSkillStore({
|
|
28393
29023
|
workspaceId: context?.workspaceId,
|
|
28394
29024
|
projectId: context?.projectId
|
|
28395
29025
|
});
|
|
@@ -28407,7 +29037,7 @@ var skillRegistration = {
|
|
|
28407
29037
|
async listForExport(tenantId, context) {
|
|
28408
29038
|
const store2 = getStore(context);
|
|
28409
29039
|
const skills = await store2.getAllSkills(tenantId, toStoreContext(context));
|
|
28410
|
-
return skills.filter((s) => !(0,
|
|
29040
|
+
return skills.filter((s) => !(0, import_core55.isBuiltInSkill)(s.id)).map((s) => ({
|
|
28411
29041
|
_exportId: "",
|
|
28412
29042
|
data: {
|
|
28413
29043
|
id: s.id,
|
|
@@ -28472,7 +29102,7 @@ var skillRegistration = {
|
|
|
28472
29102
|
const insertions = [];
|
|
28473
29103
|
for (const entity of entities) {
|
|
28474
29104
|
const id3 = entity.data.id;
|
|
28475
|
-
if ((0,
|
|
29105
|
+
if ((0, import_core55.isBuiltInSkill)(id3)) continue;
|
|
28476
29106
|
if (existingIds.has(id3)) {
|
|
28477
29107
|
conflicts.push({
|
|
28478
29108
|
_exportId: entity._exportId,
|
|
@@ -28531,9 +29161,9 @@ var skillRegistration = {
|
|
|
28531
29161
|
};
|
|
28532
29162
|
|
|
28533
29163
|
// src/export_registrations/agent.registration.ts
|
|
28534
|
-
var
|
|
29164
|
+
var import_core56 = require("@axiom-lattice/core");
|
|
28535
29165
|
function getStore2() {
|
|
28536
|
-
return (0,
|
|
29166
|
+
return (0, import_core56.getStoreLattice)("default", "assistant").store;
|
|
28537
29167
|
}
|
|
28538
29168
|
var agentRegistration = {
|
|
28539
29169
|
entityType: "agent",
|
|
@@ -28613,9 +29243,9 @@ var agentRegistration = {
|
|
|
28613
29243
|
};
|
|
28614
29244
|
|
|
28615
29245
|
// src/export_registrations/database-config.registration.ts
|
|
28616
|
-
var
|
|
29246
|
+
var import_core57 = require("@axiom-lattice/core");
|
|
28617
29247
|
function getStore3() {
|
|
28618
|
-
return (0,
|
|
29248
|
+
return (0, import_core57.getStoreLattice)("default", "database").store;
|
|
28619
29249
|
}
|
|
28620
29250
|
var databaseConfigRegistration = {
|
|
28621
29251
|
entityType: "database_config",
|
|
@@ -28695,9 +29325,9 @@ var databaseConfigRegistration = {
|
|
|
28695
29325
|
};
|
|
28696
29326
|
|
|
28697
29327
|
// src/export_registrations/metrics-config.registration.ts
|
|
28698
|
-
var
|
|
29328
|
+
var import_core58 = require("@axiom-lattice/core");
|
|
28699
29329
|
function getStore4() {
|
|
28700
|
-
return (0,
|
|
29330
|
+
return (0, import_core58.getStoreLattice)("default", "metrics").store;
|
|
28701
29331
|
}
|
|
28702
29332
|
var metricsConfigRegistration = {
|
|
28703
29333
|
entityType: "metrics_config",
|
|
@@ -28777,9 +29407,9 @@ var metricsConfigRegistration = {
|
|
|
28777
29407
|
};
|
|
28778
29408
|
|
|
28779
29409
|
// src/export_registrations/mcp-config.registration.ts
|
|
28780
|
-
var
|
|
29410
|
+
var import_core59 = require("@axiom-lattice/core");
|
|
28781
29411
|
function getStore5() {
|
|
28782
|
-
return (0,
|
|
29412
|
+
return (0, import_core59.getStoreLattice)("default", "mcp").store;
|
|
28783
29413
|
}
|
|
28784
29414
|
var mcpConfigRegistration = {
|
|
28785
29415
|
entityType: "mcp_config",
|
|
@@ -28862,9 +29492,9 @@ var mcpConfigRegistration = {
|
|
|
28862
29492
|
};
|
|
28863
29493
|
|
|
28864
29494
|
// src/export_registrations/connection.registration.ts
|
|
28865
|
-
var
|
|
29495
|
+
var import_core60 = require("@axiom-lattice/core");
|
|
28866
29496
|
function getStore6() {
|
|
28867
|
-
return (0,
|
|
29497
|
+
return (0, import_core60.getStoreLattice)("default", "connection").store;
|
|
28868
29498
|
}
|
|
28869
29499
|
async function listAllConnections(tenantId) {
|
|
28870
29500
|
const store2 = getStore6();
|
|
@@ -28946,9 +29576,9 @@ var connectionRegistration = {
|
|
|
28946
29576
|
};
|
|
28947
29577
|
|
|
28948
29578
|
// src/export_registrations/collection.registration.ts
|
|
28949
|
-
var
|
|
29579
|
+
var import_core61 = require("@axiom-lattice/core");
|
|
28950
29580
|
function getStore7() {
|
|
28951
|
-
return (0,
|
|
29581
|
+
return (0, import_core61.getStoreLattice)("default", "collection").store;
|
|
28952
29582
|
}
|
|
28953
29583
|
var collectionRegistration = {
|
|
28954
29584
|
entityType: "collection",
|
|
@@ -29019,7 +29649,7 @@ var collectionRegistration = {
|
|
|
29019
29649
|
};
|
|
29020
29650
|
|
|
29021
29651
|
// src/export_registrations/channel-installation.registration.ts
|
|
29022
|
-
var
|
|
29652
|
+
var import_core62 = require("@axiom-lattice/core");
|
|
29023
29653
|
var import_crypto11 = require("crypto");
|
|
29024
29654
|
var UUID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
29025
29655
|
var PUBLIC_CHANNELS = /* @__PURE__ */ new Set(["lark", "email", "slack", "wechat"]);
|
|
@@ -29053,7 +29683,7 @@ function validateImportData(data) {
|
|
|
29053
29683
|
};
|
|
29054
29684
|
}
|
|
29055
29685
|
function getStore8() {
|
|
29056
|
-
return (0,
|
|
29686
|
+
return (0, import_core62.getStoreLattice)("default", "channelInstallation").store;
|
|
29057
29687
|
}
|
|
29058
29688
|
function getOverwriteError(tenantId, incomingChannel, existing) {
|
|
29059
29689
|
if (!existing) return "Channel installation overwrite target must exist";
|
|
@@ -29187,9 +29817,9 @@ var channelInstallationRegistration = {
|
|
|
29187
29817
|
};
|
|
29188
29818
|
|
|
29189
29819
|
// src/export_registrations/menu.registration.ts
|
|
29190
|
-
var
|
|
29820
|
+
var import_core63 = require("@axiom-lattice/core");
|
|
29191
29821
|
function getStore9() {
|
|
29192
|
-
return (0,
|
|
29822
|
+
return (0, import_core63.getStoreLattice)("default", "menu").store;
|
|
29193
29823
|
}
|
|
29194
29824
|
var menuRegistration = {
|
|
29195
29825
|
entityType: "menu",
|
|
@@ -29267,9 +29897,9 @@ var menuRegistration = {
|
|
|
29267
29897
|
};
|
|
29268
29898
|
|
|
29269
29899
|
// src/export_registrations/eval.registration.ts
|
|
29270
|
-
var
|
|
29900
|
+
var import_core64 = require("@axiom-lattice/core");
|
|
29271
29901
|
function getStore10() {
|
|
29272
|
-
return (0,
|
|
29902
|
+
return (0, import_core64.getStoreLattice)("default", "eval").store;
|
|
29273
29903
|
}
|
|
29274
29904
|
var evalRegistration = {
|
|
29275
29905
|
entityType: "eval",
|
|
@@ -29595,7 +30225,7 @@ var evalRegistration = {
|
|
|
29595
30225
|
|
|
29596
30226
|
// src/export_registrations/index.ts
|
|
29597
30227
|
function registerAllBuiltinEntities() {
|
|
29598
|
-
const registry =
|
|
30228
|
+
const registry = import_core65.ExportableEntityRegistry.getInstance();
|
|
29599
30229
|
registry.register(skillRegistration);
|
|
29600
30230
|
registry.register(agentRegistration);
|
|
29601
30231
|
registry.register(databaseConfigRegistration);
|
|
@@ -29726,7 +30356,7 @@ function createAuditLoggerMiddleware() {
|
|
|
29726
30356
|
}
|
|
29727
30357
|
|
|
29728
30358
|
// src/index.ts
|
|
29729
|
-
var
|
|
30359
|
+
var import_core91 = require("@axiom-lattice/core");
|
|
29730
30360
|
|
|
29731
30361
|
// src/swagger.ts
|
|
29732
30362
|
var import_swagger = __toESM(require("@fastify/swagger"));
|
|
@@ -29792,7 +30422,7 @@ var configureSwagger = async (app2, customSwaggerConfig, customSwaggerUiConfig)
|
|
|
29792
30422
|
|
|
29793
30423
|
// src/services/agent_task_consumer.ts
|
|
29794
30424
|
var import_node_crypto27 = require("crypto");
|
|
29795
|
-
var
|
|
30425
|
+
var import_core66 = require("@axiom-lattice/core");
|
|
29796
30426
|
var import_protocols31 = require("@axiom-lattice/protocols");
|
|
29797
30427
|
var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
29798
30428
|
const {
|
|
@@ -29812,7 +30442,7 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
|
29812
30442
|
`\u5F00\u59CB\u5904\u7406\u4EFB\u52A1 [assistant_id: ${assistant_id}, thread_id: ${thread_id}]`
|
|
29813
30443
|
);
|
|
29814
30444
|
const scope = (0, import_protocols31.resolveRunScope)(runConfig);
|
|
29815
|
-
const agent =
|
|
30445
|
+
const agent = import_core66.agentInstanceManager.getAgent({ assistant_id, thread_id, tenant_id, workspace_id: scope.workspaceId, project_id: scope.projectId, custom_run_config: runConfig });
|
|
29816
30446
|
if (callback_event) {
|
|
29817
30447
|
const callbackEvent = callback_event;
|
|
29818
30448
|
const messageId = typeof input?.id === "string" && input.id !== "" ? input.id : (0, import_node_crypto27.randomUUID)();
|
|
@@ -29833,13 +30463,13 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
|
29833
30463
|
const onCompleted = (evt) => {
|
|
29834
30464
|
if (!belongsToMessage(evt)) return;
|
|
29835
30465
|
settle(() => {
|
|
29836
|
-
|
|
30466
|
+
import_core66.eventBus.publish(callbackEvent, {
|
|
29837
30467
|
success: true,
|
|
29838
30468
|
state: evt.state
|
|
29839
30469
|
});
|
|
29840
30470
|
if (main_thread_id && main_tenant_id) {
|
|
29841
30471
|
try {
|
|
29842
|
-
const mainAgent =
|
|
30472
|
+
const mainAgent = import_core66.agentInstanceManager.getAgent({
|
|
29843
30473
|
assistant_id: main_assistant_id ?? assistant_id,
|
|
29844
30474
|
thread_id: main_thread_id,
|
|
29845
30475
|
tenant_id: main_tenant_id,
|
|
@@ -29872,7 +30502,7 @@ ${summary}`
|
|
|
29872
30502
|
const onInterrupted = (evt) => {
|
|
29873
30503
|
if (!belongsToMessage(evt)) return;
|
|
29874
30504
|
settle(() => {
|
|
29875
|
-
|
|
30505
|
+
import_core66.eventBus.publish(callbackEvent, {
|
|
29876
30506
|
success: true,
|
|
29877
30507
|
state: evt.state
|
|
29878
30508
|
});
|
|
@@ -29881,7 +30511,7 @@ ${summary}`
|
|
|
29881
30511
|
const onFailed = (evt) => {
|
|
29882
30512
|
if (!belongsToMessage(evt)) return;
|
|
29883
30513
|
settle(() => {
|
|
29884
|
-
|
|
30514
|
+
import_core66.eventBus.publish(callbackEvent, {
|
|
29885
30515
|
success: false,
|
|
29886
30516
|
error: evt?.error instanceof Error ? evt.error.message : typeof evt?.error === "string" ? evt.error : "Agent execution failed"
|
|
29887
30517
|
});
|
|
@@ -29896,13 +30526,13 @@ ${summary}`
|
|
|
29896
30526
|
agent.subscribe("message:interrupted", onInterrupted);
|
|
29897
30527
|
agent.subscribe("message:failed", onFailed);
|
|
29898
30528
|
try {
|
|
29899
|
-
await agent.addMessage({ input: { ...input, id: messageId }, command, custom_run_config: runConfig },
|
|
30529
|
+
await agent.addMessage({ input: { ...input, id: messageId }, command, custom_run_config: runConfig }, import_core66.QueueMode.STEER);
|
|
29900
30530
|
} catch (error) {
|
|
29901
30531
|
dispose();
|
|
29902
30532
|
throw error;
|
|
29903
30533
|
}
|
|
29904
30534
|
} else {
|
|
29905
|
-
await agent.addMessage({ input, command, custom_run_config: runConfig },
|
|
30535
|
+
await agent.addMessage({ input, command, custom_run_config: runConfig }, import_core66.QueueMode.STEER);
|
|
29906
30536
|
}
|
|
29907
30537
|
return true;
|
|
29908
30538
|
} catch (error) {
|
|
@@ -29921,7 +30551,7 @@ ${summary}`
|
|
|
29921
30551
|
return handleAgentTask(taskRequest, nextRetryCount);
|
|
29922
30552
|
}
|
|
29923
30553
|
if (callback_event) {
|
|
29924
|
-
|
|
30554
|
+
import_core66.eventBus.publish(callback_event, {
|
|
29925
30555
|
success: false,
|
|
29926
30556
|
error: error instanceof Error ? error.message : String(error)
|
|
29927
30557
|
});
|
|
@@ -29958,7 +30588,7 @@ var _AgentTaskConsumer = class _AgentTaskConsumer {
|
|
|
29958
30588
|
* 初始化事件监听和队列轮询
|
|
29959
30589
|
*/
|
|
29960
30590
|
initialize() {
|
|
29961
|
-
|
|
30591
|
+
import_core66.eventBus.subscribe(import_core66.AGENT_TASK_EVENT, this.trigger_agent_task.bind(this));
|
|
29962
30592
|
this.startPollingQueue();
|
|
29963
30593
|
console.log("Agent\u4EFB\u52A1\u6D88\u8D39\u8005\u5DF2\u542F\u52A8\u5E76\u76D1\u542C\u4EFB\u52A1\u4E8B\u4EF6\u548C\u961F\u5217");
|
|
29964
30594
|
}
|
|
@@ -30077,7 +30707,7 @@ var _AgentTaskConsumer = class _AgentTaskConsumer {
|
|
|
30077
30707
|
handleAgentTask(taskRequest).catch((error) => {
|
|
30078
30708
|
console.error("\u5904\u7406Agent\u4EFB\u52A1\u65F6\u53D1\u751F\u672A\u6355\u83B7\u7684\u9519\u8BEF:", error);
|
|
30079
30709
|
if (taskRequest.callback_event) {
|
|
30080
|
-
|
|
30710
|
+
import_core66.eventBus.publish(taskRequest.callback_event, {
|
|
30081
30711
|
success: false,
|
|
30082
30712
|
error: error instanceof Error ? error.message : String(error)
|
|
30083
30713
|
});
|
|
@@ -30092,13 +30722,13 @@ _AgentTaskConsumer.agent_run_endpoint = "http://localhost:4001/api/runs";
|
|
|
30092
30722
|
var AgentTaskConsumer = _AgentTaskConsumer;
|
|
30093
30723
|
|
|
30094
30724
|
// src/index.ts
|
|
30095
|
-
var
|
|
30725
|
+
var import_core92 = require("@axiom-lattice/core");
|
|
30096
30726
|
|
|
30097
30727
|
// src/channels/ChannelInfrastructure.ts
|
|
30098
|
-
var
|
|
30728
|
+
var import_core68 = require("@axiom-lattice/core");
|
|
30099
30729
|
|
|
30100
30730
|
// src/router/MessageRouter.ts
|
|
30101
|
-
var
|
|
30731
|
+
var import_core67 = require("@axiom-lattice/core");
|
|
30102
30732
|
var import_protocols32 = require("@axiom-lattice/protocols");
|
|
30103
30733
|
var import_crypto12 = require("crypto");
|
|
30104
30734
|
var BindingNotFoundError = class extends Error {
|
|
@@ -30384,7 +31014,7 @@ var MessageRouter = class {
|
|
|
30384
31014
|
channel: message.channel,
|
|
30385
31015
|
adapterChannel: adapter.channel
|
|
30386
31016
|
}, "Thread resolved by adapter strategy");
|
|
30387
|
-
const threadStore = (0,
|
|
31017
|
+
const threadStore = (0, import_core67.getStoreLattice)("default", "thread").store;
|
|
30388
31018
|
try {
|
|
30389
31019
|
await threadStore.createThread(
|
|
30390
31020
|
tenantId,
|
|
@@ -30421,7 +31051,7 @@ var MessageRouter = class {
|
|
|
30421
31051
|
}
|
|
30422
31052
|
}
|
|
30423
31053
|
if (!threadId) {
|
|
30424
|
-
const threadStore = (0,
|
|
31054
|
+
const threadStore = (0, import_core67.getStoreLattice)("default", "thread").store;
|
|
30425
31055
|
const newThreadId = (0, import_crypto12.randomUUID)();
|
|
30426
31056
|
console.log({
|
|
30427
31057
|
event: "dispatch:thread:create",
|
|
@@ -30461,7 +31091,7 @@ var MessageRouter = class {
|
|
|
30461
31091
|
senderId: message.sender.id,
|
|
30462
31092
|
contentLength: message.content.text.length
|
|
30463
31093
|
}, "Dispatching to agent");
|
|
30464
|
-
const agent =
|
|
31094
|
+
const agent = import_core67.agentInstanceManager.getAgent({
|
|
30465
31095
|
tenant_id: tenantId,
|
|
30466
31096
|
assistant_id: agentId,
|
|
30467
31097
|
thread_id: threadId,
|
|
@@ -30734,7 +31364,7 @@ function createChannelInfrastructure(deps) {
|
|
|
30734
31364
|
onMessageCommitted: deps.onMessageCommitted ?? (deps.realtime ? (message) => deps.realtime?.messageCreated(message) : void 0),
|
|
30735
31365
|
onCallbackFailure: (event) => deps.warn("project-room:message-commit-callback-failed", event)
|
|
30736
31366
|
};
|
|
30737
|
-
deps.adapterRegistry.register(createRoomChannelAdapter(new
|
|
31367
|
+
deps.adapterRegistry.register(createRoomChannelAdapter(new import_core68.RoomAgentMessageService(writerDeps)));
|
|
30738
31368
|
} catch (error) {
|
|
30739
31369
|
deps.warn("Room channel unavailable", { error: error instanceof Error ? error.message : String(error) });
|
|
30740
31370
|
}
|
|
@@ -30754,11 +31384,168 @@ async function prepareProjectTaskRuntime(runtime, log2) {
|
|
|
30754
31384
|
}
|
|
30755
31385
|
}
|
|
30756
31386
|
|
|
31387
|
+
// src/services/multiReplicaReadiness.ts
|
|
31388
|
+
var import_core69 = require("@axiom-lattice/core");
|
|
31389
|
+
var SHARED_STORE_KINDS = ["lease", "outbox", "threadMessageQueue", "task", "taskWorkItem"];
|
|
31390
|
+
function storeClassName(kind) {
|
|
31391
|
+
try {
|
|
31392
|
+
return (0, import_core69.getStoreLattice)("default", kind).store.constructor?.name;
|
|
31393
|
+
} catch {
|
|
31394
|
+
return void 0;
|
|
31395
|
+
}
|
|
31396
|
+
}
|
|
31397
|
+
function warnMultiReplicaReadiness(logger8) {
|
|
31398
|
+
if (typeof process.env.AXIOM_REPLICA_ID !== "string" || process.env.AXIOM_REPLICA_ID.trim() === "") return;
|
|
31399
|
+
for (const kind of SHARED_STORE_KINDS) {
|
|
31400
|
+
const name = storeClassName(kind);
|
|
31401
|
+
if (name === void 0 || !name.startsWith("InMemory")) continue;
|
|
31402
|
+
logger8.warn(`Multi-replica: store '${kind}' is ${name} (not shared); configure a shared store`, {
|
|
31403
|
+
phase: "multi_replica_readiness",
|
|
31404
|
+
store: kind
|
|
31405
|
+
});
|
|
31406
|
+
}
|
|
31407
|
+
if (!process.env.AUTH_TOKEN_SECRET?.trim() && !process.env.JWT_SECRET?.trim()) {
|
|
31408
|
+
logger8.warn(
|
|
31409
|
+
"Multi-replica: AUTH_TOKEN_SECRET/JWT_SECRET unset; console sessions are signed per-process and will not verify across replicas",
|
|
31410
|
+
{ phase: "multi_replica_readiness", env: "AUTH_TOKEN_SECRET" }
|
|
31411
|
+
);
|
|
31412
|
+
}
|
|
31413
|
+
if (!process.env.LATTICE_ENCRYPTION_KEY?.trim()) {
|
|
31414
|
+
logger8.warn(
|
|
31415
|
+
"Multi-replica: LATTICE_ENCRYPTION_KEY unset; stored credentials use the shared dev default and may not decrypt across differing keys",
|
|
31416
|
+
{ phase: "multi_replica_readiness", env: "LATTICE_ENCRYPTION_KEY" }
|
|
31417
|
+
);
|
|
31418
|
+
}
|
|
31419
|
+
logger8.warn(
|
|
31420
|
+
"Multi-replica: agent run SSE and resume_stream are process-local; route a thread's follow-up runs to the replica streaming it (sticky routing) or share the stream/queue state",
|
|
31421
|
+
{ phase: "multi_replica_readiness", feature: "agent-run-sse" }
|
|
31422
|
+
);
|
|
31423
|
+
}
|
|
31424
|
+
|
|
31425
|
+
// src/services/OutboxRetentionJob.ts
|
|
31426
|
+
var HOUR_MS = 60 * 60 * 1e3;
|
|
31427
|
+
var DEFAULT_INTERVAL_MS2 = 6 * HOUR_MS;
|
|
31428
|
+
var DEFAULT_INITIAL_DELAY_MS2 = 6e4;
|
|
31429
|
+
var AXIOM_OUTBOX_RETENTION_HOURS_ENV = "AXIOM_OUTBOX_RETENTION_HOURS";
|
|
31430
|
+
var DEFAULT_RETENTION_HOURS = 24;
|
|
31431
|
+
function parseRetentionHours(value) {
|
|
31432
|
+
if (value === void 0 || value === null) return DEFAULT_RETENTION_HOURS;
|
|
31433
|
+
if (typeof value !== "string") return void 0;
|
|
31434
|
+
const trimmed = value.trim();
|
|
31435
|
+
if (trimmed.length === 0) return DEFAULT_RETENTION_HOURS;
|
|
31436
|
+
const parsed = Number(trimmed);
|
|
31437
|
+
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : void 0;
|
|
31438
|
+
}
|
|
31439
|
+
var OutboxRetentionJob = class {
|
|
31440
|
+
/** @param deps Outbox slice, logger, and optional retention/interval bounds. */
|
|
31441
|
+
constructor(deps) {
|
|
31442
|
+
this.deps = deps;
|
|
31443
|
+
this.running = false;
|
|
31444
|
+
this.stopped = false;
|
|
31445
|
+
}
|
|
31446
|
+
/** Schedules one delayed sweep plus the recurring interval (both unref'd). */
|
|
31447
|
+
start() {
|
|
31448
|
+
if (this.stopped || this.deps.retentionMs === void 0) return;
|
|
31449
|
+
if (this.initial !== void 0 || this.interval !== void 0) return;
|
|
31450
|
+
this.initial = setTimeout(() => {
|
|
31451
|
+
this.initial = void 0;
|
|
31452
|
+
void this.runOnce();
|
|
31453
|
+
}, this.deps.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS2);
|
|
31454
|
+
this.initial.unref?.();
|
|
31455
|
+
this.interval = setInterval(() => void this.runOnce(), this.deps.intervalMs ?? DEFAULT_INTERVAL_MS2);
|
|
31456
|
+
this.interval.unref?.();
|
|
31457
|
+
}
|
|
31458
|
+
/**
|
|
31459
|
+
* Runs one age-based prune.
|
|
31460
|
+
*
|
|
31461
|
+
* @returns The number of rows removed (0 when disabled, overlapping, or on failure).
|
|
31462
|
+
*/
|
|
31463
|
+
async runOnce() {
|
|
31464
|
+
const retentionMs = this.deps.retentionMs;
|
|
31465
|
+
if (this.stopped || retentionMs === void 0 || this.running) return 0;
|
|
31466
|
+
this.running = true;
|
|
31467
|
+
try {
|
|
31468
|
+
const removed = await this.deps.outbox.pruneOlderThan(retentionMs);
|
|
31469
|
+
if (removed > 0) this.deps.log.info("outbox pruned", { removed });
|
|
31470
|
+
return removed;
|
|
31471
|
+
} catch (error) {
|
|
31472
|
+
this.deps.log.warn("outbox prune failed", {
|
|
31473
|
+
error: error instanceof Error ? error.message : String(error)
|
|
31474
|
+
});
|
|
31475
|
+
return 0;
|
|
31476
|
+
} finally {
|
|
31477
|
+
this.running = false;
|
|
31478
|
+
}
|
|
31479
|
+
}
|
|
31480
|
+
/** Stops the timers; an in-flight sweep finishes on its own. */
|
|
31481
|
+
stop() {
|
|
31482
|
+
this.stopped = true;
|
|
31483
|
+
if (this.initial !== void 0) {
|
|
31484
|
+
clearTimeout(this.initial);
|
|
31485
|
+
this.initial = void 0;
|
|
31486
|
+
}
|
|
31487
|
+
if (this.interval !== void 0) {
|
|
31488
|
+
clearInterval(this.interval);
|
|
31489
|
+
this.interval = void 0;
|
|
31490
|
+
}
|
|
31491
|
+
}
|
|
31492
|
+
};
|
|
31493
|
+
function createOutboxRetentionJob(deps) {
|
|
31494
|
+
const retentionMs = deps.retentionMs ?? resolveRetentionMs(process.env[AXIOM_OUTBOX_RETENTION_HOURS_ENV]);
|
|
31495
|
+
return new OutboxRetentionJob({ ...deps, retentionMs });
|
|
31496
|
+
}
|
|
31497
|
+
function resolveRetentionMs(value) {
|
|
31498
|
+
const hours = parseRetentionHours(value);
|
|
31499
|
+
return hours === void 0 ? void 0 : hours * HOUR_MS;
|
|
31500
|
+
}
|
|
31501
|
+
|
|
31502
|
+
// src/services/collaboration/roomEventSync.ts
|
|
31503
|
+
var ROOM_EVENT_TOPIC = "room-event";
|
|
31504
|
+
async function publishRoomEvent(outbox, owner, scope, serialized, sourceKey) {
|
|
31505
|
+
try {
|
|
31506
|
+
await outbox.append({
|
|
31507
|
+
topic: ROOM_EVENT_TOPIC,
|
|
31508
|
+
payload: { scope, serialized, sourceKey },
|
|
31509
|
+
originReplicaId: owner
|
|
31510
|
+
});
|
|
31511
|
+
} catch {
|
|
31512
|
+
}
|
|
31513
|
+
}
|
|
31514
|
+
function ingestRoomEvent(payload, broker) {
|
|
31515
|
+
const record = payload;
|
|
31516
|
+
const serialized = record?.serialized;
|
|
31517
|
+
if (typeof serialized !== "string" || serialized.length === 0) return false;
|
|
31518
|
+
const sourceKey = record?.sourceKey;
|
|
31519
|
+
if (typeof sourceKey === "string" && sourceKey.length > 0) {
|
|
31520
|
+
return broker.ingestForeignEvent(serialized, sourceKey);
|
|
31521
|
+
}
|
|
31522
|
+
return broker.ingestForeignEvent(serialized);
|
|
31523
|
+
}
|
|
31524
|
+
|
|
31525
|
+
// src/services/assistantRegistrySync.ts
|
|
31526
|
+
var ASSISTANT_CHANGE_EVENTS = ["assistant:created", "assistant:updated", "assistant:deleted"];
|
|
31527
|
+
var ASSISTANT_CHANGED_TOPIC = "assistant-changed";
|
|
31528
|
+
function bridgeAssistantEvents(subscribe, outbox, owner) {
|
|
31529
|
+
for (const event of ASSISTANT_CHANGE_EVENTS) {
|
|
31530
|
+
subscribe(event, (data) => {
|
|
31531
|
+
const tenantId = data?.tenantId;
|
|
31532
|
+
if (typeof tenantId !== "string" || tenantId.length === 0) return;
|
|
31533
|
+
void outbox.append({ topic: ASSISTANT_CHANGED_TOPIC, payload: { tenantId }, originReplicaId: owner }).catch(() => void 0);
|
|
31534
|
+
});
|
|
31535
|
+
}
|
|
31536
|
+
}
|
|
31537
|
+
async function handleAssistantChanged(payload, reload) {
|
|
31538
|
+
const tenantId = payload?.tenantId;
|
|
31539
|
+
if (typeof tenantId !== "string" || tenantId.length === 0) return;
|
|
31540
|
+
await reload(tenantId);
|
|
31541
|
+
}
|
|
31542
|
+
|
|
30757
31543
|
// src/index.ts
|
|
30758
31544
|
var import_protocols40 = require("@axiom-lattice/protocols");
|
|
30759
31545
|
init_TopCallerRecovery();
|
|
30760
31546
|
init_OrphanRecoveryRuntime();
|
|
30761
31547
|
init_RecoveryCallerDeps();
|
|
31548
|
+
init_taskRunLiveness();
|
|
30762
31549
|
process.on("unhandledRejection", (reason, promise) => {
|
|
30763
31550
|
console.error("\u672A\u5904\u7406\u7684Promise\u62D2\u7EDD:", reason);
|
|
30764
31551
|
});
|
|
@@ -30772,11 +31559,11 @@ var DEFAULT_LOGGER_CONFIG = {
|
|
|
30772
31559
|
var loggerLattice = initializeLogger(DEFAULT_LOGGER_CONFIG);
|
|
30773
31560
|
var logger7 = loggerLattice.client;
|
|
30774
31561
|
function initializeLogger(config) {
|
|
30775
|
-
if (
|
|
30776
|
-
|
|
31562
|
+
if (import_core92.loggerLatticeManager.hasLattice("default")) {
|
|
31563
|
+
import_core92.loggerLatticeManager.removeLattice("default");
|
|
30777
31564
|
}
|
|
30778
|
-
(0,
|
|
30779
|
-
return (0,
|
|
31565
|
+
(0, import_core92.registerLoggerLattice)("default", config);
|
|
31566
|
+
return (0, import_core92.getLoggerLattice)("default");
|
|
30780
31567
|
}
|
|
30781
31568
|
var app = (0, import_fastify.default)({
|
|
30782
31569
|
logger: false,
|
|
@@ -30837,7 +31624,7 @@ app.register(import_cors.default, {
|
|
|
30837
31624
|
origin: true,
|
|
30838
31625
|
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
|
|
30839
31626
|
allowedHeaders: "*",
|
|
30840
|
-
exposedHeaders: ["Content-Type", "Content-Disposition"],
|
|
31627
|
+
exposedHeaders: ["Content-Type", "Content-Disposition", import_protocols40.REPLICA_HEADER, import_protocols40.AFFINITY_ECHO_HEADER],
|
|
30841
31628
|
credentials: true
|
|
30842
31629
|
});
|
|
30843
31630
|
app.register(import_sensible.default);
|
|
@@ -30873,7 +31660,7 @@ app.setErrorHandler((error, request, reply) => {
|
|
|
30873
31660
|
});
|
|
30874
31661
|
function getConfiguredSandboxProvider() {
|
|
30875
31662
|
const sandboxProviderType = process.env.SANDBOX_PROVIDER_TYPE || "microsandbox-remote";
|
|
30876
|
-
return (0,
|
|
31663
|
+
return (0, import_core92.createSandboxProvider)({
|
|
30877
31664
|
type: sandboxProviderType,
|
|
30878
31665
|
remoteBaseURL: process.env.SANDBOX_BASE_URL,
|
|
30879
31666
|
microsandboxServiceBaseURL: process.env.MICROSANDBOX_SERVICE_BASE_URL,
|
|
@@ -30889,7 +31676,7 @@ function getConfiguredSandboxProvider() {
|
|
|
30889
31676
|
}
|
|
30890
31677
|
async function restoreMcpConnections() {
|
|
30891
31678
|
try {
|
|
30892
|
-
const storeLattice = (0,
|
|
31679
|
+
const storeLattice = (0, import_core92.getStoreLattice)("default", "mcp");
|
|
30893
31680
|
const store2 = storeLattice.store;
|
|
30894
31681
|
if (!store2) {
|
|
30895
31682
|
logger7.info("MCP store not configured, skipping connection restoration");
|
|
@@ -30900,25 +31687,16 @@ async function restoreMcpConnections() {
|
|
|
30900
31687
|
);
|
|
30901
31688
|
if (configs.length === 0) return;
|
|
30902
31689
|
logger7.info(`Restoring ${configs.length} MCP server connections...`);
|
|
30903
|
-
|
|
30904
|
-
|
|
30905
|
-
|
|
30906
|
-
|
|
30907
|
-
|
|
30908
|
-
maxAttempts: config.config.retryAttempts,
|
|
30909
|
-
selectedTools: config.selectedTools
|
|
30910
|
-
});
|
|
30911
|
-
} catch (err) {
|
|
30912
|
-
logger7.warn(`Failed to prepare MCP server "${config.tenantId}/${config.key}"`, { error: err });
|
|
30913
|
-
}
|
|
30914
|
-
}
|
|
30915
|
-
await import_core85.mcpManager.connectAll();
|
|
31690
|
+
const deps = {
|
|
31691
|
+
store: store2,
|
|
31692
|
+
manager: import_core92.mcpManager,
|
|
31693
|
+
convertToConnection: import_core92.convertToConnection
|
|
31694
|
+
};
|
|
30916
31695
|
const results = await Promise.allSettled(
|
|
30917
31696
|
configs.map(
|
|
30918
|
-
(config) =>
|
|
30919
|
-
config.tenantId,
|
|
30920
|
-
|
|
30921
|
-
config.selectedTools
|
|
31697
|
+
(config) => reconcileMcpConfigChange(
|
|
31698
|
+
{ tenantId: config.tenantId, serverKey: config.key },
|
|
31699
|
+
deps
|
|
30922
31700
|
)
|
|
30923
31701
|
)
|
|
30924
31702
|
);
|
|
@@ -30926,7 +31704,7 @@ async function restoreMcpConnections() {
|
|
|
30926
31704
|
if (result.status === "rejected") {
|
|
30927
31705
|
const config = configs[index];
|
|
30928
31706
|
logger7.warn(
|
|
30929
|
-
`Failed to
|
|
31707
|
+
`Failed to restore MCP server "${config.tenantId}/${config.key}"`,
|
|
30930
31708
|
{ error: result.reason }
|
|
30931
31709
|
);
|
|
30932
31710
|
}
|
|
@@ -30953,9 +31731,9 @@ var start = async (config) => {
|
|
|
30953
31731
|
let projectRoomRealtimeRuntime;
|
|
30954
31732
|
if (projectRoomRealtimeMode === "single-gateway") {
|
|
30955
31733
|
projectRoomRealtimeRuntime = createProjectRoomRealtimeRuntime({
|
|
30956
|
-
tasks: (0,
|
|
30957
|
-
rooms: (0,
|
|
30958
|
-
memberships: (0,
|
|
31734
|
+
tasks: (0, import_core92.getStoreLattice)("default", "task").store,
|
|
31735
|
+
rooms: (0, import_core92.getStoreLattice)("default", "projectRoom").store,
|
|
31736
|
+
memberships: (0, import_core92.getStoreLattice)("default", "projectBotMembership").store,
|
|
30959
31737
|
log: { warn: (message, context) => logger7.warn(message, context) }
|
|
30960
31738
|
});
|
|
30961
31739
|
}
|
|
@@ -30969,7 +31747,7 @@ var start = async (config) => {
|
|
|
30969
31747
|
const infrastructure = createChannelInfrastructure({
|
|
30970
31748
|
adapterRegistry,
|
|
30971
31749
|
getStore: ((kind) => getStore11("default", kind).store),
|
|
30972
|
-
trustedDispatcher: (0,
|
|
31750
|
+
trustedDispatcher: (0, import_core92.createTrustedAgentMessageDispatcher)((scope) => import_core92.agentInstanceManager.getAgent(scope)),
|
|
30973
31751
|
middlewares: [
|
|
30974
31752
|
createDeduplicationMiddleware(),
|
|
30975
31753
|
createRateLimitMiddleware(),
|
|
@@ -30980,7 +31758,7 @@ var start = async (config) => {
|
|
|
30980
31758
|
});
|
|
30981
31759
|
const bindingStore = infrastructure.bindingRegistry;
|
|
30982
31760
|
const installationStore = infrastructure.installationStore;
|
|
30983
|
-
(0,
|
|
31761
|
+
(0, import_core91.setBindingRegistry)(bindingStore);
|
|
30984
31762
|
const router = infrastructure.router;
|
|
30985
31763
|
app.addHook("onClose", async () => router.dispose());
|
|
30986
31764
|
channelDeps = {
|
|
@@ -30996,10 +31774,10 @@ var start = async (config) => {
|
|
|
30996
31774
|
error: err instanceof Error ? err.message : String(err)
|
|
30997
31775
|
});
|
|
30998
31776
|
}
|
|
30999
|
-
(0,
|
|
31777
|
+
(0, import_core91.setEvalRunService)(evalRunner);
|
|
31000
31778
|
try {
|
|
31001
|
-
const menuStore = (0,
|
|
31002
|
-
(0,
|
|
31779
|
+
const menuStore = (0, import_core92.getStoreLattice)("default", "menu").store;
|
|
31780
|
+
(0, import_core91.setMenuRegistry)(menuStore);
|
|
31003
31781
|
logger7.info("Menu registry initialized");
|
|
31004
31782
|
} catch {
|
|
31005
31783
|
}
|
|
@@ -31016,10 +31794,10 @@ var start = async (config) => {
|
|
|
31016
31794
|
const { A2AAuthService: A2AAuthService2, parseEnvKeys: parseEnvKeys2 } = await Promise.resolve().then(() => (init_A2AAuthService(), A2AAuthService_exports));
|
|
31017
31795
|
const { registerA2AStandardRoutes: registerA2AStandardRoutes2 } = await Promise.resolve().then(() => (init_a2a_standard(), a2a_standard_exports));
|
|
31018
31796
|
const a2a = await Promise.resolve().then(() => (init_a2a(), a2a_exports));
|
|
31019
|
-
const a2aKeyStore = (0,
|
|
31020
|
-
const assistantStore = (0,
|
|
31021
|
-
const projectStore = (0,
|
|
31022
|
-
const taskStore = (0,
|
|
31797
|
+
const a2aKeyStore = (0, import_core92.getStoreLattice)("default", "a2aApiKey").store;
|
|
31798
|
+
const assistantStore = (0, import_core92.getStoreLattice)("default", "assistant").store;
|
|
31799
|
+
const projectStore = (0, import_core92.getStoreLattice)("default", "project").store;
|
|
31800
|
+
const taskStore = (0, import_core92.getStoreLattice)("default", "task").store;
|
|
31023
31801
|
const authService = new A2AAuthService2({
|
|
31024
31802
|
keyStore: a2aKeyStore,
|
|
31025
31803
|
assistantStore,
|
|
@@ -31058,8 +31836,8 @@ var start = async (config) => {
|
|
|
31058
31836
|
const { CollectionService: CollectionService2 } = await Promise.resolve().then(() => (init_collection_service(), collection_service_exports));
|
|
31059
31837
|
openLattice2.register(createKbProvider2(new CollectionService2()));
|
|
31060
31838
|
openLattice2.register(createOpenSandboxProvider2());
|
|
31061
|
-
const threadStore = (0,
|
|
31062
|
-
const assistantStore = (0,
|
|
31839
|
+
const threadStore = (0, import_core92.getStoreLattice)("default", "thread").store;
|
|
31840
|
+
const assistantStore = (0, import_core92.getStoreLattice)("default", "assistant").store;
|
|
31063
31841
|
openLattice2.register(
|
|
31064
31842
|
createAgentProvider2({
|
|
31065
31843
|
threadStore,
|
|
@@ -31082,18 +31860,29 @@ var start = async (config) => {
|
|
|
31082
31860
|
error: err instanceof Error ? err.message : String(err)
|
|
31083
31861
|
});
|
|
31084
31862
|
}
|
|
31085
|
-
|
|
31086
|
-
|
|
31863
|
+
try {
|
|
31864
|
+
const { registerGatewaySandboxOpenCredentialProvider: registerGatewaySandboxOpenCredentialProvider2 } = await Promise.resolve().then(() => (init_sandboxOpenCredentialProvider(), sandboxOpenCredentialProvider_exports));
|
|
31865
|
+
registerGatewaySandboxOpenCredentialProvider2((error) => {
|
|
31866
|
+
logger7.warn("sandbox open-credential provider failed", { error });
|
|
31867
|
+
});
|
|
31868
|
+
logger7.info("Sandbox open-credential provider registered");
|
|
31869
|
+
} catch (err) {
|
|
31870
|
+
logger7.warn("Sandbox open-credential provider unavailable", {
|
|
31871
|
+
error: err instanceof Error ? err.message : String(err)
|
|
31872
|
+
});
|
|
31873
|
+
}
|
|
31874
|
+
if (!import_core92.sandboxLatticeManager.hasLattice("default")) {
|
|
31875
|
+
import_core92.sandboxLatticeManager.registerLattice("default", getConfiguredSandboxProvider());
|
|
31087
31876
|
logger7.info("Registered sandbox manager from env configuration");
|
|
31088
31877
|
}
|
|
31089
31878
|
try {
|
|
31090
31879
|
const { ResourceController: ResourceController2 } = await Promise.resolve().then(() => (init_resources(), resources_exports));
|
|
31091
|
-
const sharedResourceStore = (0,
|
|
31092
|
-
const
|
|
31880
|
+
const sharedResourceStore = (0, import_core92.getStoreLattice)("default", "sharedResource").store;
|
|
31881
|
+
const cache2 = new import_core92.TokenCache();
|
|
31093
31882
|
const resourceController = new ResourceController2({
|
|
31094
31883
|
store: sharedResourceStore,
|
|
31095
|
-
sandboxManager:
|
|
31096
|
-
cache,
|
|
31884
|
+
sandboxManager: import_core92.sandboxLatticeManager,
|
|
31885
|
+
cache: cache2,
|
|
31097
31886
|
logger: logger7
|
|
31098
31887
|
});
|
|
31099
31888
|
registerResourceRoutes(app, resourceController);
|
|
@@ -31117,30 +31906,98 @@ var start = async (config) => {
|
|
|
31117
31906
|
}
|
|
31118
31907
|
}
|
|
31119
31908
|
const target_port = config?.port || Number(process.env.PORT) || 4001;
|
|
31120
|
-
|
|
31121
|
-
|
|
31909
|
+
(0, import_core92.configureCoordinationLeaseStore)((0, import_core92.getStoreLattice)("default", "lease").store);
|
|
31910
|
+
const outboxStore = (0, import_core92.getStoreLattice)("default", "outbox").store;
|
|
31911
|
+
import_core92.taskLifecycleNotifier.setOutbox(outboxStore);
|
|
31912
|
+
import_core92.projectTaskAdmissionNotifier.setOutbox(outboxStore);
|
|
31913
|
+
(0, import_core92.configurePluginCatalogSync)({ outbox: outboxStore, owner: (0, import_core92.getReplicaId)() });
|
|
31914
|
+
bridgeAssistantEvents(
|
|
31915
|
+
(event, cb) => import_core92.eventBus.subscribe(event, cb),
|
|
31916
|
+
outboxStore,
|
|
31917
|
+
(0, import_core92.getReplicaId)()
|
|
31918
|
+
);
|
|
31919
|
+
if (projectRoomRealtimeRuntime) {
|
|
31920
|
+
projectRoomRealtimeRuntime.broker.setBroadcastHook((scope, serialized, sourceKey) => {
|
|
31921
|
+
void publishRoomEvent(outboxStore, (0, import_core92.getReplicaId)(), scope, serialized, sourceKey);
|
|
31922
|
+
});
|
|
31122
31923
|
}
|
|
31123
|
-
|
|
31124
|
-
|
|
31125
|
-
|
|
31126
|
-
|
|
31127
|
-
|
|
31128
|
-
|
|
31129
|
-
|
|
31130
|
-
|
|
31131
|
-
|
|
31132
|
-
|
|
31133
|
-
|
|
31134
|
-
|
|
31135
|
-
|
|
31136
|
-
|
|
31137
|
-
|
|
31138
|
-
|
|
31139
|
-
|
|
31924
|
+
const outboxPoller = new import_core92.OutboxPoller({
|
|
31925
|
+
store: outboxStore,
|
|
31926
|
+
owner: (0, import_core92.getReplicaId)(),
|
|
31927
|
+
handlers: {
|
|
31928
|
+
"task-lifecycle": (payload) => import_core92.taskLifecycleNotifier.deliverFromOutbox(payload),
|
|
31929
|
+
"project-task-admission": (payload) => import_core92.projectTaskAdmissionNotifier.deliverFromOutbox(payload),
|
|
31930
|
+
[ROOM_EVENT_TOPIC]: async (payload) => {
|
|
31931
|
+
if (projectRoomRealtimeRuntime) ingestRoomEvent(payload, projectRoomRealtimeRuntime.broker);
|
|
31932
|
+
},
|
|
31933
|
+
"assistant-changed": (payload) => handleAssistantChanged(payload, (tenantId) => import_core92.agentLatticeManager.initializeStoredAssistantsForTenant(tenantId)),
|
|
31934
|
+
[MCP_CONFIG_CHANGED_TOPIC]: (payload) => reconcileMcpConfigChange(payload, {
|
|
31935
|
+
store: (0, import_core92.getStoreLattice)("default", "mcp").store,
|
|
31936
|
+
manager: import_core92.mcpManager,
|
|
31937
|
+
convertToConnection: import_core92.convertToConnection
|
|
31938
|
+
}),
|
|
31939
|
+
[import_core92.PLUGIN_CATALOG_CHANGED_TOPIC]: async (payload) => {
|
|
31940
|
+
const tenantId = payload?.tenantId;
|
|
31941
|
+
if (typeof tenantId === "string" && tenantId.length > 0) (0, import_core92.getSandboxPluginCatalog)().invalidate(tenantId);
|
|
31942
|
+
}
|
|
31943
|
+
},
|
|
31944
|
+
log: logger7
|
|
31945
|
+
});
|
|
31946
|
+
try {
|
|
31947
|
+
await outboxPoller.start();
|
|
31948
|
+
} catch (err) {
|
|
31949
|
+
logger7.warn("Outbox poller failed to start", { error: err instanceof Error ? err.message : String(err) });
|
|
31950
|
+
}
|
|
31951
|
+
const leaseStore = (0, import_core92.getStoreLattice)("default", "lease").store;
|
|
31952
|
+
if (leaseStore.constructor?.name === "InMemoryLeaseStore") {
|
|
31953
|
+
logger7.warn(
|
|
31954
|
+
"Startup recovery leader gate uses a non-distributed lease store (per-process only); configure a shared 'lease' store for multi-replica deployments",
|
|
31955
|
+
{ phase: "startup_recovery" }
|
|
31956
|
+
);
|
|
31957
|
+
}
|
|
31958
|
+
warnMultiReplicaReadiness(logger7);
|
|
31959
|
+
const startup = await (0, import_core92.runAsLeader)(leaseStore, "startup-recovery", async () => {
|
|
31960
|
+
if (routes.projectTaskRuntime) {
|
|
31961
|
+
await prepareProjectTaskRuntime(routes.projectTaskRuntime, logger7);
|
|
31140
31962
|
}
|
|
31963
|
+
if (process.env.AXIOM_TASK_ORPHAN_RECOVERY === "true") {
|
|
31964
|
+
try {
|
|
31965
|
+
const { createOrphanRecoveryRuntime: createOrphanRecoveryRuntime2 } = await Promise.resolve().then(() => (init_OrphanRecoveryRuntime(), OrphanRecoveryRuntime_exports));
|
|
31966
|
+
const { createRecoveryCallerDeps: createRecoveryCallerDeps2 } = await Promise.resolve().then(() => (init_RecoveryCallerDeps(), RecoveryCallerDeps_exports));
|
|
31967
|
+
const runtime = createOrphanRecoveryRuntime2({
|
|
31968
|
+
taskStore: (0, import_core92.getStoreLattice)("default", "task").store,
|
|
31969
|
+
workItemStore: (0, import_core92.getStoreLattice)("default", "taskWorkItem").store,
|
|
31970
|
+
tenantStore: (0, import_core92.getStoreLattice)("default", "tenant").store,
|
|
31971
|
+
...createRecoveryCallerDeps2(),
|
|
31972
|
+
log: logger7
|
|
31973
|
+
});
|
|
31974
|
+
await runtime.recoverAll();
|
|
31975
|
+
} catch (err) {
|
|
31976
|
+
logger7.warn("Task orphan recovery failed", { error: err instanceof Error ? err.message : String(err) });
|
|
31977
|
+
}
|
|
31978
|
+
}
|
|
31979
|
+
if (import_core92.scheduleLatticeManager.hasLattice("default")) {
|
|
31980
|
+
try {
|
|
31981
|
+
const restored = await import_core92.scheduleLatticeManager.getScheduleLattice("default").restore();
|
|
31982
|
+
logger7.info("Scheduled tasks restored", { phase: "startup_recovery", restored });
|
|
31983
|
+
} catch (err) {
|
|
31984
|
+
logger7.warn("Scheduled task restore failed", {
|
|
31985
|
+
phase: "startup_recovery",
|
|
31986
|
+
error: err instanceof Error ? err.message : String(err)
|
|
31987
|
+
});
|
|
31988
|
+
}
|
|
31989
|
+
}
|
|
31990
|
+
}, { hold: true, ttlMs: 5 * 6e4 });
|
|
31991
|
+
if (!startup.ran) {
|
|
31992
|
+
logger7.info("Startup recovery skipped (another replica leads)", { phase: "startup_recovery" });
|
|
31141
31993
|
}
|
|
31142
31994
|
await app.listen({ port: target_port, host: "0.0.0.0" });
|
|
31143
31995
|
logger7.info(`Lattice Gateway is running on port: ${target_port}`);
|
|
31996
|
+
const outboxRetention = createOutboxRetentionJob({
|
|
31997
|
+
outbox: outboxStore,
|
|
31998
|
+
log: logger7
|
|
31999
|
+
});
|
|
32000
|
+
outboxRetention.start();
|
|
31144
32001
|
const queueServiceConfig = config?.queueServiceConfig;
|
|
31145
32002
|
if (queueServiceConfig) {
|
|
31146
32003
|
setQueueServiceType(queueServiceConfig.type);
|
|
@@ -31167,8 +32024,13 @@ var LatticeGateway = {
|
|
|
31167
32024
|
// Annotate the CommonJS export names for ESM import in node:
|
|
31168
32025
|
0 && (module.exports = {
|
|
31169
32026
|
LatticeGateway,
|
|
32027
|
+
ProjectRoomEventBroker,
|
|
32028
|
+
ROOM_EVENT_TOPIC,
|
|
31170
32029
|
createOrphanRecoveryRuntime,
|
|
31171
32030
|
createRecoveryCallerDeps,
|
|
32031
|
+
createTaskRunLiveness,
|
|
32032
|
+
ingestRoomEvent,
|
|
32033
|
+
publishRoomEvent,
|
|
31172
32034
|
recoverTask,
|
|
31173
32035
|
recoverTopCaller,
|
|
31174
32036
|
resolveTopCaller,
|