@axiom-lattice/gateway 6.0.1 → 6.1.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/embed/{embed-page-AgentDetailSideApp-JYVZKSUU.js → embed-page-AgentDetailSideApp-2UFH4RJG.js} +1 -1
- package/dist/embed/{embed-page-AgentGovernanceWorkbench-SD2EHW2B.js → embed-page-AgentGovernanceWorkbench-3JOSRW2V.js} +1 -1
- package/dist/embed/{embed-page-MessageGraph-GLQXKAVC.js → embed-page-MessageGraph-SPB75EHC.js} +1 -1
- package/dist/embed/{embed-page-ReactChart-74MHCE2K.js → embed-page-ReactChart-EE4A5WKS.js} +1 -1
- package/dist/embed/{embed-page-SkillFlow-NDAK3GAD.js → embed-page-SkillFlow-H2ARZGEX.js} +1 -1
- package/dist/embed/{embed-page-TasksSideApp-DA4LUTMD.js → embed-page-TasksSideApp-BQMOLOUF.js} +1 -1
- package/dist/embed/{embed-page-TeamWorkspace-DUB3L6V6.js → embed-page-TeamWorkspace-QXMRVXWU.js} +1 -1
- package/dist/embed/{embed-page-TopologyRuntimeView-NFBHAICN.js → embed-page-TopologyRuntimeView-OSV75P6Y.js} +1 -1
- package/dist/embed/{embed-page-WorkflowAutomationView-43YGTXGF.js → embed-page-WorkflowAutomationView-KJ6HJ5UT.js} +1 -1
- package/dist/embed/{embed-page-chunk-UHH575CK.js → embed-page-chunk-DBUC6J4G.js} +1 -1
- package/dist/embed/{embed-page-chunk-C4ZV4IXK.js → embed-page-chunk-E6F5YZBR.js} +1 -1
- package/dist/embed/{embed-page-chunk-BVSC3MSO.js → embed-page-chunk-FGKHXQAJ.js} +1 -1
- package/dist/embed/{embed-page-chunk-2PFKLMTR.js → embed-page-chunk-GSCVATOA.js} +1 -1
- package/dist/embed/{embed-page-chunk-GKHIPXZ2.js → embed-page-chunk-IIEDLN7W.js} +1 -1
- package/dist/embed/{embed-page-chunk-P477ZTUO.js → embed-page-chunk-U4XSGC4Y.js} +163 -163
- package/dist/embed/{embed-page-chunk-DWIBLGBW.js → embed-page-chunk-VXWRPT33.js} +1 -1
- package/dist/embed/{embed-page-en-S4MXFPIU.js → embed-page-en-X6B6RVNL.js} +1 -1
- package/dist/embed/{embed-page-zh-SSMSF5LE.js → embed-page-zh-EQ5X2M32.js} +1 -1
- package/dist/embed/embed-page.js +1 -1
- package/dist/index.d.mts +43 -8
- package/dist/index.d.ts +43 -8
- package/dist/index.js +1117 -365
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +907 -148
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1445,11 +1445,11 @@ async function resolveAgentOpenGrants(tenantId, assistantId, deps) {
|
|
|
1445
1445
|
}
|
|
1446
1446
|
}
|
|
1447
1447
|
function createDefaultAgentReflectionDeps(tenantId) {
|
|
1448
|
-
(0,
|
|
1448
|
+
(0, import_core75.ensureBuiltinAgentsForTenant)(tenantId);
|
|
1449
1449
|
return {
|
|
1450
|
-
ensure: (t2) =>
|
|
1450
|
+
ensure: (t2) => import_core75.agentLatticeManager.initializeStoredAssistantsForTenant(t2),
|
|
1451
1451
|
getAgentConfig: (t2, assistantId) => {
|
|
1452
|
-
const config =
|
|
1452
|
+
const config = import_core75.agentLatticeManager.getAgentConfigWithTenant(t2, assistantId);
|
|
1453
1453
|
if (!config) return void 0;
|
|
1454
1454
|
return {
|
|
1455
1455
|
middleware: extractMiddleware(config),
|
|
@@ -1457,16 +1457,16 @@ function createDefaultAgentReflectionDeps(tenantId) {
|
|
|
1457
1457
|
};
|
|
1458
1458
|
},
|
|
1459
1459
|
getAssistantMiddleware: async (t2, assistantId) => {
|
|
1460
|
-
const store2 = (0,
|
|
1460
|
+
const store2 = (0, import_core75.getStoreLattice)("default", "assistant").store;
|
|
1461
1461
|
const assistant = await store2.getAssistantById(t2, assistantId);
|
|
1462
1462
|
return extractMiddleware(assistant?.graphDefinition);
|
|
1463
1463
|
},
|
|
1464
1464
|
exposedActionsByType: (type) => {
|
|
1465
|
-
const plugin =
|
|
1465
|
+
const plugin = import_core75.PluginRegistry.get(type);
|
|
1466
1466
|
return plugin ? normalizeOpenExpose(plugin.meta.openExpose) : [];
|
|
1467
1467
|
},
|
|
1468
1468
|
resolvableAssistants: async (t2) => new Set(
|
|
1469
|
-
|
|
1469
|
+
import_core75.agentLatticeManager.getAllAgentLatticesByTenant(t2).map((lattice) => lattice.config.key)
|
|
1470
1470
|
)
|
|
1471
1471
|
};
|
|
1472
1472
|
}
|
|
@@ -1538,30 +1538,30 @@ function buildTenantExposedGrants(manifests) {
|
|
|
1538
1538
|
}
|
|
1539
1539
|
function createDefaultPluginReflectionDeps() {
|
|
1540
1540
|
return {
|
|
1541
|
-
ensure: (tenantId) =>
|
|
1541
|
+
ensure: (tenantId) => import_core75.agentLatticeManager.initializeStoredAssistantsForTenant(tenantId),
|
|
1542
1542
|
globalExposedDomains: () => {
|
|
1543
1543
|
const grants = [];
|
|
1544
|
-
for (const type of
|
|
1545
|
-
const plugin =
|
|
1544
|
+
for (const type of import_core75.PluginRegistry.list()) {
|
|
1545
|
+
const plugin = import_core75.PluginRegistry.get(type);
|
|
1546
1546
|
const items = normalizeOpenExpose(plugin?.meta.openExpose);
|
|
1547
1547
|
if (items.length > 0) grants.push({ domain: type, items });
|
|
1548
1548
|
}
|
|
1549
1549
|
return grants;
|
|
1550
1550
|
},
|
|
1551
1551
|
tenantExposedDomains: async (tenantId) => {
|
|
1552
|
-
const { manifests } = await (0,
|
|
1552
|
+
const { manifests } = await (0, import_core75.getSandboxPluginCatalog)().ensureLoaded(tenantId);
|
|
1553
1553
|
return buildTenantExposedGrants(Object.values(manifests));
|
|
1554
1554
|
},
|
|
1555
1555
|
resolvableAssistants: async (tenantId) => new Set(
|
|
1556
|
-
|
|
1556
|
+
import_core75.agentLatticeManager.getAllAgentLatticesByTenant(tenantId).map((lattice) => lattice.config.key)
|
|
1557
1557
|
)
|
|
1558
1558
|
};
|
|
1559
1559
|
}
|
|
1560
|
-
var
|
|
1560
|
+
var import_core75, AGENT_REFLECTION_CACHE_TTL_MS, cache, PLUGIN_REFLECTION_CACHE_TTL_MS, pluginCache;
|
|
1561
1561
|
var init_sandboxOpenReflection = __esm({
|
|
1562
1562
|
"src/services/open/sandboxOpenReflection.ts"() {
|
|
1563
1563
|
"use strict";
|
|
1564
|
-
|
|
1564
|
+
import_core75 = require("@axiom-lattice/core");
|
|
1565
1565
|
AGENT_REFLECTION_CACHE_TTL_MS = 6e4;
|
|
1566
1566
|
cache = /* @__PURE__ */ new Map();
|
|
1567
1567
|
PLUGIN_REFLECTION_CACHE_TTL_MS = 6e4;
|
|
@@ -1608,7 +1608,7 @@ function outcome(task) {
|
|
|
1608
1608
|
});
|
|
1609
1609
|
}
|
|
1610
1610
|
async function backfillTopCallerGroup(tasks, top, deps) {
|
|
1611
|
-
const registry = deps.registry ??
|
|
1611
|
+
const registry = deps.registry ?? import_core78.taskRunRegistry;
|
|
1612
1612
|
const results = [];
|
|
1613
1613
|
const eligible = [];
|
|
1614
1614
|
for (const task of tasks) {
|
|
@@ -1662,11 +1662,11 @@ async function recoverTask(task, deps) {
|
|
|
1662
1662
|
if (task.status !== "in_progress") {
|
|
1663
1663
|
return { kind: "skipped", reason: "not_in_progress" };
|
|
1664
1664
|
}
|
|
1665
|
-
const registry = deps.registry ??
|
|
1665
|
+
const registry = deps.registry ?? import_core78.taskRunRegistry;
|
|
1666
1666
|
if (registry.isLive(task.id) || deps.isTaskLive && await deps.isTaskLive(task)) {
|
|
1667
1667
|
return { kind: "skipped", reason: "live" };
|
|
1668
1668
|
}
|
|
1669
|
-
const { convergedTasks } = await (0,
|
|
1669
|
+
const { convergedTasks } = await (0, import_core78.reconcileStaleTaskRuns)({
|
|
1670
1670
|
tasks: [task],
|
|
1671
1671
|
actor: "system:on-demand-recovery",
|
|
1672
1672
|
lifecycle: deps.lifecycle,
|
|
@@ -1762,30 +1762,30 @@ async function runOrphanRecovery(deps) {
|
|
|
1762
1762
|
deps.log.info("Task orphan recovery complete", { recovered, skipped });
|
|
1763
1763
|
return { recovered, skipped };
|
|
1764
1764
|
}
|
|
1765
|
-
var import_messages,
|
|
1765
|
+
var import_messages, import_core78;
|
|
1766
1766
|
var init_TopCallerRecovery = __esm({
|
|
1767
1767
|
"src/services/collaboration/TopCallerRecovery.ts"() {
|
|
1768
1768
|
"use strict";
|
|
1769
1769
|
import_messages = require("@langchain/core/messages");
|
|
1770
|
-
|
|
1770
|
+
import_core78 = require("@axiom-lattice/core");
|
|
1771
1771
|
}
|
|
1772
1772
|
});
|
|
1773
1773
|
|
|
1774
1774
|
// src/services/collaboration/taskRunLiveness.ts
|
|
1775
1775
|
function createTaskRunLiveness() {
|
|
1776
1776
|
try {
|
|
1777
|
-
|
|
1777
|
+
import_core79.storeLatticeManager.getStoreLattice("default", "lease");
|
|
1778
1778
|
} catch {
|
|
1779
1779
|
return void 0;
|
|
1780
1780
|
}
|
|
1781
|
-
return (task) => (0,
|
|
1781
|
+
return (task) => (0, import_core80.isTaskRunLeaseHeld)(task);
|
|
1782
1782
|
}
|
|
1783
|
-
var
|
|
1783
|
+
var import_core79, import_core80;
|
|
1784
1784
|
var init_taskRunLiveness = __esm({
|
|
1785
1785
|
"src/services/collaboration/taskRunLiveness.ts"() {
|
|
1786
1786
|
"use strict";
|
|
1787
|
-
import_core78 = require("@axiom-lattice/core");
|
|
1788
1787
|
import_core79 = require("@axiom-lattice/core");
|
|
1788
|
+
import_core80 = require("@axiom-lattice/core");
|
|
1789
1789
|
}
|
|
1790
1790
|
});
|
|
1791
1791
|
|
|
@@ -1795,7 +1795,7 @@ __export(OrphanRecoveryRuntime_exports, {
|
|
|
1795
1795
|
createOrphanRecoveryRuntime: () => createOrphanRecoveryRuntime
|
|
1796
1796
|
});
|
|
1797
1797
|
function createOrphanRecoveryRuntime(deps) {
|
|
1798
|
-
const lifecycle = deps.lifecycle ?? (0,
|
|
1798
|
+
const lifecycle = deps.lifecycle ?? (0, import_core81.createTaskLifecycleService)({
|
|
1799
1799
|
taskStore: deps.taskStore,
|
|
1800
1800
|
workItemStore: deps.workItemStore
|
|
1801
1801
|
});
|
|
@@ -1803,7 +1803,7 @@ function createOrphanRecoveryRuntime(deps) {
|
|
|
1803
1803
|
async recoverAll() {
|
|
1804
1804
|
const isTaskLive = deps.isTaskLive ?? createTaskRunLiveness();
|
|
1805
1805
|
return runOrphanRecovery({
|
|
1806
|
-
reconcile: () => (0,
|
|
1806
|
+
reconcile: () => (0, import_core81.reconcileAllTenantTaskRuns)({
|
|
1807
1807
|
actor: "system:orphan-recovery",
|
|
1808
1808
|
tenantStore: {
|
|
1809
1809
|
listTenants: async () => (await deps.tenantStore.getAllTenants()).map((tenant2) => ({ id: tenant2.id }))
|
|
@@ -1829,7 +1829,7 @@ function createOrphanRecoveryRuntime(deps) {
|
|
|
1829
1829
|
const isTaskLive = deps.isTaskLive ?? createTaskRunLiveness();
|
|
1830
1830
|
return recoverTask(task, {
|
|
1831
1831
|
lifecycle,
|
|
1832
|
-
registry:
|
|
1832
|
+
registry: import_core81.taskRunRegistry,
|
|
1833
1833
|
orphans,
|
|
1834
1834
|
callerFor: deps.callerFor,
|
|
1835
1835
|
resume: deps.resume,
|
|
@@ -1838,11 +1838,11 @@ function createOrphanRecoveryRuntime(deps) {
|
|
|
1838
1838
|
}
|
|
1839
1839
|
};
|
|
1840
1840
|
}
|
|
1841
|
-
var
|
|
1841
|
+
var import_core81;
|
|
1842
1842
|
var init_OrphanRecoveryRuntime = __esm({
|
|
1843
1843
|
"src/services/collaboration/OrphanRecoveryRuntime.ts"() {
|
|
1844
1844
|
"use strict";
|
|
1845
|
-
|
|
1845
|
+
import_core81 = require("@axiom-lattice/core");
|
|
1846
1846
|
init_TopCallerRecovery();
|
|
1847
1847
|
init_projectTaskScope();
|
|
1848
1848
|
init_taskRunLiveness();
|
|
@@ -1858,12 +1858,12 @@ function createRecoveryCallerDeps() {
|
|
|
1858
1858
|
return {
|
|
1859
1859
|
callerFor: async (top, tenantId) => {
|
|
1860
1860
|
if (!top.assistantId) return void 0;
|
|
1861
|
-
const load =
|
|
1861
|
+
const load = import_core82.getAgentClientAsync ?? import_core82.getAgentClient;
|
|
1862
1862
|
const client = await load(tenantId, top.assistantId);
|
|
1863
1863
|
const config = { configurable: { thread_id: top.threadId, runConfig: { tenantId, assistant_id: top.assistantId } } };
|
|
1864
1864
|
let agent;
|
|
1865
1865
|
try {
|
|
1866
|
-
agent =
|
|
1866
|
+
agent = import_core82.agentInstanceManager.getAgent({ assistant_id: top.assistantId, thread_id: top.threadId, tenant_id: tenantId });
|
|
1867
1867
|
} catch {
|
|
1868
1868
|
}
|
|
1869
1869
|
return agent ? { client, config, agent } : { client, config };
|
|
@@ -1880,11 +1880,11 @@ function createRecoveryCallerDeps() {
|
|
|
1880
1880
|
}
|
|
1881
1881
|
};
|
|
1882
1882
|
}
|
|
1883
|
-
var
|
|
1883
|
+
var import_core82;
|
|
1884
1884
|
var init_RecoveryCallerDeps = __esm({
|
|
1885
1885
|
"src/services/collaboration/RecoveryCallerDeps.ts"() {
|
|
1886
1886
|
"use strict";
|
|
1887
|
-
|
|
1887
|
+
import_core82 = require("@axiom-lattice/core");
|
|
1888
1888
|
}
|
|
1889
1889
|
});
|
|
1890
1890
|
|
|
@@ -1955,18 +1955,18 @@ function extractText(msg) {
|
|
|
1955
1955
|
}
|
|
1956
1956
|
return null;
|
|
1957
1957
|
}
|
|
1958
|
-
var
|
|
1958
|
+
var import_zod20, logger7, wechatConfigSchema, MAX_RECONNECT_DELAY_MS, BASE_RECONNECT_DELAY_MS, HEARTBEAT_INTERVAL_MS, MSG_TYPE_USER, MSG_ITEM_TEXT, activeConnections3, seenClientIds, wechatChannelAdapter;
|
|
1959
1959
|
var init_WechatChannelAdapter = __esm({
|
|
1960
1960
|
"src/channels/wechat/WechatChannelAdapter.ts"() {
|
|
1961
1961
|
"use strict";
|
|
1962
|
-
|
|
1962
|
+
import_zod20 = require("zod");
|
|
1963
1963
|
init_wechat_client();
|
|
1964
1964
|
init_context_store();
|
|
1965
1965
|
init_Logger();
|
|
1966
1966
|
logger7 = new Logger({ serviceName: "lattice/gateway/wechat" });
|
|
1967
|
-
wechatConfigSchema =
|
|
1968
|
-
botToken:
|
|
1969
|
-
uin:
|
|
1967
|
+
wechatConfigSchema = import_zod20.z.object({
|
|
1968
|
+
botToken: import_zod20.z.string(),
|
|
1969
|
+
uin: import_zod20.z.string().optional()
|
|
1970
1970
|
});
|
|
1971
1971
|
MAX_RECONNECT_DELAY_MS = 3e4;
|
|
1972
1972
|
BASE_RECONNECT_DELAY_MS = 1e3;
|
|
@@ -2303,13 +2303,13 @@ function isA2ATaskSnapshot(value) {
|
|
|
2303
2303
|
function snapshotSequence(value) {
|
|
2304
2304
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
2305
2305
|
}
|
|
2306
|
-
var import_node_crypto31, import_node_util,
|
|
2306
|
+
var import_node_crypto31, import_node_util, import_core83, TASK_STATUS_TO_A2A_STATE, TITLE_MAX_LENGTH, A2ATaskScopeConflictError, A2ATaskStoreAdapter;
|
|
2307
2307
|
var init_A2ATaskStoreAdapter = __esm({
|
|
2308
2308
|
"src/services/a2a/A2ATaskStoreAdapter.ts"() {
|
|
2309
2309
|
"use strict";
|
|
2310
2310
|
import_node_crypto31 = require("crypto");
|
|
2311
2311
|
import_node_util = require("util");
|
|
2312
|
-
|
|
2312
|
+
import_core83 = require("@axiom-lattice/core");
|
|
2313
2313
|
TASK_STATUS_TO_A2A_STATE = {
|
|
2314
2314
|
pending: "submitted",
|
|
2315
2315
|
in_progress: "working",
|
|
@@ -2335,7 +2335,7 @@ var init_A2ATaskStoreAdapter = __esm({
|
|
|
2335
2335
|
this.workItemStore = options.workItemStore;
|
|
2336
2336
|
this.lifecycle = options.lifecycle;
|
|
2337
2337
|
this.scope = options.scope;
|
|
2338
|
-
this.runBridge = (0,
|
|
2338
|
+
this.runBridge = (0, import_core83.createTaskRunBridge)({
|
|
2339
2339
|
lifecycle: this.lifecycle,
|
|
2340
2340
|
taskStore: this.taskStore,
|
|
2341
2341
|
workItemStore: this.workItemStore
|
|
@@ -2686,12 +2686,12 @@ function assistantHasGovernedTask(assistant) {
|
|
|
2686
2686
|
const allowedTools = taskMiddleware?.allowedTools;
|
|
2687
2687
|
return !!taskMiddleware && (allowedTools === void 0 || Array.isArray(allowedTools) && (allowedTools.length === 0 || allowedTools.includes("manage_task")));
|
|
2688
2688
|
}
|
|
2689
|
-
var import_uuid11,
|
|
2689
|
+
var import_uuid11, import_core84, import_protocols35, _AxiomAgentExecutor, AxiomAgentExecutor;
|
|
2690
2690
|
var init_AxiomAgentExecutor = __esm({
|
|
2691
2691
|
"src/services/a2a/AxiomAgentExecutor.ts"() {
|
|
2692
2692
|
"use strict";
|
|
2693
2693
|
import_uuid11 = require("uuid");
|
|
2694
|
-
|
|
2694
|
+
import_core84 = require("@axiom-lattice/core");
|
|
2695
2695
|
import_protocols35 = require("@axiom-lattice/protocols");
|
|
2696
2696
|
init_a2aFileRefs();
|
|
2697
2697
|
init_task_file_refs();
|
|
@@ -2788,7 +2788,7 @@ var init_AxiomAgentExecutor = __esm({
|
|
|
2788
2788
|
await this.taskStore.save(initialTask);
|
|
2789
2789
|
bus.publish(initialTask);
|
|
2790
2790
|
try {
|
|
2791
|
-
const agent =
|
|
2791
|
+
const agent = import_core84.agentInstanceManager.getAgent(this.agentParams(threadId));
|
|
2792
2792
|
const requestText = inputFiles.length > 0 ? `${text}
|
|
2793
2793
|
|
|
2794
2794
|
${formatFileRefsSection(inputFiles)}` : text;
|
|
@@ -2976,7 +2976,7 @@ ${formatFileRefsSection(inputFiles)}` : text;
|
|
|
2976
2976
|
const threadId = task ? asString2(task.metadata?.threadId) : void 0;
|
|
2977
2977
|
if (threadId) {
|
|
2978
2978
|
try {
|
|
2979
|
-
const agent =
|
|
2979
|
+
const agent = import_core84.agentInstanceManager.getAgent(this.agentParams(threadId));
|
|
2980
2980
|
await agent.abort();
|
|
2981
2981
|
} catch (err) {
|
|
2982
2982
|
console.warn({
|
|
@@ -3350,10 +3350,10 @@ function isAsyncGenerator(value) {
|
|
|
3350
3350
|
}
|
|
3351
3351
|
function registerA2AStandardRoutes(app2, deps) {
|
|
3352
3352
|
const authService = deps.authService;
|
|
3353
|
-
const resolveTasks = deps.getTaskStoreLattice ?? (() => (0,
|
|
3354
|
-
const resolveTaskWorkItems = deps.getTaskWorkItemStore ?? (() => (0,
|
|
3355
|
-
const getAssistantStore2 = deps.getAssistantStore ?? (() => (0,
|
|
3356
|
-
const getProjectStore2 = deps.getProjectStore ?? (() => (0,
|
|
3353
|
+
const resolveTasks = deps.getTaskStoreLattice ?? (() => (0, import_core85.getStoreLattice)("default", "task").store);
|
|
3354
|
+
const resolveTaskWorkItems = deps.getTaskWorkItemStore ?? (() => (0, import_core85.getStoreLattice)("default", "taskWorkItem").store);
|
|
3355
|
+
const getAssistantStore2 = deps.getAssistantStore ?? (() => (0, import_core85.getStoreLattice)("default", "assistant").store);
|
|
3356
|
+
const getProjectStore2 = deps.getProjectStore ?? (() => (0, import_core85.getStoreLattice)("default", "project").store);
|
|
3357
3357
|
const runtimeRegistry = deps.runtimeRegistry ?? new A2ARuntimeRegistry();
|
|
3358
3358
|
app2.addHook("onClose", async () => {
|
|
3359
3359
|
runtimeRegistry.close();
|
|
@@ -3436,7 +3436,7 @@ function registerA2AStandardRoutes(app2, deps) {
|
|
|
3436
3436
|
const taskStore = assistantHasGovernedTask(assistant) ? new A2ATaskStoreAdapter({
|
|
3437
3437
|
taskStore: internalTasks,
|
|
3438
3438
|
workItemStore: workItems,
|
|
3439
|
-
lifecycle: (0,
|
|
3439
|
+
lifecycle: (0, import_core85.createTaskLifecycleService)({
|
|
3440
3440
|
taskStore: internalTasks,
|
|
3441
3441
|
workItemStore: workItems
|
|
3442
3442
|
}),
|
|
@@ -3555,7 +3555,7 @@ data: ${JSON.stringify(errorResponse)}
|
|
|
3555
3555
|
const taskStore = assistantHasGovernedTask(assistant) ? new A2ATaskStoreAdapter({
|
|
3556
3556
|
taskStore: internalTasks,
|
|
3557
3557
|
workItemStore: workItems,
|
|
3558
|
-
lifecycle: (0,
|
|
3558
|
+
lifecycle: (0, import_core85.createTaskLifecycleService)({
|
|
3559
3559
|
taskStore: internalTasks,
|
|
3560
3560
|
workItemStore: workItems
|
|
3561
3561
|
}),
|
|
@@ -3610,13 +3610,13 @@ data: ${JSON.stringify(data)}
|
|
|
3610
3610
|
}
|
|
3611
3611
|
);
|
|
3612
3612
|
}
|
|
3613
|
-
var import_uuid12, import_server2,
|
|
3613
|
+
var import_uuid12, import_server2, import_core85, SSE_HEADERS;
|
|
3614
3614
|
var init_a2a_standard = __esm({
|
|
3615
3615
|
"src/routes/a2a-standard.ts"() {
|
|
3616
3616
|
"use strict";
|
|
3617
3617
|
import_uuid12 = require("uuid");
|
|
3618
3618
|
import_server2 = require("@a2a-js/sdk/server");
|
|
3619
|
-
|
|
3619
|
+
import_core85 = require("@axiom-lattice/core");
|
|
3620
3620
|
init_A2AAuthService();
|
|
3621
3621
|
init_A2AAgentCardBuilder();
|
|
3622
3622
|
init_A2ATaskStoreAdapter();
|
|
@@ -3829,11 +3829,11 @@ function grantCovers(grants, domain, action) {
|
|
|
3829
3829
|
(g) => g.domain === domain && (!g.items || g.items.length === 0 || g.items.includes(action))
|
|
3830
3830
|
);
|
|
3831
3831
|
}
|
|
3832
|
-
var
|
|
3832
|
+
var import_zod21, GrantDeniedError, ValidationError, ActionNotFoundError, OpenLattice, openLattice;
|
|
3833
3833
|
var init_openLattice = __esm({
|
|
3834
3834
|
"src/services/open/openLattice.ts"() {
|
|
3835
3835
|
"use strict";
|
|
3836
|
-
|
|
3836
|
+
import_zod21 = require("zod");
|
|
3837
3837
|
GrantDeniedError = class extends Error {
|
|
3838
3838
|
constructor(toolName) {
|
|
3839
3839
|
super(`GRANT_DENIED: no grant covers ${toolName}`);
|
|
@@ -3973,7 +3973,7 @@ var init_openLattice = __esm({
|
|
|
3973
3973
|
throw new GrantDeniedError(toolName);
|
|
3974
3974
|
}
|
|
3975
3975
|
const resolvedSchema = resolved.action.schema;
|
|
3976
|
-
const parsed = "safeParse" in resolvedSchema ? resolvedSchema.safeParse(args) :
|
|
3976
|
+
const parsed = "safeParse" in resolvedSchema ? resolvedSchema.safeParse(args) : import_zod21.z.object(resolvedSchema).safeParse(args);
|
|
3977
3977
|
if (!parsed.success) {
|
|
3978
3978
|
throw new ValidationError(parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; "));
|
|
3979
3979
|
}
|
|
@@ -4106,7 +4106,7 @@ var init_openMcpServer = __esm({
|
|
|
4106
4106
|
|
|
4107
4107
|
// src/services/open/pluginExposeAdapter.ts
|
|
4108
4108
|
function schemaOf(tool) {
|
|
4109
|
-
return tool.lc_kwargs?.schema ?? tool.schema ??
|
|
4109
|
+
return tool.lc_kwargs?.schema ?? tool.schema ?? import_zod22.z.object({}).passthrough();
|
|
4110
4110
|
}
|
|
4111
4111
|
function createPluginProvider(domain, tools, options = {}) {
|
|
4112
4112
|
function toAction(info) {
|
|
@@ -4154,11 +4154,11 @@ function createPluginProvider(domain, tools, options = {}) {
|
|
|
4154
4154
|
}
|
|
4155
4155
|
};
|
|
4156
4156
|
}
|
|
4157
|
-
var
|
|
4157
|
+
var import_zod22;
|
|
4158
4158
|
var init_pluginExposeAdapter = __esm({
|
|
4159
4159
|
"src/services/open/pluginExposeAdapter.ts"() {
|
|
4160
4160
|
"use strict";
|
|
4161
|
-
|
|
4161
|
+
import_zod22 = require("zod");
|
|
4162
4162
|
}
|
|
4163
4163
|
});
|
|
4164
4164
|
|
|
@@ -4183,8 +4183,8 @@ function exposedDeclarations(plugin) {
|
|
|
4183
4183
|
return (plugin.meta.tools ?? []).filter((t2) => t2.expose);
|
|
4184
4184
|
}
|
|
4185
4185
|
async function registerExposedPluginTools() {
|
|
4186
|
-
for (const key of
|
|
4187
|
-
const plugin =
|
|
4186
|
+
for (const key of import_core86.PluginRegistry.list()) {
|
|
4187
|
+
const plugin = import_core86.PluginRegistry.get(key);
|
|
4188
4188
|
if (!plugin?.middleware) continue;
|
|
4189
4189
|
const exposed = exposedDeclarations(plugin);
|
|
4190
4190
|
if (exposed.length === 0) continue;
|
|
@@ -4219,8 +4219,8 @@ async function registerExposedPluginTools() {
|
|
|
4219
4219
|
}
|
|
4220
4220
|
function collectExposedPluginUiResources(grants) {
|
|
4221
4221
|
const resources = /* @__PURE__ */ new Map();
|
|
4222
|
-
for (const type of
|
|
4223
|
-
const plugin =
|
|
4222
|
+
for (const type of import_core86.PluginRegistry.list()) {
|
|
4223
|
+
const plugin = import_core86.PluginRegistry.get(type);
|
|
4224
4224
|
if (!plugin?.middleware) continue;
|
|
4225
4225
|
const exposedNames = new Set(exposedDeclarations(plugin).map((d) => d.name));
|
|
4226
4226
|
if (exposedNames.size === 0) continue;
|
|
@@ -4244,11 +4244,11 @@ function collectExposedPluginUiResources(grants) {
|
|
|
4244
4244
|
}
|
|
4245
4245
|
return resources;
|
|
4246
4246
|
}
|
|
4247
|
-
var
|
|
4247
|
+
var import_core86;
|
|
4248
4248
|
var init_registerExposedPlugins = __esm({
|
|
4249
4249
|
"src/services/open/registerExposedPlugins.ts"() {
|
|
4250
4250
|
"use strict";
|
|
4251
|
-
|
|
4251
|
+
import_core86 = require("@axiom-lattice/core");
|
|
4252
4252
|
init_openLattice();
|
|
4253
4253
|
init_pluginExposeAdapter();
|
|
4254
4254
|
}
|
|
@@ -4263,14 +4263,14 @@ function toText(result) {
|
|
|
4263
4263
|
}
|
|
4264
4264
|
function defaultCatalog() {
|
|
4265
4265
|
return {
|
|
4266
|
-
getValidatedManifest: (tenantId, type) => (0,
|
|
4267
|
-
getExecutor: () => (0,
|
|
4268
|
-
readPluginFile: (tenantId, type, relPath) => (0,
|
|
4266
|
+
getValidatedManifest: (tenantId, type) => (0, import_core87.getSandboxPluginCatalog)().getValidatedManifest(tenantId, type),
|
|
4267
|
+
getExecutor: () => (0, import_core87.getSandboxPluginCatalog)().getExecutor(),
|
|
4268
|
+
readPluginFile: (tenantId, type, relPath) => (0, import_core87.getSandboxPluginCatalog)().readPluginFile(tenantId, type, relPath)
|
|
4269
4269
|
};
|
|
4270
4270
|
}
|
|
4271
4271
|
async function defaultResolveConnections(pluginType, ctx) {
|
|
4272
4272
|
try {
|
|
4273
|
-
return await (0,
|
|
4273
|
+
return await (0, import_core87.resolveSandboxPluginConnections)(
|
|
4274
4274
|
pluginType,
|
|
4275
4275
|
{ connectAll: true },
|
|
4276
4276
|
{
|
|
@@ -4299,7 +4299,7 @@ function mergeOpenCatalog(globalCatalog, tenantTools) {
|
|
|
4299
4299
|
async function buildTenantOpenPlugins(tenantId, grants, deps = {}) {
|
|
4300
4300
|
const catalog = deps.catalog ?? defaultCatalog();
|
|
4301
4301
|
const listPlugins = deps.listPlugins ?? (async (tenant2) => {
|
|
4302
|
-
const snapshot = await (0,
|
|
4302
|
+
const snapshot = await (0, import_core87.getSandboxPluginCatalog)().ensureLoaded(tenant2);
|
|
4303
4303
|
return { plugins: snapshot.plugins, diagnostics: snapshot.diagnostics };
|
|
4304
4304
|
});
|
|
4305
4305
|
const resolveConnections = deps.resolveConnections ?? defaultResolveConnections;
|
|
@@ -4341,7 +4341,7 @@ async function buildTenantOpenPlugins(tenantId, grants, deps = {}) {
|
|
|
4341
4341
|
domain,
|
|
4342
4342
|
action: tool.name,
|
|
4343
4343
|
description: tool.description,
|
|
4344
|
-
schema: (0,
|
|
4344
|
+
schema: (0, import_core87.jsonSchemaToZod)(tool.schema),
|
|
4345
4345
|
annotations: {
|
|
4346
4346
|
readOnlyHint: tool.readOnly ?? false,
|
|
4347
4347
|
destructiveHint: tool.destructive ?? false
|
|
@@ -4392,11 +4392,11 @@ async function buildTenantOpenPlugins(tenantId, grants, deps = {}) {
|
|
|
4392
4392
|
}
|
|
4393
4393
|
};
|
|
4394
4394
|
}
|
|
4395
|
-
var
|
|
4395
|
+
var import_core87;
|
|
4396
4396
|
var init_tenantOpenPlugins = __esm({
|
|
4397
4397
|
"src/services/open/tenantOpenPlugins.ts"() {
|
|
4398
4398
|
"use strict";
|
|
4399
|
-
|
|
4399
|
+
import_core87 = require("@axiom-lattice/core");
|
|
4400
4400
|
init_openLattice();
|
|
4401
4401
|
init_pluginToolExecution();
|
|
4402
4402
|
}
|
|
@@ -4433,13 +4433,13 @@ function emptyTenantPlugins() {
|
|
|
4433
4433
|
}
|
|
4434
4434
|
function registerOpenRoutes(app2, deps = {}) {
|
|
4435
4435
|
const openAuth = deps.openAuth ?? new OpenCredentialService(
|
|
4436
|
-
(0,
|
|
4437
|
-
(0,
|
|
4436
|
+
(0, import_core88.getStoreLattice)("default", "a2aApiKey").store,
|
|
4437
|
+
(0, import_core88.getStoreLattice)("default", "project").store
|
|
4438
4438
|
);
|
|
4439
4439
|
const grantsSource = deps.grantsSource ?? ((ctx) => ctx.grants);
|
|
4440
4440
|
const audit = deps.audit ?? (() => {
|
|
4441
4441
|
try {
|
|
4442
|
-
const store2 = (0,
|
|
4442
|
+
const store2 = (0, import_core88.getStoreLattice)("default", "openAudit").store;
|
|
4443
4443
|
return new OpenAuditService(store2);
|
|
4444
4444
|
} catch {
|
|
4445
4445
|
return void 0;
|
|
@@ -4611,12 +4611,12 @@ function registerOpenRoutes(app2, deps = {}) {
|
|
|
4611
4611
|
}
|
|
4612
4612
|
);
|
|
4613
4613
|
}
|
|
4614
|
-
var import_types,
|
|
4614
|
+
var import_types, import_core88, RPC_ERROR;
|
|
4615
4615
|
var init_open = __esm({
|
|
4616
4616
|
"src/routes/open.ts"() {
|
|
4617
4617
|
"use strict";
|
|
4618
4618
|
import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
4619
|
-
|
|
4619
|
+
import_core88 = require("@axiom-lattice/core");
|
|
4620
4620
|
init_openCredentialService();
|
|
4621
4621
|
init_openAuditService();
|
|
4622
4622
|
init_openRateLimiter();
|
|
@@ -4649,7 +4649,7 @@ function registerOpenSessionRoutes(app2) {
|
|
|
4649
4649
|
if (typeof shareToken !== "string" || shareToken.length === 0) {
|
|
4650
4650
|
return reply.status(400).send({ error: "SHARE_TOKEN_REQUIRED" });
|
|
4651
4651
|
}
|
|
4652
|
-
const store2 = (0,
|
|
4652
|
+
const store2 = (0, import_core89.getStoreLattice)("default", "sharedResource").store;
|
|
4653
4653
|
const record = await store2.findByToken(shareToken);
|
|
4654
4654
|
if (!record || record.revoked) {
|
|
4655
4655
|
return reply.status(404).send({ error: "SHARE_NOT_FOUND" });
|
|
@@ -4674,11 +4674,11 @@ function registerOpenSessionRoutes(app2) {
|
|
|
4674
4674
|
}
|
|
4675
4675
|
);
|
|
4676
4676
|
}
|
|
4677
|
-
var
|
|
4677
|
+
var import_core89;
|
|
4678
4678
|
var init_open_session = __esm({
|
|
4679
4679
|
"src/routes/open-session.ts"() {
|
|
4680
4680
|
"use strict";
|
|
4681
|
-
|
|
4681
|
+
import_core89 = require("@axiom-lattice/core");
|
|
4682
4682
|
init_openToken();
|
|
4683
4683
|
init_previewToken();
|
|
4684
4684
|
init_openLattice();
|
|
@@ -4687,13 +4687,13 @@ var init_open_session = __esm({
|
|
|
4687
4687
|
|
|
4688
4688
|
// src/services/open/openCatalogService.ts
|
|
4689
4689
|
async function defaultListTenantPlugins(tenantId) {
|
|
4690
|
-
return (await (0,
|
|
4690
|
+
return (await (0, import_core90.getSandboxPluginCatalog)().ensureLoaded(tenantId)).plugins;
|
|
4691
4691
|
}
|
|
4692
|
-
var
|
|
4692
|
+
var import_core90, OpenCatalogService;
|
|
4693
4693
|
var init_openCatalogService = __esm({
|
|
4694
4694
|
"src/services/open/openCatalogService.ts"() {
|
|
4695
4695
|
"use strict";
|
|
4696
|
-
|
|
4696
|
+
import_core90 = require("@axiom-lattice/core");
|
|
4697
4697
|
init_openLattice();
|
|
4698
4698
|
OpenCatalogService = class {
|
|
4699
4699
|
constructor(assistantStore, lattice = openLattice, listTenantPlugins2 = defaultListTenantPlugins) {
|
|
@@ -4759,26 +4759,26 @@ var open_catalog_exports = {};
|
|
|
4759
4759
|
__export(open_catalog_exports, {
|
|
4760
4760
|
registerOpenCatalogRoutes: () => registerOpenCatalogRoutes
|
|
4761
4761
|
});
|
|
4762
|
-
function
|
|
4762
|
+
function tenantIdOf2(request) {
|
|
4763
4763
|
return request.user?.tenantId;
|
|
4764
4764
|
}
|
|
4765
4765
|
function registerOpenCatalogRoutes(app2) {
|
|
4766
4766
|
app2.get("/api/open/catalog", async (request, reply) => {
|
|
4767
|
-
const tenantId =
|
|
4767
|
+
const tenantId = tenantIdOf2(request);
|
|
4768
4768
|
if (!tenantId) {
|
|
4769
4769
|
return reply.status(401).send({ success: false, error: "Unauthorized" });
|
|
4770
4770
|
}
|
|
4771
|
-
const assistantStore = (0,
|
|
4771
|
+
const assistantStore = (0, import_core91.getStoreLattice)("default", "assistant").store;
|
|
4772
4772
|
const service2 = new OpenCatalogService(assistantStore);
|
|
4773
4773
|
const catalog = await service2.buildForTenant(tenantId);
|
|
4774
4774
|
return reply.status(200).send({ success: true, data: catalog });
|
|
4775
4775
|
});
|
|
4776
4776
|
}
|
|
4777
|
-
var
|
|
4777
|
+
var import_core91;
|
|
4778
4778
|
var init_open_catalog = __esm({
|
|
4779
4779
|
"src/routes/open-catalog.ts"() {
|
|
4780
4780
|
"use strict";
|
|
4781
|
-
|
|
4781
|
+
import_core91 = require("@axiom-lattice/core");
|
|
4782
4782
|
init_openCatalogService();
|
|
4783
4783
|
}
|
|
4784
4784
|
});
|
|
@@ -4793,11 +4793,11 @@ async function resolveContextSandbox(ctx) {
|
|
|
4793
4793
|
const sandboxName = ctx.runConfig?.sandboxName;
|
|
4794
4794
|
if (typeof sandboxName === "string" && sandboxName.length > 0) {
|
|
4795
4795
|
try {
|
|
4796
|
-
return await
|
|
4796
|
+
return await import_core92.sandboxLatticeManager.getSandbox(sandboxName);
|
|
4797
4797
|
} catch {
|
|
4798
4798
|
}
|
|
4799
4799
|
}
|
|
4800
|
-
return
|
|
4800
|
+
return import_core92.sandboxLatticeManager.getSandboxFromConfig({
|
|
4801
4801
|
assistant_id: "",
|
|
4802
4802
|
thread_id: "",
|
|
4803
4803
|
tenantId: ctx.tenantId,
|
|
@@ -4816,21 +4816,21 @@ function createOpenSandboxProvider() {
|
|
|
4816
4816
|
name: "files_read",
|
|
4817
4817
|
label: "Read files",
|
|
4818
4818
|
description: "Read a file from the project sandbox.",
|
|
4819
|
-
schema: { path:
|
|
4819
|
+
schema: { path: import_zod23.z.string().min(1) },
|
|
4820
4820
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
4821
4821
|
},
|
|
4822
4822
|
{
|
|
4823
4823
|
name: "files_list",
|
|
4824
4824
|
label: "List files",
|
|
4825
4825
|
description: "List files under a directory in the project sandbox.",
|
|
4826
|
-
schema: { path:
|
|
4826
|
+
schema: { path: import_zod23.z.string(), recursive: import_zod23.z.boolean().optional() },
|
|
4827
4827
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
4828
4828
|
},
|
|
4829
4829
|
{
|
|
4830
4830
|
name: "files_write",
|
|
4831
4831
|
label: "Write files",
|
|
4832
4832
|
description: "Write content to a file in the project sandbox.",
|
|
4833
|
-
schema: { path:
|
|
4833
|
+
schema: { path: import_zod23.z.string().min(1), content: import_zod23.z.string() },
|
|
4834
4834
|
annotations: { readOnlyHint: false, destructiveHint: true }
|
|
4835
4835
|
},
|
|
4836
4836
|
{
|
|
@@ -4838,9 +4838,9 @@ function createOpenSandboxProvider() {
|
|
|
4838
4838
|
label: "Run shell commands",
|
|
4839
4839
|
description: "Execute a shell command in the project sandbox. Returns stdout (up to 64KB) and exit code.",
|
|
4840
4840
|
schema: {
|
|
4841
|
-
command:
|
|
4842
|
-
exec_dir:
|
|
4843
|
-
timeout:
|
|
4841
|
+
command: import_zod23.z.string().min(1),
|
|
4842
|
+
exec_dir: import_zod23.z.string().optional(),
|
|
4843
|
+
timeout: import_zod23.z.number().int().min(1e3).optional()
|
|
4844
4844
|
},
|
|
4845
4845
|
annotations: { readOnlyHint: false, destructiveHint: true }
|
|
4846
4846
|
}
|
|
@@ -4895,12 +4895,12 @@ ${truncated}`
|
|
|
4895
4895
|
}
|
|
4896
4896
|
};
|
|
4897
4897
|
}
|
|
4898
|
-
var
|
|
4898
|
+
var import_zod23, import_core92, MAX_OUTPUT_BYTES;
|
|
4899
4899
|
var init_sandboxProvider = __esm({
|
|
4900
4900
|
"src/services/open/providers/sandboxProvider.ts"() {
|
|
4901
4901
|
"use strict";
|
|
4902
|
-
|
|
4903
|
-
|
|
4902
|
+
import_zod23 = require("zod");
|
|
4903
|
+
import_core92 = require("@axiom-lattice/core");
|
|
4904
4904
|
MAX_OUTPUT_BYTES = 64e3;
|
|
4905
4905
|
}
|
|
4906
4906
|
});
|
|
@@ -4922,12 +4922,12 @@ function safePath(raw) {
|
|
|
4922
4922
|
}
|
|
4923
4923
|
function registerOpenFilesRoutes(app2, deps = {}) {
|
|
4924
4924
|
const openAuth = deps.openAuth ?? new OpenCredentialService(
|
|
4925
|
-
(0,
|
|
4926
|
-
(0,
|
|
4925
|
+
(0, import_core93.getStoreLattice)("default", "a2aApiKey").store,
|
|
4926
|
+
(0, import_core93.getStoreLattice)("default", "project").store
|
|
4927
4927
|
);
|
|
4928
4928
|
const audit = deps.audit ?? (() => {
|
|
4929
4929
|
try {
|
|
4930
|
-
const store2 = (0,
|
|
4930
|
+
const store2 = (0, import_core93.getStoreLattice)("default", "openAudit").store;
|
|
4931
4931
|
return new OpenAuditService(store2);
|
|
4932
4932
|
} catch {
|
|
4933
4933
|
return void 0;
|
|
@@ -5037,11 +5037,11 @@ function registerOpenFilesRoutes(app2, deps = {}) {
|
|
|
5037
5037
|
}
|
|
5038
5038
|
});
|
|
5039
5039
|
}
|
|
5040
|
-
var
|
|
5040
|
+
var import_core93;
|
|
5041
5041
|
var init_open_files = __esm({
|
|
5042
5042
|
"src/routes/open-files.ts"() {
|
|
5043
5043
|
"use strict";
|
|
5044
|
-
|
|
5044
|
+
import_core93 = require("@axiom-lattice/core");
|
|
5045
5045
|
init_openCredentialService();
|
|
5046
5046
|
init_openLattice();
|
|
5047
5047
|
init_sandboxProvider();
|
|
@@ -5063,7 +5063,7 @@ function registerOpenAuditRoutes(app2) {
|
|
|
5063
5063
|
return reply.status(401).send({ success: false, error: "Unauthorized" });
|
|
5064
5064
|
}
|
|
5065
5065
|
const status = request.query.status === "ok" || request.query.status === "error" ? request.query.status : void 0;
|
|
5066
|
-
const store2 = (0,
|
|
5066
|
+
const store2 = (0, import_core94.getStoreLattice)("default", "openAudit").store;
|
|
5067
5067
|
const records = await store2.query({
|
|
5068
5068
|
tenantId,
|
|
5069
5069
|
credentialId: request.query.credentialId,
|
|
@@ -5078,11 +5078,11 @@ function registerOpenAuditRoutes(app2) {
|
|
|
5078
5078
|
}
|
|
5079
5079
|
);
|
|
5080
5080
|
}
|
|
5081
|
-
var
|
|
5081
|
+
var import_core94;
|
|
5082
5082
|
var init_open_audit = __esm({
|
|
5083
5083
|
"src/routes/open-audit.ts"() {
|
|
5084
5084
|
"use strict";
|
|
5085
|
-
|
|
5085
|
+
import_core94 = require("@axiom-lattice/core");
|
|
5086
5086
|
}
|
|
5087
5087
|
});
|
|
5088
5088
|
|
|
@@ -5099,7 +5099,7 @@ function registerOpenExposureRoutes(app2, deps = {}) {
|
|
|
5099
5099
|
if (!tenantId) {
|
|
5100
5100
|
return reply.status(401).send({ success: false, error: "Unauthorized" });
|
|
5101
5101
|
}
|
|
5102
|
-
const keyStore = (0,
|
|
5102
|
+
const keyStore = (0, import_core95.getStoreLattice)("default", "a2aApiKey").store;
|
|
5103
5103
|
const record = await keyStore.findById(request.params.id);
|
|
5104
5104
|
if (!record || record.tenantId !== tenantId) {
|
|
5105
5105
|
return reply.status(404).send({ success: false, error: "Key not found" });
|
|
@@ -5133,7 +5133,7 @@ function registerOpenExposureRoutes(app2, deps = {}) {
|
|
|
5133
5133
|
hasUi: Boolean(t2.ui)
|
|
5134
5134
|
}));
|
|
5135
5135
|
const agentGrant = grants.find((g) => g.domain === "agent");
|
|
5136
|
-
const assistantStore = (0,
|
|
5136
|
+
const assistantStore = (0, import_core95.getStoreLattice)("default", "assistant").store;
|
|
5137
5137
|
const agents = [];
|
|
5138
5138
|
for (const assistantId of agentGrant?.items ?? []) {
|
|
5139
5139
|
const assistant = await assistantStore.getAssistantById(
|
|
@@ -5168,11 +5168,11 @@ function registerOpenExposureRoutes(app2, deps = {}) {
|
|
|
5168
5168
|
}
|
|
5169
5169
|
);
|
|
5170
5170
|
}
|
|
5171
|
-
var
|
|
5171
|
+
var import_core95, import_protocols38;
|
|
5172
5172
|
var init_open_exposure = __esm({
|
|
5173
5173
|
"src/routes/open-exposure.ts"() {
|
|
5174
5174
|
"use strict";
|
|
5175
|
-
|
|
5175
|
+
import_core95 = require("@axiom-lattice/core");
|
|
5176
5176
|
import_protocols38 = require("@axiom-lattice/protocols");
|
|
5177
5177
|
init_openLattice();
|
|
5178
5178
|
init_tenantOpenPlugins();
|
|
@@ -5197,9 +5197,9 @@ function createKbProvider(collectionService3) {
|
|
|
5197
5197
|
label: "Search collections",
|
|
5198
5198
|
description: "Search a knowledge base collection. Returns matched entries with content, metadata and similarity score.",
|
|
5199
5199
|
schema: {
|
|
5200
|
-
collection:
|
|
5201
|
-
query:
|
|
5202
|
-
limit:
|
|
5200
|
+
collection: import_zod24.z.string().min(1),
|
|
5201
|
+
query: import_zod24.z.string().min(1),
|
|
5202
|
+
limit: import_zod24.z.number().int().min(1).max(50).optional()
|
|
5203
5203
|
},
|
|
5204
5204
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
5205
5205
|
}
|
|
@@ -5227,11 +5227,11 @@ function createKbProvider(collectionService3) {
|
|
|
5227
5227
|
}
|
|
5228
5228
|
};
|
|
5229
5229
|
}
|
|
5230
|
-
var
|
|
5230
|
+
var import_zod24;
|
|
5231
5231
|
var init_kbProvider = __esm({
|
|
5232
5232
|
"src/services/open/providers/kbProvider.ts"() {
|
|
5233
5233
|
"use strict";
|
|
5234
|
-
|
|
5234
|
+
import_zod24 = require("zod");
|
|
5235
5235
|
}
|
|
5236
5236
|
});
|
|
5237
5237
|
|
|
@@ -5269,7 +5269,7 @@ function createAgentProvider(deps = {}) {
|
|
|
5269
5269
|
toolName: `invoke_${assistantId}`,
|
|
5270
5270
|
label: name,
|
|
5271
5271
|
description: `Invoke the "${name}" agent${description ? ` \u2014 ${description}` : ""}. Returns its final reply.`,
|
|
5272
|
-
schema: { message:
|
|
5272
|
+
schema: { message: import_zod25.z.string().min(1) },
|
|
5273
5273
|
annotations: { readOnlyHint: false, destructiveHint: false }
|
|
5274
5274
|
};
|
|
5275
5275
|
})
|
|
@@ -5292,7 +5292,7 @@ function createAgentProvider(deps = {}) {
|
|
|
5292
5292
|
} catch {
|
|
5293
5293
|
}
|
|
5294
5294
|
}
|
|
5295
|
-
const agent =
|
|
5295
|
+
const agent = import_core96.agentInstanceManager.getAgent({
|
|
5296
5296
|
tenant_id: ctx.tenantId,
|
|
5297
5297
|
assistant_id: assistantId,
|
|
5298
5298
|
thread_id: threadId,
|
|
@@ -5317,12 +5317,12 @@ function createAgentProvider(deps = {}) {
|
|
|
5317
5317
|
}
|
|
5318
5318
|
};
|
|
5319
5319
|
}
|
|
5320
|
-
var
|
|
5320
|
+
var import_zod25, import_core96, import_protocols39, STOP_TYPES;
|
|
5321
5321
|
var init_agentProvider = __esm({
|
|
5322
5322
|
"src/services/open/providers/agentProvider.ts"() {
|
|
5323
5323
|
"use strict";
|
|
5324
|
-
|
|
5325
|
-
|
|
5324
|
+
import_zod25 = require("zod");
|
|
5325
|
+
import_core96 = require("@axiom-lattice/core");
|
|
5326
5326
|
import_protocols39 = require("@axiom-lattice/protocols");
|
|
5327
5327
|
STOP_TYPES = [import_protocols39.MessageChunkTypes.MESSAGE_COMPLETED];
|
|
5328
5328
|
}
|
|
@@ -5366,7 +5366,7 @@ function createSandboxOpenCredentialProvider(options) {
|
|
|
5366
5366
|
};
|
|
5367
5367
|
}
|
|
5368
5368
|
function registerGatewaySandboxOpenCredentialProvider(onError) {
|
|
5369
|
-
return (0,
|
|
5369
|
+
return (0, import_core97.registerSandboxOpenCredentialProvider)(
|
|
5370
5370
|
createSandboxOpenCredentialProvider({
|
|
5371
5371
|
gatewayUrl: process.env.PUBLIC_GATEWAY_URL?.trim() || void 0,
|
|
5372
5372
|
onError
|
|
@@ -5374,11 +5374,11 @@ function registerGatewaySandboxOpenCredentialProvider(onError) {
|
|
|
5374
5374
|
{ onError }
|
|
5375
5375
|
);
|
|
5376
5376
|
}
|
|
5377
|
-
var
|
|
5377
|
+
var import_core97, DEFAULT_SANDBOX_OPEN_GRANTS, MAX_SANDBOX_OPEN_DEPTH;
|
|
5378
5378
|
var init_sandboxOpenCredentialProvider = __esm({
|
|
5379
5379
|
"src/services/open/sandboxOpenCredentialProvider.ts"() {
|
|
5380
5380
|
"use strict";
|
|
5381
|
-
|
|
5381
|
+
import_core97 = require("@axiom-lattice/core");
|
|
5382
5382
|
init_openToken();
|
|
5383
5383
|
init_sandboxOpenReflection();
|
|
5384
5384
|
DEFAULT_SANDBOX_OPEN_GRANTS = [
|
|
@@ -5415,12 +5415,12 @@ var resources_exports = {};
|
|
|
5415
5415
|
__export(resources_exports, {
|
|
5416
5416
|
ResourceController: () => ResourceController
|
|
5417
5417
|
});
|
|
5418
|
-
var import_bcryptjs,
|
|
5418
|
+
var import_bcryptjs, import_core98, ResourceController;
|
|
5419
5419
|
var init_resources = __esm({
|
|
5420
5420
|
"src/controllers/resources.ts"() {
|
|
5421
5421
|
"use strict";
|
|
5422
5422
|
import_bcryptjs = __toESM(require("bcryptjs"));
|
|
5423
|
-
|
|
5423
|
+
import_core98 = require("@axiom-lattice/core");
|
|
5424
5424
|
init_mime();
|
|
5425
5425
|
init_http_range();
|
|
5426
5426
|
init_sandboxGrants();
|
|
@@ -5437,14 +5437,14 @@ var init_resources = __esm({
|
|
|
5437
5437
|
if (!workspaceId || !projectId) {
|
|
5438
5438
|
return reply.status(400).send({ error: "x-workspace-id and x-project-id headers required" });
|
|
5439
5439
|
}
|
|
5440
|
-
const payload = (0,
|
|
5440
|
+
const payload = (0, import_core98.createSharePayload)(
|
|
5441
5441
|
tenantId,
|
|
5442
5442
|
workspaceId,
|
|
5443
5443
|
projectId,
|
|
5444
5444
|
userId,
|
|
5445
5445
|
body
|
|
5446
5446
|
);
|
|
5447
|
-
const token = (0,
|
|
5447
|
+
const token = (0, import_core98.generateToken)();
|
|
5448
5448
|
try {
|
|
5449
5449
|
await this.deps.store.create({ ...payload, token });
|
|
5450
5450
|
this.deps.logger.info(
|
|
@@ -5581,7 +5581,7 @@ var init_resources = __esm({
|
|
|
5581
5581
|
resourcePath: subPath
|
|
5582
5582
|
}, subPath, ext, request, reply);
|
|
5583
5583
|
}
|
|
5584
|
-
const volume = (0,
|
|
5584
|
+
const volume = (0, import_core98.buildNamedVolumeName)("p", "project", tenantId, workspaceId, projectId);
|
|
5585
5585
|
return this._resolveAndServe(
|
|
5586
5586
|
volume,
|
|
5587
5587
|
subPath,
|
|
@@ -8417,13 +8417,13 @@ async function searchEntries(request, reply) {
|
|
|
8417
8417
|
|
|
8418
8418
|
// src/controllers/tools.ts
|
|
8419
8419
|
var import_core14 = require("@axiom-lattice/core");
|
|
8420
|
-
function serializeSchema(
|
|
8421
|
-
if (!
|
|
8420
|
+
function serializeSchema(schema2) {
|
|
8421
|
+
if (!schema2) {
|
|
8422
8422
|
return void 0;
|
|
8423
8423
|
}
|
|
8424
8424
|
try {
|
|
8425
|
-
if (
|
|
8426
|
-
const def =
|
|
8425
|
+
if (schema2._def) {
|
|
8426
|
+
const def = schema2._def;
|
|
8427
8427
|
if (def.typeName === "ZodObject") {
|
|
8428
8428
|
const shape = def.shape();
|
|
8429
8429
|
const properties = {};
|
|
@@ -8449,7 +8449,7 @@ function serializeSchema(schema) {
|
|
|
8449
8449
|
}
|
|
8450
8450
|
return {
|
|
8451
8451
|
type: "object",
|
|
8452
|
-
description:
|
|
8452
|
+
description: schema2.description || "Schema definition"
|
|
8453
8453
|
};
|
|
8454
8454
|
} catch (error) {
|
|
8455
8455
|
return {
|
|
@@ -17118,6 +17118,49 @@ function registerA2ABridgeRoutes(app2) {
|
|
|
17118
17118
|
|
|
17119
17119
|
// src/routes/stt.ts
|
|
17120
17120
|
var import_core46 = require("@axiom-lattice/core");
|
|
17121
|
+
|
|
17122
|
+
// src/controllers/tenant-scope.ts
|
|
17123
|
+
var TenantScopeError2 = class extends Error {
|
|
17124
|
+
/** Creates a tenant scope error. */
|
|
17125
|
+
constructor(code, statusCode, message) {
|
|
17126
|
+
super(message);
|
|
17127
|
+
this.code = code;
|
|
17128
|
+
this.statusCode = statusCode;
|
|
17129
|
+
this.name = "TenantScopeError";
|
|
17130
|
+
}
|
|
17131
|
+
};
|
|
17132
|
+
function resolveTenantScope(request, authRequired2) {
|
|
17133
|
+
const authenticated = request.user?.tenantId;
|
|
17134
|
+
const header2 = request.headers["x-tenant-id"];
|
|
17135
|
+
const requested = Array.isArray(header2) ? header2[0] : header2;
|
|
17136
|
+
if (authenticated) {
|
|
17137
|
+
if (requested && requested !== authenticated) {
|
|
17138
|
+
throw new TenantScopeError2(
|
|
17139
|
+
"TENANT_ACCESS_DENIED",
|
|
17140
|
+
403,
|
|
17141
|
+
"Tenant access denied"
|
|
17142
|
+
);
|
|
17143
|
+
}
|
|
17144
|
+
return { tenantId: authenticated, userId: request.user?.id };
|
|
17145
|
+
}
|
|
17146
|
+
if (authRequired2) {
|
|
17147
|
+
throw new TenantScopeError2(
|
|
17148
|
+
"UNAUTHENTICATED",
|
|
17149
|
+
401,
|
|
17150
|
+
"Console session required"
|
|
17151
|
+
);
|
|
17152
|
+
}
|
|
17153
|
+
return { tenantId: requested || "default" };
|
|
17154
|
+
}
|
|
17155
|
+
|
|
17156
|
+
// src/routes/stt.ts
|
|
17157
|
+
function tenantIdOf(request) {
|
|
17158
|
+
try {
|
|
17159
|
+
return resolveTenantScope(request, false).tenantId;
|
|
17160
|
+
} catch {
|
|
17161
|
+
return "default";
|
|
17162
|
+
}
|
|
17163
|
+
}
|
|
17121
17164
|
var ALLOWED_AUDIO_FORMATS = /* @__PURE__ */ new Set([
|
|
17122
17165
|
"webm",
|
|
17123
17166
|
"wav",
|
|
@@ -17171,10 +17214,11 @@ var registerSTTRoutes = (app2) => {
|
|
|
17171
17214
|
return reply.status(400).send({ error: `Unsupported audio format: ${format}` });
|
|
17172
17215
|
}
|
|
17173
17216
|
try {
|
|
17174
|
-
|
|
17175
|
-
|
|
17176
|
-
|
|
17177
|
-
|
|
17217
|
+
const client = await import_core46.sttModelLatticeManager.getSTTClientWithTenantAsync(
|
|
17218
|
+
tenantIdOf(request),
|
|
17219
|
+
modelKey2
|
|
17220
|
+
);
|
|
17221
|
+
if (!client) {
|
|
17178
17222
|
return reply.status(404).send({ error: `STT model "${modelKey2}" not found` });
|
|
17179
17223
|
}
|
|
17180
17224
|
const result = await client.transcribe(buffer, format);
|
|
@@ -21451,13 +21495,48 @@ function resolveDiscoveryTimeoutMs(raw = process.env.LATTICE_MODEL_DISCOVERY_TIM
|
|
|
21451
21495
|
return parsed;
|
|
21452
21496
|
}
|
|
21453
21497
|
function buildModelsEndpoint(baseURL) {
|
|
21498
|
+
return buildOpenAiEndpoint(baseURL, "models");
|
|
21499
|
+
}
|
|
21500
|
+
function buildOpenAiEndpoint(baseURL, path7) {
|
|
21454
21501
|
const url = new URL(baseURL);
|
|
21455
21502
|
const trimmed = url.pathname.replace(/\/+$/, "");
|
|
21456
|
-
url.pathname = trimmed
|
|
21503
|
+
url.pathname = /\/v\d+$/.test(trimmed) ? `${trimmed}/${path7}` : `${trimmed}/v1/${path7}`;
|
|
21457
21504
|
url.search = "";
|
|
21458
21505
|
url.hash = "";
|
|
21459
21506
|
return url.toString();
|
|
21460
21507
|
}
|
|
21508
|
+
function assertUpstreamOk(response) {
|
|
21509
|
+
if (response.status >= 300 && response.status < 400) {
|
|
21510
|
+
throw new ModelProviderServiceError(
|
|
21511
|
+
"UPSTREAM_REDIRECT_BLOCKED",
|
|
21512
|
+
502,
|
|
21513
|
+
"Upstream returned a redirect; configure the final URL directly"
|
|
21514
|
+
);
|
|
21515
|
+
}
|
|
21516
|
+
if (response.status === 401 || response.status === 403) {
|
|
21517
|
+
throw new ModelProviderServiceError(
|
|
21518
|
+
"UPSTREAM_AUTH_FAILED",
|
|
21519
|
+
502,
|
|
21520
|
+
"Upstream rejected the configured credentials"
|
|
21521
|
+
);
|
|
21522
|
+
}
|
|
21523
|
+
if (response.status === 429) {
|
|
21524
|
+
throw new ModelProviderServiceError(
|
|
21525
|
+
"UPSTREAM_RATE_LIMITED",
|
|
21526
|
+
502,
|
|
21527
|
+
"Upstream rate limited the request",
|
|
21528
|
+
true
|
|
21529
|
+
);
|
|
21530
|
+
}
|
|
21531
|
+
if (!response.ok) {
|
|
21532
|
+
throw new ModelProviderServiceError(
|
|
21533
|
+
"UPSTREAM_UNREACHABLE",
|
|
21534
|
+
502,
|
|
21535
|
+
"Upstream returned an error response",
|
|
21536
|
+
response.status >= 500
|
|
21537
|
+
);
|
|
21538
|
+
}
|
|
21539
|
+
}
|
|
21461
21540
|
function parseModelsPayload(payload) {
|
|
21462
21541
|
const entries = Array.isArray(payload) ? payload : typeof payload === "object" && payload !== null ? payload.data : void 0;
|
|
21463
21542
|
if (!Array.isArray(entries)) {
|
|
@@ -21528,36 +21607,60 @@ var openAiCompatibleAdapter = {
|
|
|
21528
21607
|
true
|
|
21529
21608
|
);
|
|
21530
21609
|
}
|
|
21531
|
-
|
|
21532
|
-
|
|
21533
|
-
|
|
21534
|
-
|
|
21535
|
-
|
|
21536
|
-
|
|
21537
|
-
}
|
|
21538
|
-
if (response.status === 401 || response.status === 403) {
|
|
21539
|
-
throw new ModelProviderServiceError(
|
|
21540
|
-
"UPSTREAM_AUTH_FAILED",
|
|
21541
|
-
502,
|
|
21542
|
-
"Upstream rejected the configured credentials"
|
|
21543
|
-
);
|
|
21544
|
-
}
|
|
21545
|
-
if (response.status === 429) {
|
|
21610
|
+
assertUpstreamOk(response);
|
|
21611
|
+
const body = await readBodyWithLimit(response, MAX_RESPONSE_BYTES);
|
|
21612
|
+
let payload;
|
|
21613
|
+
try {
|
|
21614
|
+
payload = JSON.parse(body);
|
|
21615
|
+
} catch {
|
|
21546
21616
|
throw new ModelProviderServiceError(
|
|
21547
|
-
"
|
|
21617
|
+
"UPSTREAM_INVALID_RESPONSE",
|
|
21548
21618
|
502,
|
|
21549
|
-
"Upstream
|
|
21550
|
-
true
|
|
21619
|
+
"Upstream response was not valid JSON"
|
|
21551
21620
|
);
|
|
21552
21621
|
}
|
|
21553
|
-
|
|
21622
|
+
return parseModelsPayload(payload);
|
|
21623
|
+
}
|
|
21624
|
+
};
|
|
21625
|
+
async function probeEmbeddingInference(input, signal) {
|
|
21626
|
+
const startedAt = Date.now();
|
|
21627
|
+
const endpoint = buildOpenAiEndpoint(input.baseURL, "embeddings");
|
|
21628
|
+
const headers = {
|
|
21629
|
+
Accept: "application/json",
|
|
21630
|
+
"Content-Type": "application/json"
|
|
21631
|
+
};
|
|
21632
|
+
if (input.apiKey) {
|
|
21633
|
+
headers.Authorization = `Bearer ${input.apiKey}`;
|
|
21634
|
+
}
|
|
21635
|
+
try {
|
|
21636
|
+
let response;
|
|
21637
|
+
try {
|
|
21638
|
+
response = await fetch(endpoint, {
|
|
21639
|
+
method: "POST",
|
|
21640
|
+
headers,
|
|
21641
|
+
// Never follow redirects: a redirected request could reach an address
|
|
21642
|
+
// that bypassed the SSRF checks.
|
|
21643
|
+
redirect: "manual",
|
|
21644
|
+
signal,
|
|
21645
|
+
body: JSON.stringify({ model: input.modelId, input: "ping" })
|
|
21646
|
+
});
|
|
21647
|
+
} catch (error) {
|
|
21648
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
21649
|
+
throw new ModelProviderServiceError(
|
|
21650
|
+
"UPSTREAM_TIMEOUT",
|
|
21651
|
+
504,
|
|
21652
|
+
"Upstream did not respond in time",
|
|
21653
|
+
true
|
|
21654
|
+
);
|
|
21655
|
+
}
|
|
21554
21656
|
throw new ModelProviderServiceError(
|
|
21555
21657
|
"UPSTREAM_UNREACHABLE",
|
|
21556
21658
|
502,
|
|
21557
|
-
"Upstream
|
|
21558
|
-
|
|
21659
|
+
"Upstream could not be reached",
|
|
21660
|
+
true
|
|
21559
21661
|
);
|
|
21560
21662
|
}
|
|
21663
|
+
assertUpstreamOk(response);
|
|
21561
21664
|
const body = await readBodyWithLimit(response, MAX_RESPONSE_BYTES);
|
|
21562
21665
|
let payload;
|
|
21563
21666
|
try {
|
|
@@ -21569,9 +21672,37 @@ var openAiCompatibleAdapter = {
|
|
|
21569
21672
|
"Upstream response was not valid JSON"
|
|
21570
21673
|
);
|
|
21571
21674
|
}
|
|
21572
|
-
return
|
|
21675
|
+
return {
|
|
21676
|
+
reachable: true,
|
|
21677
|
+
latencyMs: Date.now() - startedAt,
|
|
21678
|
+
dimensions: readEmbeddingDimensions(payload)
|
|
21679
|
+
};
|
|
21680
|
+
} catch (error) {
|
|
21681
|
+
if (error instanceof ModelProviderServiceError && isUpstreamErrorCode(error.code)) {
|
|
21682
|
+
return {
|
|
21683
|
+
reachable: false,
|
|
21684
|
+
latencyMs: Date.now() - startedAt,
|
|
21685
|
+
error: error.code
|
|
21686
|
+
};
|
|
21687
|
+
}
|
|
21688
|
+
throw error;
|
|
21573
21689
|
}
|
|
21574
|
-
}
|
|
21690
|
+
}
|
|
21691
|
+
function readEmbeddingDimensions(payload) {
|
|
21692
|
+
if (typeof payload !== "object" || payload === null) {
|
|
21693
|
+
return void 0;
|
|
21694
|
+
}
|
|
21695
|
+
const data = payload.data;
|
|
21696
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
21697
|
+
return void 0;
|
|
21698
|
+
}
|
|
21699
|
+
const first = data[0];
|
|
21700
|
+
if (typeof first !== "object" || first === null) {
|
|
21701
|
+
return void 0;
|
|
21702
|
+
}
|
|
21703
|
+
const embedding = first.embedding;
|
|
21704
|
+
return Array.isArray(embedding) ? embedding.length : void 0;
|
|
21705
|
+
}
|
|
21575
21706
|
async function readBodyWithLimit(response, maxBytes) {
|
|
21576
21707
|
if (!response.body) {
|
|
21577
21708
|
return response.text();
|
|
@@ -21673,6 +21804,9 @@ var ModelProviderService = class {
|
|
|
21673
21804
|
}
|
|
21674
21805
|
const models = snapshot.map((model) => ({
|
|
21675
21806
|
modelKey: (0, import_protocols16.toModelKey)(model.providerId, model.modelId),
|
|
21807
|
+
// What this row can do. Pickers filter on it, so it travels with every
|
|
21808
|
+
// entry rather than being re-derived by each consumer.
|
|
21809
|
+
kind: model.kind,
|
|
21676
21810
|
displayName: model.displayName,
|
|
21677
21811
|
providerId: model.providerId,
|
|
21678
21812
|
providerName: providerNames.get(model.providerId) ?? model.providerId,
|
|
@@ -21700,6 +21834,9 @@ var ModelProviderService = class {
|
|
|
21700
21834
|
// which is how the deployment's `default` alias came to be offered as
|
|
21701
21835
|
// a model literally called "default".
|
|
21702
21836
|
displayName: config.displayName || config.model || modelKey2,
|
|
21837
|
+
// Deployment-registered models are chat by construction: they are
|
|
21838
|
+
// built with `registerModelLattice`, which only mints LLM clients.
|
|
21839
|
+
kind: "chat",
|
|
21703
21840
|
providerId: "",
|
|
21704
21841
|
providerName: "registered",
|
|
21705
21842
|
source: "registered",
|
|
@@ -21753,6 +21890,8 @@ var ModelProviderService = class {
|
|
|
21753
21890
|
* left untouched.
|
|
21754
21891
|
*/
|
|
21755
21892
|
async reconcileProvider(tenantId, providerId2) {
|
|
21893
|
+
this.deps.registry.evictProviderCache?.(tenantId, providerId2);
|
|
21894
|
+
this.deps.registry.forgetTenantDefaultMiss?.(tenantId);
|
|
21756
21895
|
if (!this.shouldRegister(tenantId)) {
|
|
21757
21896
|
return;
|
|
21758
21897
|
}
|
|
@@ -21762,21 +21901,9 @@ var ModelProviderService = class {
|
|
|
21762
21901
|
}
|
|
21763
21902
|
const provider = await this.deps.providerStore.getProviderById(tenantId, providerId2);
|
|
21764
21903
|
if (!provider) {
|
|
21765
|
-
const prefix = `${providerId2}/`;
|
|
21766
|
-
for (const { modelKey: modelKey2 } of this.deps.registry.listRegistered(tenantId)) {
|
|
21767
|
-
if (modelKey2.startsWith(prefix)) {
|
|
21768
|
-
this.deps.registry.remove(tenantId, modelKey2);
|
|
21769
|
-
}
|
|
21770
|
-
}
|
|
21771
21904
|
return;
|
|
21772
21905
|
}
|
|
21773
21906
|
const models = await this.deps.providerStore.listModels(tenantId, providerId2);
|
|
21774
|
-
const current = new Set(models.map((model) => (0, import_protocols16.toModelKey)(providerId2, model.modelId)));
|
|
21775
|
-
for (const { modelKey: modelKey2 } of this.deps.registry.listRegistered(tenantId)) {
|
|
21776
|
-
if (modelKey2.startsWith(`${providerId2}/`) && !current.has(modelKey2)) {
|
|
21777
|
-
this.deps.registry.remove(tenantId, modelKey2);
|
|
21778
|
-
}
|
|
21779
|
-
}
|
|
21780
21907
|
this.syncRegistry(tenantId, provider, models);
|
|
21781
21908
|
}
|
|
21782
21909
|
/**
|
|
@@ -21875,11 +22002,9 @@ var ModelProviderService = class {
|
|
|
21875
22002
|
async remove(userId, tenantId, id3) {
|
|
21876
22003
|
await this.assertAdmin(userId, tenantId);
|
|
21877
22004
|
await this.requireProvider(tenantId, id3);
|
|
21878
|
-
const snapshot = await this.deps.providerStore.listModels(tenantId, id3);
|
|
21879
22005
|
await this.deps.providerStore.deleteProvider(tenantId, id3);
|
|
21880
|
-
|
|
21881
|
-
|
|
21882
|
-
}
|
|
22006
|
+
this.deps.registry.evictProviderCache?.(tenantId, id3);
|
|
22007
|
+
this.deps.registry.forgetTenantDefaultMiss?.(tenantId);
|
|
21883
22008
|
this.notifyChanged(tenantId, id3);
|
|
21884
22009
|
}
|
|
21885
22010
|
/**
|
|
@@ -21909,7 +22034,8 @@ var ModelProviderService = class {
|
|
|
21909
22034
|
() => controller.abort(),
|
|
21910
22035
|
resolveDiscoveryTimeoutMs()
|
|
21911
22036
|
);
|
|
21912
|
-
const previous =
|
|
22037
|
+
const previous = await this.deps.providerStore.listModels(tenantId, id3);
|
|
22038
|
+
const previousIds = new Set(previous.map((model) => model.modelId));
|
|
21913
22039
|
let discovered;
|
|
21914
22040
|
try {
|
|
21915
22041
|
discovered = await adapter.discover({
|
|
@@ -21935,7 +22061,12 @@ var ModelProviderService = class {
|
|
|
21935
22061
|
const inserted = await this.deps.providerStore.replaceProviderModels(
|
|
21936
22062
|
tenantId,
|
|
21937
22063
|
id3,
|
|
21938
|
-
discovered
|
|
22064
|
+
discovered.map((model) => ({
|
|
22065
|
+
...model,
|
|
22066
|
+
// Same rule as `setModels`: a row this provider just brought in starts
|
|
22067
|
+
// with the default config, a row already stored keeps the tenant's.
|
|
22068
|
+
extra: previousIds.has(model.id) ? void 0 : { ...import_core53.DEFAULT_MODEL_EXTRA }
|
|
22069
|
+
}))
|
|
21939
22070
|
);
|
|
21940
22071
|
await this.deps.providerStore.markProviderStatus(
|
|
21941
22072
|
tenantId,
|
|
@@ -22009,6 +22140,30 @@ var ModelProviderService = class {
|
|
|
22009
22140
|
resolveDiscoveryTimeoutMs()
|
|
22010
22141
|
);
|
|
22011
22142
|
const startedAt = Date.now();
|
|
22143
|
+
if (input.kind === "embedding") {
|
|
22144
|
+
if (!input.modelId) {
|
|
22145
|
+
throw new ModelProviderServiceError(
|
|
22146
|
+
"INVALID_INPUT",
|
|
22147
|
+
400,
|
|
22148
|
+
"An embedding probe needs a model id"
|
|
22149
|
+
);
|
|
22150
|
+
}
|
|
22151
|
+
try {
|
|
22152
|
+
const outcome2 = await probeEmbeddingInference(
|
|
22153
|
+
{ baseURL: input.baseURL, apiKey, modelId: input.modelId },
|
|
22154
|
+
controller.signal
|
|
22155
|
+
);
|
|
22156
|
+
return {
|
|
22157
|
+
reachable: outcome2.reachable,
|
|
22158
|
+
latencyMs: outcome2.latencyMs,
|
|
22159
|
+
models: [],
|
|
22160
|
+
...outcome2.dimensions === void 0 ? {} : { dimensions: outcome2.dimensions },
|
|
22161
|
+
...outcome2.error ? { error: outcome2.error } : {}
|
|
22162
|
+
};
|
|
22163
|
+
} finally {
|
|
22164
|
+
clearTimeout(timeout);
|
|
22165
|
+
}
|
|
22166
|
+
}
|
|
22012
22167
|
try {
|
|
22013
22168
|
const models = await adapter.discover({
|
|
22014
22169
|
baseURL: input.baseURL,
|
|
@@ -22073,8 +22228,13 @@ var ModelProviderService = class {
|
|
|
22073
22228
|
ownedBy: previousById.get(entry.modelId)?.ownedBy,
|
|
22074
22229
|
// An omitted `extra` means "keep what is stored" — the picker sends no
|
|
22075
22230
|
// config, and a sync must not wipe one set by hand. The store resolves
|
|
22076
|
-
// the fallback against the row's current value.
|
|
22077
|
-
|
|
22231
|
+
// the fallback against the row's current value. A model that is not
|
|
22232
|
+
// stored at all gets the default config rather than an empty one.
|
|
22233
|
+
extra: entry.extra ?? (previousById.has(entry.modelId) ? void 0 : { ...import_core53.DEFAULT_MODEL_EXTRA }),
|
|
22234
|
+
// Omitted means "keep the stored kind"; the store defaults a new row
|
|
22235
|
+
// to chat. A picker that only toggles `enabled` therefore cannot
|
|
22236
|
+
// accidentally reclassify a model.
|
|
22237
|
+
kind: entry.kind,
|
|
22078
22238
|
// Same rule: omitted leaves the flag alone, so a sync cannot quietly
|
|
22079
22239
|
// move the tenant's default.
|
|
22080
22240
|
isDefault: entry.isDefault
|
|
@@ -22097,14 +22257,17 @@ var ModelProviderService = class {
|
|
|
22097
22257
|
return this.toPublicEntry(provider, models.length);
|
|
22098
22258
|
}
|
|
22099
22259
|
/**
|
|
22100
|
-
* Give a tenant's sole model the default flag.
|
|
22260
|
+
* Give a tenant's sole **chat** model the default flag.
|
|
22261
|
+
*
|
|
22262
|
+
* A tenant with exactly one runnable chat model has an obvious default, and
|
|
22263
|
+
* saying so is what keeps the invariant the rest of the feature leans on: a
|
|
22264
|
+
* tenant either has no chat model at all — and falls back to the deployment's
|
|
22265
|
+
* default — or has a default, which cannot be deleted. Without this a tenant
|
|
22266
|
+
* could sit with one model and no default, and deleting that model would
|
|
22267
|
+
* leave nothing behind.
|
|
22101
22268
|
*
|
|
22102
|
-
*
|
|
22103
|
-
*
|
|
22104
|
-
* either has no models at all — and falls back to the deployment's default —
|
|
22105
|
-
* or has a default, which cannot be deleted. Without this a tenant could sit
|
|
22106
|
-
* with one model and no default, and deleting that model would leave nothing
|
|
22107
|
-
* behind.
|
|
22269
|
+
* Chat only: a bare `"default"` key resolves to a chat client, so an
|
|
22270
|
+
* embedding or ASR row must never be marked as one.
|
|
22108
22271
|
*
|
|
22109
22272
|
* Deliberately narrow: more than one model is the tenant's choice to make,
|
|
22110
22273
|
* and a disabled model is not a candidate for "the model this tenant runs".
|
|
@@ -22113,24 +22276,33 @@ var ModelProviderService = class {
|
|
|
22113
22276
|
*/
|
|
22114
22277
|
async ensureDefaultModel(tenantId) {
|
|
22115
22278
|
const models = await this.deps.providerStore.listModels(tenantId);
|
|
22116
|
-
|
|
22279
|
+
const chatModels = models.filter((model) => model.kind === "chat");
|
|
22280
|
+
if (chatModels.length !== 1) {
|
|
22117
22281
|
return;
|
|
22118
22282
|
}
|
|
22119
|
-
const [only] =
|
|
22283
|
+
const [only] = chatModels;
|
|
22120
22284
|
if (only.isDefault || !only.enabled) {
|
|
22121
22285
|
return;
|
|
22122
22286
|
}
|
|
22123
|
-
|
|
22124
|
-
|
|
22125
|
-
|
|
22126
|
-
|
|
22127
|
-
|
|
22128
|
-
|
|
22129
|
-
|
|
22130
|
-
|
|
22131
|
-
|
|
22287
|
+
const siblings = models.filter(
|
|
22288
|
+
(model) => model.providerId === only.providerId
|
|
22289
|
+
);
|
|
22290
|
+
await this.deps.providerStore.replaceProviderModels(
|
|
22291
|
+
tenantId,
|
|
22292
|
+
only.providerId,
|
|
22293
|
+
siblings.map((model) => ({
|
|
22294
|
+
id: model.modelId,
|
|
22295
|
+
enabled: model.enabled,
|
|
22296
|
+
stale: model.stale,
|
|
22297
|
+
extra: model.extra,
|
|
22298
|
+
kind: model.kind,
|
|
22299
|
+
isDefault: model.modelId === only.modelId
|
|
22300
|
+
}))
|
|
22301
|
+
);
|
|
22132
22302
|
}
|
|
22133
22303
|
syncRegistry(tenantId, provider, models) {
|
|
22304
|
+
this.deps.registry.evictProviderCache?.(tenantId, provider.id);
|
|
22305
|
+
this.deps.registry.forgetTenantDefaultMiss?.(tenantId);
|
|
22134
22306
|
if (!this.shouldRegister(tenantId)) {
|
|
22135
22307
|
return [];
|
|
22136
22308
|
}
|
|
@@ -22377,6 +22549,10 @@ var setModelsSchema = import_zod10.z.object({
|
|
|
22377
22549
|
// Omitted means "leave the stored config alone" — the picker sends
|
|
22378
22550
|
// only ids and states, and must not wipe a config set by hand.
|
|
22379
22551
|
extra: extraSchema.optional(),
|
|
22552
|
+
// What this model does. Omitted means "leave the stored kind
|
|
22553
|
+
// alone"; a new row defaults to chat. The kinds are independent —
|
|
22554
|
+
// each has its own runtime lattice and loader guard.
|
|
22555
|
+
kind: import_zod10.z.enum(["chat", "embedding", "asr"]).optional(),
|
|
22380
22556
|
// At most one per tenant; the service rejects a tie with a
|
|
22381
22557
|
// readable error rather than letting the unique index raise one.
|
|
22382
22558
|
// Omitted means "leave the stored flag alone", which is what a
|
|
@@ -22389,43 +22565,13 @@ var probeProviderSchema = import_zod10.z.object({
|
|
|
22389
22565
|
baseURL: import_zod10.z.string().trim().min(1).max(2048),
|
|
22390
22566
|
apiKey: import_zod10.z.string().max(1024).optional(),
|
|
22391
22567
|
providerId: import_zod10.z.string().trim().min(1).max(255).optional(),
|
|
22392
|
-
protocol: protocolSchema.optional()
|
|
22568
|
+
protocol: protocolSchema.optional(),
|
|
22569
|
+
// Only an embedding probe uses these: it names the model and asks for one
|
|
22570
|
+
// inference, because a model list cannot prove a model can embed.
|
|
22571
|
+
kind: import_zod10.z.enum(["chat", "embedding", "asr"]).optional(),
|
|
22572
|
+
modelId: import_zod10.z.string().trim().min(1).max(512).optional()
|
|
22393
22573
|
}).strict();
|
|
22394
22574
|
|
|
22395
|
-
// src/controllers/tenant-scope.ts
|
|
22396
|
-
var TenantScopeError2 = class extends Error {
|
|
22397
|
-
/** Creates a tenant scope error. */
|
|
22398
|
-
constructor(code, statusCode, message) {
|
|
22399
|
-
super(message);
|
|
22400
|
-
this.code = code;
|
|
22401
|
-
this.statusCode = statusCode;
|
|
22402
|
-
this.name = "TenantScopeError";
|
|
22403
|
-
}
|
|
22404
|
-
};
|
|
22405
|
-
function resolveTenantScope(request, authRequired2) {
|
|
22406
|
-
const authenticated = request.user?.tenantId;
|
|
22407
|
-
const header2 = request.headers["x-tenant-id"];
|
|
22408
|
-
const requested = Array.isArray(header2) ? header2[0] : header2;
|
|
22409
|
-
if (authenticated) {
|
|
22410
|
-
if (requested && requested !== authenticated) {
|
|
22411
|
-
throw new TenantScopeError2(
|
|
22412
|
-
"TENANT_ACCESS_DENIED",
|
|
22413
|
-
403,
|
|
22414
|
-
"Tenant access denied"
|
|
22415
|
-
);
|
|
22416
|
-
}
|
|
22417
|
-
return { tenantId: authenticated, userId: request.user?.id };
|
|
22418
|
-
}
|
|
22419
|
-
if (authRequired2) {
|
|
22420
|
-
throw new TenantScopeError2(
|
|
22421
|
-
"UNAUTHENTICATED",
|
|
22422
|
-
401,
|
|
22423
|
-
"Console session required"
|
|
22424
|
-
);
|
|
22425
|
-
}
|
|
22426
|
-
return { tenantId: requested || "default" };
|
|
22427
|
-
}
|
|
22428
|
-
|
|
22429
22575
|
// src/controllers/model-providers.ts
|
|
22430
22576
|
init_Logger();
|
|
22431
22577
|
var logger4 = new Logger({ serviceName: "lattice/gateway/model-providers" });
|
|
@@ -28767,7 +28913,13 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
28767
28913
|
config: lattice.client.getConfig()
|
|
28768
28914
|
}))
|
|
28769
28915
|
),
|
|
28770
|
-
forgetTenantDefaultMiss: (tenantId) => import_core58.modelLatticeManager.forgetTenantDefaultMiss(tenantId)
|
|
28916
|
+
forgetTenantDefaultMiss: (tenantId) => import_core58.modelLatticeManager.forgetTenantDefaultMiss(tenantId),
|
|
28917
|
+
evictProviderCache: (tenantId, providerId2) => {
|
|
28918
|
+
import_core58.modelLatticeManager.evictProviderCache(tenantId, providerId2);
|
|
28919
|
+
import_core58.embeddingsLatticeManager.evictProviderCache(tenantId, providerId2);
|
|
28920
|
+
import_core58.sttModelLatticeManager.evictProviderCache(tenantId, providerId2);
|
|
28921
|
+
import_core58.vectorStoreLatticeManager.clearTenantVectorStores(tenantId);
|
|
28922
|
+
}
|
|
28771
28923
|
},
|
|
28772
28924
|
onChanged: (tenantId, providerId2) => broadcastModelProviderChanged(tenantId, providerId2)
|
|
28773
28925
|
}, { authRequired: process.env.AUTH_REQUIRED === "true" });
|
|
@@ -30827,11 +30979,11 @@ function createAuditLoggerMiddleware() {
|
|
|
30827
30979
|
}
|
|
30828
30980
|
|
|
30829
30981
|
// src/index.ts
|
|
30830
|
-
var
|
|
30982
|
+
var import_core99 = require("@axiom-lattice/core");
|
|
30831
30983
|
|
|
30832
30984
|
// src/channels/wecom/WecomChannelAdapter.ts
|
|
30833
30985
|
var import_node_crypto27 = require("crypto");
|
|
30834
|
-
var
|
|
30986
|
+
var import_zod18 = require("zod");
|
|
30835
30987
|
var WecomAiBot = __toESM(require("@wecom/aibot-node-sdk"));
|
|
30836
30988
|
|
|
30837
30989
|
// src/channels/wecom/parser.ts
|
|
@@ -30856,24 +31008,288 @@ function parseWecomTextFrame(frame) {
|
|
|
30856
31008
|
};
|
|
30857
31009
|
}
|
|
30858
31010
|
|
|
31011
|
+
// src/channels/wecom/cardTool.ts
|
|
31012
|
+
var import_core71 = require("@axiom-lattice/core");
|
|
31013
|
+
var import_zod17 = require("zod");
|
|
31014
|
+
var CARD_TTL_MS = 10 * 6e4;
|
|
31015
|
+
var MAX_CARD_ENTRIES = 1e3;
|
|
31016
|
+
var cardEntries = /* @__PURE__ */ new Map();
|
|
31017
|
+
function pruneCards(now) {
|
|
31018
|
+
for (const [key, entry] of cardEntries) {
|
|
31019
|
+
if (entry.expiresAt <= now) cardEntries.delete(key);
|
|
31020
|
+
}
|
|
31021
|
+
while (cardEntries.size > MAX_CARD_ENTRIES) {
|
|
31022
|
+
const oldest = cardEntries.keys().next().value;
|
|
31023
|
+
if (oldest === void 0) break;
|
|
31024
|
+
cardEntries.delete(oldest);
|
|
31025
|
+
}
|
|
31026
|
+
}
|
|
31027
|
+
function putWecomCard(key, card) {
|
|
31028
|
+
const now = Date.now();
|
|
31029
|
+
pruneCards(now);
|
|
31030
|
+
if (cardEntries.get(key)?.closed) return false;
|
|
31031
|
+
cardEntries.delete(key);
|
|
31032
|
+
cardEntries.set(key, { card, expiresAt: now + CARD_TTL_MS, closed: false });
|
|
31033
|
+
return true;
|
|
31034
|
+
}
|
|
31035
|
+
function takeWecomCard(key) {
|
|
31036
|
+
const now = Date.now();
|
|
31037
|
+
pruneCards(now);
|
|
31038
|
+
const entry = cardEntries.get(key);
|
|
31039
|
+
if (!entry) return void 0;
|
|
31040
|
+
cardEntries.delete(key);
|
|
31041
|
+
cardEntries.set(key, { expiresAt: now + CARD_TTL_MS, closed: true });
|
|
31042
|
+
return entry.card;
|
|
31043
|
+
}
|
|
31044
|
+
function discardWecomCard(key) {
|
|
31045
|
+
const now = Date.now();
|
|
31046
|
+
pruneCards(now);
|
|
31047
|
+
const entry = cardEntries.get(key);
|
|
31048
|
+
if (entry) entry.card = void 0;
|
|
31049
|
+
cardEntries.delete(key);
|
|
31050
|
+
cardEntries.set(key, { expiresAt: now + CARD_TTL_MS, closed: true });
|
|
31051
|
+
}
|
|
31052
|
+
var CARD_TYPES = [
|
|
31053
|
+
"text_notice",
|
|
31054
|
+
"news_notice",
|
|
31055
|
+
"button_interaction",
|
|
31056
|
+
"vote_interaction",
|
|
31057
|
+
"multiple_interaction"
|
|
31058
|
+
];
|
|
31059
|
+
var optionSchema = import_zod17.z.object({
|
|
31060
|
+
id: import_zod17.z.string().describe("\u9009\u9879 ID"),
|
|
31061
|
+
text: import_zod17.z.string().describe("\u9009\u9879\u6587\u6848"),
|
|
31062
|
+
is_checked: import_zod17.z.boolean().optional().describe("\u662F\u5426\u9ED8\u8BA4\u9009\u4E2D")
|
|
31063
|
+
});
|
|
31064
|
+
var schema = import_zod17.z.object({
|
|
31065
|
+
card_type: import_zod17.z.enum(CARD_TYPES).default("text_notice").describe(
|
|
31066
|
+
"\u5361\u7247\u7C7B\u578B\uFF1Atext_notice(\u6587\u672C\u901A\u77E5)/news_notice(\u56FE\u6587)/button_interaction(\u6309\u94AE)/vote_interaction(\u6295\u7968)/multiple_interaction(\u591A\u9009)"
|
|
31067
|
+
),
|
|
31068
|
+
title: import_zod17.z.string().min(1).max(26).describe("\u4E00\u7EA7\u6807\u9898\uFF0C\u4E0D\u8D85\u8FC7 26 \u5B57"),
|
|
31069
|
+
desc: import_zod17.z.string().max(30).optional().describe("\u6807\u9898\u8F85\u52A9\u4FE1\u606F\uFF0C\u4E0D\u8D85\u8FC7 30 \u5B57"),
|
|
31070
|
+
source_desc: import_zod17.z.string().max(13).optional().describe("\u5361\u7247\u5DE6\u4E0A\u89D2\u6765\u6E90\u6587\u6848\uFF0C\u4E0D\u8D85\u8FC7 13 \u5B57"),
|
|
31071
|
+
source_color: import_zod17.z.number().int().min(0).max(3).optional().describe("\u6765\u6E90\u6587\u5B57\u989C\u8272\uFF1A0 \u7070(\u9ED8\u8BA4)/1 \u9ED1/2 \u7EA2/3 \u7EFF"),
|
|
31072
|
+
emphasis_title: import_zod17.z.string().max(10).optional().describe("\u5173\u952E\u6570\u5B57\uFF0C\u4E0D\u8D85\u8FC7 10 \u5B57"),
|
|
31073
|
+
emphasis_desc: import_zod17.z.string().max(15).optional().describe("\u5173\u952E\u6570\u5B57\u8BF4\u660E\uFF0C\u4E0D\u8D85\u8FC7 15 \u5B57"),
|
|
31074
|
+
subtitle: import_zod17.z.string().max(112).optional().describe("\u4E8C\u7EA7\u666E\u901A\u6587\u672C\uFF0C\u4E0D\u8D85\u8FC7 112 \u5B57"),
|
|
31075
|
+
quote_text: import_zod17.z.string().optional().describe("\u5F15\u7528\u6837\u5F0F\u6587\u672C\uFF08\u4E0E\u5173\u952E\u6570\u5B57\u4E8C\u9009\u4E00\uFF09"),
|
|
31076
|
+
items: import_zod17.z.array(import_zod17.z.object({
|
|
31077
|
+
key: import_zod17.z.string().max(5).describe("\u4E8C\u7EA7\u6807\u9898\uFF0C\u4E0D\u8D85\u8FC7 5 \u5B57"),
|
|
31078
|
+
value: import_zod17.z.string().max(26).describe("\u4E8C\u7EA7\u6587\u672C\uFF0C\u4E0D\u8D85\u8FC7 26 \u5B57"),
|
|
31079
|
+
url: import_zod17.z.string().optional().describe("\u70B9\u51FB\u8DF3\u8F6C\u94FE\u63A5\uFF08\u53EF\u9009\uFF09")
|
|
31080
|
+
})).max(6).optional().describe("\u952E\u503C\u660E\u7EC6\u5217\u8868\uFF0C\u6700\u591A 6 \u6761"),
|
|
31081
|
+
links: import_zod17.z.array(import_zod17.z.object({
|
|
31082
|
+
title: import_zod17.z.string().max(13).describe("\u94FE\u63A5\u6587\u6848\uFF0C\u4E0D\u8D85\u8FC7 13 \u5B57"),
|
|
31083
|
+
url: import_zod17.z.string()
|
|
31084
|
+
})).max(3).optional().describe("\u8DF3\u8F6C\u94FE\u63A5\u5217\u8868\uFF0C\u6700\u591A 3 \u6761"),
|
|
31085
|
+
action_url: import_zod17.z.string().optional().describe("\u6574\u5F20\u5361\u7247\u70B9\u51FB\u8DF3\u8F6C\u7684\u94FE\u63A5\uFF08\u4F01\u5FAE\u8981\u6C42\u5FC5\u586B\uFF1B\u7F3A\u7701\u65F6\u81EA\u52A8\u53D6\u7B2C\u4E00\u6761 links[].url\uFF09"),
|
|
31086
|
+
// ── news_notice ──────────────────────────────────────────────
|
|
31087
|
+
image_url: import_zod17.z.string().optional().describe("\u5361\u7247\u56FE\u7247\uFF08news_notice\uFF09"),
|
|
31088
|
+
image_text: import_zod17.z.object({ title: import_zod17.z.string(), desc: import_zod17.z.string().optional(), url: import_zod17.z.string().optional() }).optional().describe("\u5DE6\u56FE\u53F3\u6587\u533A\u57DF\uFF08news_notice\uFF09"),
|
|
31089
|
+
vertical_items: import_zod17.z.array(import_zod17.z.object({ title: import_zod17.z.string(), desc: import_zod17.z.string().optional() })).max(4).optional().describe("\u5782\u76F4\u5185\u5BB9\u5217\u8868\uFF0C\u6700\u591A 4 \u6761\uFF08news_notice\uFF09"),
|
|
31090
|
+
// ── button_interaction ───────────────────────────────────────
|
|
31091
|
+
buttons: import_zod17.z.array(import_zod17.z.object({
|
|
31092
|
+
text: import_zod17.z.string().max(4).describe("\u6309\u94AE\u6587\u6848\uFF0C\u4E0D\u8D85\u8FC7 4 \u5B57"),
|
|
31093
|
+
key: import_zod17.z.string().describe("\u6309\u94AE key\uFF0C\u7528\u4E8E\u56DE\u8C03"),
|
|
31094
|
+
style: import_zod17.z.number().int().min(1).max(4).optional().describe("\u6309\u94AE\u6837\u5F0F 1-4")
|
|
31095
|
+
})).max(6).optional().describe("\u6309\u94AE\u5217\u8868\uFF0C\u6700\u591A 6 \u6761\uFF08button_interaction\uFF09"),
|
|
31096
|
+
// ── vote_interaction ─────────────────────────────────────────
|
|
31097
|
+
checkbox: import_zod17.z.object({
|
|
31098
|
+
question_key: import_zod17.z.string().describe("\u9009\u62E9\u9898 key"),
|
|
31099
|
+
option_list: import_zod17.z.array(optionSchema).max(20).describe("\u9009\u9879\u5217\u8868\uFF0C\u6700\u591A 20 \u4E2A")
|
|
31100
|
+
}).optional().describe("\u9009\u62E9\u9898\uFF08vote_interaction\uFF09"),
|
|
31101
|
+
submit_text: import_zod17.z.string().optional().describe("\u63D0\u4EA4\u6309\u94AE\u6587\u6848\uFF0C\u9ED8\u8BA4\u300C\u63D0\u4EA4\u300D"),
|
|
31102
|
+
// ── multiple_interaction ─────────────────────────────────────
|
|
31103
|
+
selections: import_zod17.z.array(import_zod17.z.object({
|
|
31104
|
+
question_key: import_zod17.z.string(),
|
|
31105
|
+
title: import_zod17.z.string().optional(),
|
|
31106
|
+
option_list: import_zod17.z.array(optionSchema).max(20)
|
|
31107
|
+
})).max(3).optional().describe("\u4E0B\u62C9\u9009\u62E9\u5668\u5217\u8868\uFF0C\u6700\u591A 3 \u4E2A\uFF08multiple_interaction\uFF09")
|
|
31108
|
+
});
|
|
31109
|
+
function assertUrl(url, field) {
|
|
31110
|
+
if (url === void 0) return;
|
|
31111
|
+
if (!/^https?:\/\/\S+$/i.test(url)) {
|
|
31112
|
+
throw new Error(`${field} \u5FC5\u987B\u662F http(s):// \u5F00\u5934\u7684\u53EF\u8BBF\u95EE\u94FE\u63A5\uFF0C\u6536\u5230\u300C${url}\u300D`);
|
|
31113
|
+
}
|
|
31114
|
+
}
|
|
31115
|
+
function newTaskId() {
|
|
31116
|
+
return `wecom-card-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
31117
|
+
}
|
|
31118
|
+
function buildTemplateCard(input) {
|
|
31119
|
+
if (!input.title.trim()) throw new Error("title \u4E0D\u80FD\u4E3A\u7A7A");
|
|
31120
|
+
assertUrl(input.action_url, "action_url");
|
|
31121
|
+
assertUrl(input.image_url, "image_url");
|
|
31122
|
+
input.links?.forEach((link, i) => assertUrl(link.url, `links[${i}].url`));
|
|
31123
|
+
input.items?.forEach((item, i) => assertUrl(item.url, `items[${i}].url`));
|
|
31124
|
+
assertUrl(input.image_text?.url, "image_text.url");
|
|
31125
|
+
const actionUrl = input.action_url ?? input.links?.[0]?.url;
|
|
31126
|
+
if (!actionUrl) {
|
|
31127
|
+
throw new Error(
|
|
31128
|
+
"\u5361\u7247\u5FC5\u987B\u63D0\u4F9B action_url\uFF08\u6574\u5361\u70B9\u51FB\u8DF3\u8F6C\uFF09\uFF0C\u6216\u81F3\u5C11\u4E00\u6761\u5E26 url \u7684 links \u2014\u2014 \u4F01\u5FAE\u8981\u6C42 card_action \u4E0D\u80FD\u4E3A\u7A7A"
|
|
31129
|
+
);
|
|
31130
|
+
}
|
|
31131
|
+
const card = {
|
|
31132
|
+
card_type: input.card_type,
|
|
31133
|
+
main_title: {
|
|
31134
|
+
title: input.title,
|
|
31135
|
+
...input.desc ? { desc: input.desc } : {}
|
|
31136
|
+
},
|
|
31137
|
+
card_action: { type: 1, url: actionUrl }
|
|
31138
|
+
};
|
|
31139
|
+
if (input.source_desc) {
|
|
31140
|
+
card.source = {
|
|
31141
|
+
desc: input.source_desc,
|
|
31142
|
+
...input.source_color !== void 0 ? { desc_color: input.source_color } : {}
|
|
31143
|
+
};
|
|
31144
|
+
}
|
|
31145
|
+
if (input.emphasis_title || input.emphasis_desc) {
|
|
31146
|
+
card.emphasis_content = {
|
|
31147
|
+
...input.emphasis_title ? { title: input.emphasis_title } : {},
|
|
31148
|
+
...input.emphasis_desc ? { desc: input.emphasis_desc } : {}
|
|
31149
|
+
};
|
|
31150
|
+
}
|
|
31151
|
+
if (input.subtitle) card.sub_title_text = input.subtitle;
|
|
31152
|
+
if (input.quote_text) card.quote_area = { type: 0, quote_text: input.quote_text };
|
|
31153
|
+
if (input.items?.length) {
|
|
31154
|
+
card.horizontal_content_list = input.items.map((item) => ({
|
|
31155
|
+
type: item.url ? 1 : 0,
|
|
31156
|
+
keyname: item.key,
|
|
31157
|
+
value: item.value,
|
|
31158
|
+
...item.url ? { url: item.url } : {}
|
|
31159
|
+
}));
|
|
31160
|
+
}
|
|
31161
|
+
if (input.links?.length) {
|
|
31162
|
+
card.jump_list = input.links.map((link) => ({
|
|
31163
|
+
type: 1,
|
|
31164
|
+
url: link.url,
|
|
31165
|
+
title: link.title
|
|
31166
|
+
}));
|
|
31167
|
+
}
|
|
31168
|
+
if (input.card_type === "news_notice") {
|
|
31169
|
+
if (input.image_url) card.card_image = { url: input.image_url };
|
|
31170
|
+
if (input.image_text) {
|
|
31171
|
+
card.image_text_area = {
|
|
31172
|
+
type: input.image_text.url ? 1 : 0,
|
|
31173
|
+
...input.image_text.url ? { url: input.image_text.url } : {},
|
|
31174
|
+
title: input.image_text.title,
|
|
31175
|
+
...input.image_text.desc ? { desc: input.image_text.desc } : {}
|
|
31176
|
+
};
|
|
31177
|
+
}
|
|
31178
|
+
if (input.vertical_items?.length) {
|
|
31179
|
+
card.vertical_content_list = input.vertical_items.map((item) => ({
|
|
31180
|
+
title: item.title,
|
|
31181
|
+
...item.desc ? { desc: item.desc } : {}
|
|
31182
|
+
}));
|
|
31183
|
+
}
|
|
31184
|
+
}
|
|
31185
|
+
if (input.card_type === "button_interaction") {
|
|
31186
|
+
if (!input.buttons?.length) throw new Error("button_interaction \u5FC5\u987B\u63D0\u4F9B buttons");
|
|
31187
|
+
card.button_list = input.buttons.map((button) => ({
|
|
31188
|
+
text: button.text,
|
|
31189
|
+
key: button.key,
|
|
31190
|
+
...button.style !== void 0 ? { style: button.style } : {}
|
|
31191
|
+
}));
|
|
31192
|
+
card.task_id = newTaskId();
|
|
31193
|
+
}
|
|
31194
|
+
if (input.card_type === "vote_interaction") {
|
|
31195
|
+
if (!input.checkbox) throw new Error("vote_interaction \u5FC5\u987B\u63D0\u4F9B checkbox");
|
|
31196
|
+
card.checkbox = {
|
|
31197
|
+
question_key: input.checkbox.question_key,
|
|
31198
|
+
option_list: input.checkbox.option_list.map((option) => ({
|
|
31199
|
+
id: option.id,
|
|
31200
|
+
text: option.text,
|
|
31201
|
+
...option.is_checked !== void 0 ? { is_checked: option.is_checked } : {}
|
|
31202
|
+
}))
|
|
31203
|
+
};
|
|
31204
|
+
card.submit_button = { text: input.submit_text ?? "\u63D0\u4EA4", type: 1, key: "submit" };
|
|
31205
|
+
card.task_id = newTaskId();
|
|
31206
|
+
}
|
|
31207
|
+
if (input.card_type === "multiple_interaction") {
|
|
31208
|
+
if (!input.selections?.length) throw new Error("multiple_interaction \u5FC5\u987B\u63D0\u4F9B selections");
|
|
31209
|
+
card.select_list = input.selections.map((selection) => ({
|
|
31210
|
+
question_key: selection.question_key,
|
|
31211
|
+
...selection.title ? { title: selection.title } : {},
|
|
31212
|
+
option_list: selection.option_list.map((option) => ({
|
|
31213
|
+
id: option.id,
|
|
31214
|
+
text: option.text,
|
|
31215
|
+
...option.is_checked !== void 0 ? { is_checked: option.is_checked } : {}
|
|
31216
|
+
}))
|
|
31217
|
+
}));
|
|
31218
|
+
card.submit_button = { text: input.submit_text ?? "\u63D0\u4EA4", type: 1, key: "submit" };
|
|
31219
|
+
card.task_id = newTaskId();
|
|
31220
|
+
}
|
|
31221
|
+
return card;
|
|
31222
|
+
}
|
|
31223
|
+
function readReplyKey(exeConfig) {
|
|
31224
|
+
const configurable = exeConfig?.configurable;
|
|
31225
|
+
const key = configurable?.runConfig?.wecomReplyKey;
|
|
31226
|
+
return typeof key === "string" && key.length > 0 ? key : void 0;
|
|
31227
|
+
}
|
|
31228
|
+
function registerWecomCardTool() {
|
|
31229
|
+
if ((0, import_core71.getToolLattice)("wecom_card")) return;
|
|
31230
|
+
(0, import_core71.registerToolLattice)(
|
|
31231
|
+
"wecom_card",
|
|
31232
|
+
{
|
|
31233
|
+
name: "wecom_card",
|
|
31234
|
+
description: "\u5728**\u4F01\u4E1A\u5FAE\u4FE1\u4F1A\u8BDD**\u4E2D\uFF0C\u628A\u672C\u8F6E\u56DE\u590D\u7684\u6838\u5FC3\u7ED3\u679C\u505A\u6210\u4E00\u5F20\u6A21\u677F\u5361\u7247\uFF0C\u5361\u7247\u4F1A\u5728\u672C\u6761\u56DE\u590D\u540E\u7531\u6E20\u9053\u81EA\u52A8\u53D1\u9001\u3002\n\n\u4E3B\u52A8\u4F7F\u7528\uFF08\u7528\u6237\u4E0D\u9700\u8981\u8BF4\u300C\u5361\u7247\u300D\u300C\u5361\u7247\u6D88\u606F\u300D\uFF09\uFF1A\u5F53\u56DE\u590D\u7684\u4E3B\u8981\u4EF7\u503C\u662F\u7ED3\u6784\u5316\u4E1A\u52A1\u5BF9\u8C61\u65F6 \u2014\u2014 \u5BA2\u6237\u4EA4\u63A5/\u6D3E\u5355\u3001\u544A\u8B66/\u5F02\u5E38/\u98CE\u9669\u3001\u6E05\u5355/\u6838\u5BF9\u8868\u3001\u5F85\u529E/\u884C\u52A8\u9879\u3001\u72B6\u6001/\u8FDB\u5EA6/\u6307\u6807\u6C47\u603B\u3001\u6295\u7968/\u9009\u62E9/\u786E\u8BA4\u3001\u9700\u8981\u70B9\u51FB\u8FDB\u5165\u7684\u94FE\u63A5/\u516C\u544A\u5165\u53E3\u3002\u53EA\u8981\u7ED3\u679C\u5177\u5907\u300C\u6807\u9898 + 1-6 \u6761\u952E\u503C\u660E\u7EC6\uFF08\u6216\u9009\u9879\uFF09+ \u4E00\u4E2A\u53EF\u8DF3\u8F6C\u94FE\u63A5\u300D\uFF0C\u5C31\u5E94\u8C03\u7528\u3002\n\n\u4E0D\u8981\u4F7F\u7528\uFF1A\u666E\u901A\u95EE\u7B54\u3001\u89E3\u91CA\u3001\u95F2\u804A\u3001\u957F\u6587\u5206\u6790\u3001\u4EE3\u7801\u3001\u6CA1\u6709\u660E\u786E\u8DF3\u8F6C\u76EE\u6807\u7684\u5BF9\u8BDD\u3001\u4E00\u53E5\u8BDD\u5C31\u80FD\u8BF4\u6E05\u7684\u7ED3\u679C\u3002\n\n\u8C03\u7528\u540E\u4ECD\u7528\u4E00\u4E24\u53E5\u8BDD\u603B\u7ED3\u7ED3\u8BBA\uFF1B\u4E0D\u8981\u518D\u8F93\u51FA JSON\uFF0C\u4E5F\u4E0D\u8981\u5199\u3010\u5361\u7247\u6D88\u606F\u3011\u3002\u6BCF\u6761\u56DE\u590D\u6700\u591A\u4E00\u5F20\u5361\u7247\uFF0C\u91CD\u590D\u8C03\u7528\u4F1A\u66FF\u6362\u4E0A\u4E00\u5F20\u3002\u8FD4\u56DE ERROR \u65F6\u6309\u63D0\u793A\u4FEE\u6B63\u540E\u91CD\u8BD5\uFF0C\u4E0D\u8981\u628A ERROR \u653E\u8FDB\u56DE\u590D\u3002\u5B50 agent \u4E0D\u8981\u8C03\u7528\u672C\u5DE5\u5177\u3002",
|
|
31235
|
+
schema
|
|
31236
|
+
},
|
|
31237
|
+
async (input, exeConfig) => {
|
|
31238
|
+
const replyKey = readReplyKey(exeConfig);
|
|
31239
|
+
if (!replyKey) {
|
|
31240
|
+
return "ERROR: wecom_card \u53EA\u80FD\u5728\u4F01\u4E1A\u5FAE\u4FE1\u5B9E\u65F6\u4F1A\u8BDD\u4E2D\u4F7F\u7528\uFF0C\u8BF7\u76F4\u63A5\u7528\u6587\u5B57\u56DE\u590D\u3002";
|
|
31241
|
+
}
|
|
31242
|
+
try {
|
|
31243
|
+
const card = buildTemplateCard(input);
|
|
31244
|
+
if (!putWecomCard(replyKey, card)) {
|
|
31245
|
+
return "ERROR: \u672C\u6761\u56DE\u590D\u5DF2\u7ED3\u675F\uFF0C\u65E0\u6CD5\u518D\u9644\u5E26\u5361\u7247\u3002\u8BF7\u628A\u7ED3\u679C\u5199\u5165\u6B63\u6587\u3002";
|
|
31246
|
+
}
|
|
31247
|
+
const title = card.main_title?.title;
|
|
31248
|
+
const suffix = typeof title === "string" && title ? `\u300C${title}\u300D` : "";
|
|
31249
|
+
return `\u5DF2\u751F\u6210\u4F01\u4E1A\u5FAE\u4FE1\u5361\u7247${suffix}\uFF0C\u5C06\u968F\u672C\u6761\u56DE\u590D\u81EA\u52A8\u53D1\u9001\u3002\u8BF7\u7528\u6587\u5B57\u603B\u7ED3\u7ED3\u8BBA\uFF0C\u4E0D\u8981\u91CD\u590D\u5361\u7247\u5185\u5BB9\u3002`;
|
|
31250
|
+
} catch (error) {
|
|
31251
|
+
return `ERROR: ${error instanceof Error ? error.message : String(error)}\u3002\u8BF7\u4FEE\u6B63\u53C2\u6570\u540E\u91CD\u65B0\u8C03\u7528 wecom_card\u3002`;
|
|
31252
|
+
}
|
|
31253
|
+
}
|
|
31254
|
+
);
|
|
31255
|
+
}
|
|
31256
|
+
|
|
30859
31257
|
// src/channels/wecom/WecomChannelAdapter.ts
|
|
30860
31258
|
init_Logger();
|
|
30861
31259
|
var logger6 = new Logger({ serviceName: "lattice/gateway/wecom" });
|
|
30862
|
-
var wecomConfigSchema =
|
|
30863
|
-
botId:
|
|
30864
|
-
secret:
|
|
31260
|
+
var wecomConfigSchema = import_zod18.z.object({
|
|
31261
|
+
botId: import_zod18.z.string(),
|
|
31262
|
+
secret: import_zod18.z.string()
|
|
30865
31263
|
});
|
|
30866
31264
|
var RECONNECT_BASE_MS = 5e3;
|
|
30867
31265
|
var RECONNECT_MAX_MS = 6e4;
|
|
31266
|
+
var SENT_CARD_TTL_MS = 10 * 6e4;
|
|
31267
|
+
var MAX_SENT_CARDS = 1e3;
|
|
30868
31268
|
var activeConnections2 = /* @__PURE__ */ new Map();
|
|
30869
31269
|
var streamIdsByReqId = /* @__PURE__ */ new Map();
|
|
30870
31270
|
var MAX_TRACKED_STREAMS = 1e3;
|
|
30871
|
-
|
|
30872
|
-
|
|
30873
|
-
|
|
31271
|
+
var sentCardsByTaskId = /* @__PURE__ */ new Map();
|
|
31272
|
+
var handledCardEventKeys = /* @__PURE__ */ new Map();
|
|
31273
|
+
var ACKNOWLEDGED_TTL_MS = 10 * 6e4;
|
|
31274
|
+
function isRecord4(value) {
|
|
31275
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
31276
|
+
}
|
|
31277
|
+
function replyKeyOf(installationId, reqId) {
|
|
31278
|
+
return `${installationId}:${reqId ?? "no-req"}`;
|
|
31279
|
+
}
|
|
31280
|
+
function replyKeyForTarget(replyTarget) {
|
|
31281
|
+
const frame = replyTarget.rawTarget?.frame;
|
|
31282
|
+
return replyKeyOf(replyTarget.channelInstallationId, frame?.headers?.req_id);
|
|
31283
|
+
}
|
|
31284
|
+
function isEventReplyTarget(replyTarget) {
|
|
31285
|
+
return replyTarget.rawTarget?.kind === "template_card_event";
|
|
31286
|
+
}
|
|
31287
|
+
function eventChatId(replyTarget) {
|
|
31288
|
+
const chatId = replyTarget.rawTarget?.chatId;
|
|
31289
|
+
return typeof chatId === "string" && chatId.length > 0 ? chatId : void 0;
|
|
30874
31290
|
}
|
|
30875
31291
|
function streamIdFor(replyTarget) {
|
|
30876
|
-
const key =
|
|
31292
|
+
const key = replyKeyForTarget(replyTarget);
|
|
30877
31293
|
let streamId = streamIdsByReqId.get(key);
|
|
30878
31294
|
if (!streamId) {
|
|
30879
31295
|
streamId = (0, import_node_crypto27.randomUUID)();
|
|
@@ -30885,6 +31301,267 @@ function streamIdFor(replyTarget) {
|
|
|
30885
31301
|
}
|
|
30886
31302
|
return streamId;
|
|
30887
31303
|
}
|
|
31304
|
+
function rememberSentCard(card) {
|
|
31305
|
+
const taskId = typeof card.task_id === "string" ? card.task_id : void 0;
|
|
31306
|
+
if (!taskId) return;
|
|
31307
|
+
const now = Date.now();
|
|
31308
|
+
for (const [key, entry] of sentCardsByTaskId) {
|
|
31309
|
+
if (entry.expiresAt <= now) sentCardsByTaskId.delete(key);
|
|
31310
|
+
}
|
|
31311
|
+
sentCardsByTaskId.set(taskId, { card, expiresAt: now + SENT_CARD_TTL_MS });
|
|
31312
|
+
while (sentCardsByTaskId.size > MAX_SENT_CARDS) {
|
|
31313
|
+
const oldest = sentCardsByTaskId.keys().next().value;
|
|
31314
|
+
if (oldest === void 0) break;
|
|
31315
|
+
sentCardsByTaskId.delete(oldest);
|
|
31316
|
+
}
|
|
31317
|
+
}
|
|
31318
|
+
function sentCardForTask(taskId) {
|
|
31319
|
+
if (!taskId) return void 0;
|
|
31320
|
+
const entry = sentCardsByTaskId.get(taskId);
|
|
31321
|
+
if (!entry) return void 0;
|
|
31322
|
+
if (entry.expiresAt <= Date.now()) {
|
|
31323
|
+
sentCardsByTaskId.delete(taskId);
|
|
31324
|
+
return void 0;
|
|
31325
|
+
}
|
|
31326
|
+
return entry.card;
|
|
31327
|
+
}
|
|
31328
|
+
function claimCardEvent(taskId, eventKey) {
|
|
31329
|
+
if (!taskId) return true;
|
|
31330
|
+
const key = `${taskId}:${eventKey ?? ""}`;
|
|
31331
|
+
const now = Date.now();
|
|
31332
|
+
for (const [handled, expiresAt] of handledCardEventKeys) {
|
|
31333
|
+
if (expiresAt <= now) handledCardEventKeys.delete(handled);
|
|
31334
|
+
}
|
|
31335
|
+
if (handledCardEventKeys.has(key)) return false;
|
|
31336
|
+
handledCardEventKeys.set(key, now + ACKNOWLEDGED_TTL_MS);
|
|
31337
|
+
while (handledCardEventKeys.size > MAX_SENT_CARDS) {
|
|
31338
|
+
const oldest = handledCardEventKeys.keys().next().value;
|
|
31339
|
+
if (oldest === void 0) break;
|
|
31340
|
+
handledCardEventKeys.delete(oldest);
|
|
31341
|
+
}
|
|
31342
|
+
return true;
|
|
31343
|
+
}
|
|
31344
|
+
async function sendStreamFrame(connection, replyTarget, input) {
|
|
31345
|
+
if (isEventReplyTarget(replyTarget)) {
|
|
31346
|
+
await sendEventReply(connection, replyTarget, input);
|
|
31347
|
+
return;
|
|
31348
|
+
}
|
|
31349
|
+
const frame = replyTarget.rawTarget?.frame;
|
|
31350
|
+
if (!frame) {
|
|
31351
|
+
logger6.warn("WeCom reply target has no inbound frame, skipping", {
|
|
31352
|
+
installationId: replyTarget.channelInstallationId
|
|
31353
|
+
});
|
|
31354
|
+
return;
|
|
31355
|
+
}
|
|
31356
|
+
const report = (message, error) => logger6.warn(message, {
|
|
31357
|
+
installationId: replyTarget.channelInstallationId,
|
|
31358
|
+
error: error instanceof Error ? error.message : String(error)
|
|
31359
|
+
});
|
|
31360
|
+
const text = input.text || (input.done ? input.card ? "\u5DF2\u5B8C\u6210\uFF0C\u8BE6\u60C5\u89C1\u4E0B\u65B9\u5361\u7247\u3002" : "\u5904\u7406\u5B8C\u6210\u3002" : "");
|
|
31361
|
+
if (!text) return;
|
|
31362
|
+
try {
|
|
31363
|
+
await Promise.resolve(connection.client.reply(frame, {
|
|
31364
|
+
msgtype: "stream",
|
|
31365
|
+
stream: { id: streamIdFor(replyTarget), finish: input.done, content: text }
|
|
31366
|
+
}));
|
|
31367
|
+
} catch (error) {
|
|
31368
|
+
report("WeCom stream reply failed", error);
|
|
31369
|
+
}
|
|
31370
|
+
if (input.done && input.card) {
|
|
31371
|
+
try {
|
|
31372
|
+
await Promise.resolve(connection.client.reply(frame, {
|
|
31373
|
+
msgtype: "template_card",
|
|
31374
|
+
template_card: input.card
|
|
31375
|
+
}));
|
|
31376
|
+
rememberSentCard(input.card);
|
|
31377
|
+
logger6.info("WeCom card sent", {
|
|
31378
|
+
installationId: replyTarget.channelInstallationId,
|
|
31379
|
+
cardType: input.card.card_type
|
|
31380
|
+
});
|
|
31381
|
+
} catch (error) {
|
|
31382
|
+
report("WeCom card reply failed (text already sent)", error);
|
|
31383
|
+
}
|
|
31384
|
+
}
|
|
31385
|
+
}
|
|
31386
|
+
async function sendEventReply(connection, replyTarget, input) {
|
|
31387
|
+
if (!input.done) return;
|
|
31388
|
+
const chatId = eventChatId(replyTarget);
|
|
31389
|
+
if (!chatId) {
|
|
31390
|
+
logger6.warn("WeCom card event has no chat id, cannot reply", {
|
|
31391
|
+
installationId: replyTarget.channelInstallationId
|
|
31392
|
+
});
|
|
31393
|
+
return;
|
|
31394
|
+
}
|
|
31395
|
+
const sendMessage2 = connection.client.sendMessage;
|
|
31396
|
+
if (!sendMessage2) {
|
|
31397
|
+
logger6.warn("WeCom client does not support sendMessage, cannot reply to card event", {
|
|
31398
|
+
installationId: replyTarget.channelInstallationId
|
|
31399
|
+
});
|
|
31400
|
+
return;
|
|
31401
|
+
}
|
|
31402
|
+
const report = (message, error) => logger6.warn(message, {
|
|
31403
|
+
installationId: replyTarget.channelInstallationId,
|
|
31404
|
+
error: error instanceof Error ? error.message : String(error)
|
|
31405
|
+
});
|
|
31406
|
+
if (input.card) {
|
|
31407
|
+
try {
|
|
31408
|
+
await Promise.resolve(sendMessage2.call(connection.client, chatId, {
|
|
31409
|
+
msgtype: "template_card",
|
|
31410
|
+
template_card: input.card
|
|
31411
|
+
}));
|
|
31412
|
+
rememberSentCard(input.card);
|
|
31413
|
+
logger6.info("WeCom card sent", {
|
|
31414
|
+
installationId: replyTarget.channelInstallationId,
|
|
31415
|
+
cardType: input.card.card_type
|
|
31416
|
+
});
|
|
31417
|
+
} catch (error) {
|
|
31418
|
+
report("WeCom card event card failed", error);
|
|
31419
|
+
}
|
|
31420
|
+
return;
|
|
31421
|
+
}
|
|
31422
|
+
if (input.text) {
|
|
31423
|
+
try {
|
|
31424
|
+
await Promise.resolve(sendMessage2.call(connection.client, chatId, {
|
|
31425
|
+
msgtype: "markdown",
|
|
31426
|
+
markdown: { content: input.text }
|
|
31427
|
+
}));
|
|
31428
|
+
} catch (error) {
|
|
31429
|
+
report("WeCom card event reply failed", error);
|
|
31430
|
+
}
|
|
31431
|
+
}
|
|
31432
|
+
}
|
|
31433
|
+
function acknowledgedCard(taskId, eventKey) {
|
|
31434
|
+
const desc = eventKey ? `\u5DF2\u6536\u5230\uFF1A${eventKey}` : "\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u5904\u7406\u2026";
|
|
31435
|
+
const original = sentCardForTask(taskId);
|
|
31436
|
+
if (original) {
|
|
31437
|
+
const mainTitle = isRecord4(original.main_title) ? original.main_title : {};
|
|
31438
|
+
return { ...original, main_title: { ...mainTitle, desc } };
|
|
31439
|
+
}
|
|
31440
|
+
return {
|
|
31441
|
+
card_type: "text_notice",
|
|
31442
|
+
main_title: { title: "\u5DF2\u6536\u5230\u4F60\u7684\u64CD\u4F5C", desc },
|
|
31443
|
+
...taskId ? { task_id: taskId } : {}
|
|
31444
|
+
};
|
|
31445
|
+
}
|
|
31446
|
+
function cardEventFields(event) {
|
|
31447
|
+
const nested = isRecord4(event?.template_card_event) ? event.template_card_event : event;
|
|
31448
|
+
const source = nested ?? {};
|
|
31449
|
+
return {
|
|
31450
|
+
cardEvent: source,
|
|
31451
|
+
taskId: typeof source.task_id === "string" ? source.task_id : void 0,
|
|
31452
|
+
eventKey: typeof source.event_key === "string" ? source.event_key : void 0,
|
|
31453
|
+
cardType: typeof source.card_type === "string" ? source.card_type : void 0
|
|
31454
|
+
};
|
|
31455
|
+
}
|
|
31456
|
+
function describeError(error) {
|
|
31457
|
+
if (error instanceof Error) return error.message;
|
|
31458
|
+
if (typeof error === "string") return error;
|
|
31459
|
+
try {
|
|
31460
|
+
return JSON.stringify(error);
|
|
31461
|
+
} catch {
|
|
31462
|
+
return String(error);
|
|
31463
|
+
}
|
|
31464
|
+
}
|
|
31465
|
+
function cardEventInbound(frame, installation, input) {
|
|
31466
|
+
const body = frame.body;
|
|
31467
|
+
const { cardEvent, taskId, eventKey, cardType } = cardEventFields(body.event);
|
|
31468
|
+
const summary = eventKey ? `\u7528\u6237\u70B9\u51FB\u4E86\u5361\u7247\u6309\u94AE\u300C${eventKey}\u300D${taskId ? `\uFF08task_id=${taskId}\uFF09` : ""}` : `\u7528\u6237\u63D0\u4EA4\u4E86\u5361\u7247\u64CD\u4F5C${taskId ? `\uFF08task_id=${taskId}\uFF09` : ""}\uFF1A${JSON.stringify(cardEvent)}`;
|
|
31469
|
+
return {
|
|
31470
|
+
channel: "wecom",
|
|
31471
|
+
channelInstallationId: installation.id,
|
|
31472
|
+
tenantId: installation.tenantId,
|
|
31473
|
+
sender: { id: input.userId },
|
|
31474
|
+
content: {
|
|
31475
|
+
text: summary,
|
|
31476
|
+
metadata: {
|
|
31477
|
+
messageId: body.msgid,
|
|
31478
|
+
chatId: input.chatId,
|
|
31479
|
+
chatType: body.chattype === "group" ? "group" : "direct",
|
|
31480
|
+
taskId,
|
|
31481
|
+
eventKey,
|
|
31482
|
+
cardType,
|
|
31483
|
+
cardEvent,
|
|
31484
|
+
wecomReplyKey: replyKeyOf(installation.id, frame.headers.req_id)
|
|
31485
|
+
}
|
|
31486
|
+
},
|
|
31487
|
+
conversation: {
|
|
31488
|
+
id: input.chatId,
|
|
31489
|
+
type: body.chattype === "group" ? "group" : "direct"
|
|
31490
|
+
},
|
|
31491
|
+
replyTarget: {
|
|
31492
|
+
adapterChannel: "wecom",
|
|
31493
|
+
channelInstallationId: installation.id,
|
|
31494
|
+
rawTarget: { kind: "template_card_event", frame, chatId: input.chatId }
|
|
31495
|
+
}
|
|
31496
|
+
};
|
|
31497
|
+
}
|
|
31498
|
+
function handleTemplateCardEvent(rawFrame, installation, client, router) {
|
|
31499
|
+
const frame = rawFrame;
|
|
31500
|
+
const body = frame?.body;
|
|
31501
|
+
const event = body?.event;
|
|
31502
|
+
const reqId = frame?.headers?.req_id;
|
|
31503
|
+
if (!body || event?.eventtype !== "template_card_event" || typeof reqId !== "string") {
|
|
31504
|
+
return;
|
|
31505
|
+
}
|
|
31506
|
+
const userId = body.from?.userid;
|
|
31507
|
+
const chatId = typeof body.chatid === "string" && body.chatid ? body.chatid : userId;
|
|
31508
|
+
if (!userId || !chatId) {
|
|
31509
|
+
logger6.warn("WeCom card event missing user/chat id, skipping", {
|
|
31510
|
+
installationId: installation.id
|
|
31511
|
+
});
|
|
31512
|
+
return;
|
|
31513
|
+
}
|
|
31514
|
+
const { taskId, eventKey } = cardEventFields(event);
|
|
31515
|
+
if (!claimCardEvent(taskId, eventKey)) {
|
|
31516
|
+
logger6.info("WeCom duplicate card event ignored", {
|
|
31517
|
+
installationId: installation.id,
|
|
31518
|
+
taskId,
|
|
31519
|
+
eventKey
|
|
31520
|
+
});
|
|
31521
|
+
return;
|
|
31522
|
+
}
|
|
31523
|
+
const updateTemplateCard = client.updateTemplateCard;
|
|
31524
|
+
if (updateTemplateCard) {
|
|
31525
|
+
const updated = acknowledgedCard(taskId, eventKey);
|
|
31526
|
+
try {
|
|
31527
|
+
void Promise.resolve(updateTemplateCard.call(client, rawFrame, updated)).catch((error) => {
|
|
31528
|
+
logger6.warn("WeCom template card update failed", {
|
|
31529
|
+
installationId: installation.id,
|
|
31530
|
+
error: describeError(error)
|
|
31531
|
+
});
|
|
31532
|
+
});
|
|
31533
|
+
} catch (error) {
|
|
31534
|
+
logger6.warn("WeCom template card update failed", {
|
|
31535
|
+
installationId: installation.id,
|
|
31536
|
+
error: describeError(error)
|
|
31537
|
+
});
|
|
31538
|
+
}
|
|
31539
|
+
} else {
|
|
31540
|
+
logger6.warn("WeCom client does not support updateTemplateCard", {
|
|
31541
|
+
installationId: installation.id
|
|
31542
|
+
});
|
|
31543
|
+
}
|
|
31544
|
+
if (!router) return;
|
|
31545
|
+
logger6.info("WeCom card event dispatched", {
|
|
31546
|
+
installationId: installation.id,
|
|
31547
|
+
taskId,
|
|
31548
|
+
eventKey,
|
|
31549
|
+
chatId
|
|
31550
|
+
});
|
|
31551
|
+
try {
|
|
31552
|
+
void router.dispatch(cardEventInbound(frame, installation, { chatId, userId })).catch((error) => {
|
|
31553
|
+
logger6.error("WeCom card event dispatch error", {
|
|
31554
|
+
installationId: installation.id,
|
|
31555
|
+
error: describeError(error)
|
|
31556
|
+
});
|
|
31557
|
+
});
|
|
31558
|
+
} catch (error) {
|
|
31559
|
+
logger6.error("WeCom card event dispatch error", {
|
|
31560
|
+
installationId: installation.id,
|
|
31561
|
+
error: describeError(error)
|
|
31562
|
+
});
|
|
31563
|
+
}
|
|
31564
|
+
}
|
|
30888
31565
|
var wecomChannelAdapter = {
|
|
30889
31566
|
channel: "wecom",
|
|
30890
31567
|
configSchema: wecomConfigSchema,
|
|
@@ -30898,11 +31575,13 @@ var wecomChannelAdapter = {
|
|
|
30898
31575
|
sender: { id: parsed.fromUserId },
|
|
30899
31576
|
content: {
|
|
30900
31577
|
text: parsed.text,
|
|
30901
|
-
// `messageId` 供去重中间件使用(企业微信可能重投同一 msgid
|
|
31578
|
+
// `messageId` 供去重中间件使用(企业微信可能重投同一 msgid);
|
|
31579
|
+
// `wecomReplyKey` 供 `wecom_card` 工具登记本轮卡片。
|
|
30902
31580
|
metadata: {
|
|
30903
31581
|
messageId: parsed.msgId,
|
|
30904
31582
|
chatId: parsed.chatId,
|
|
30905
|
-
chatType: parsed.chatType
|
|
31583
|
+
chatType: parsed.chatType,
|
|
31584
|
+
wecomReplyKey: replyKeyOf(installation.id, parsed.reqId)
|
|
30906
31585
|
}
|
|
30907
31586
|
},
|
|
30908
31587
|
conversation: {
|
|
@@ -30926,14 +31605,12 @@ var wecomChannelAdapter = {
|
|
|
30926
31605
|
});
|
|
30927
31606
|
return;
|
|
30928
31607
|
}
|
|
30929
|
-
const key =
|
|
30930
|
-
|
|
30931
|
-
|
|
30932
|
-
|
|
30933
|
-
|
|
30934
|
-
|
|
30935
|
-
content: message.text
|
|
30936
|
-
}
|
|
31608
|
+
const key = replyKeyForTarget(replyTarget);
|
|
31609
|
+
const card = takeWecomCard(key);
|
|
31610
|
+
await sendStreamFrame(connection, replyTarget, {
|
|
31611
|
+
text: message.text,
|
|
31612
|
+
done: true,
|
|
31613
|
+
card
|
|
30937
31614
|
});
|
|
30938
31615
|
streamIdsByReqId.delete(key);
|
|
30939
31616
|
},
|
|
@@ -30952,15 +31629,21 @@ var wecomChannelAdapter = {
|
|
|
30952
31629
|
});
|
|
30953
31630
|
return;
|
|
30954
31631
|
}
|
|
30955
|
-
|
|
30956
|
-
|
|
30957
|
-
|
|
30958
|
-
|
|
30959
|
-
|
|
30960
|
-
|
|
31632
|
+
const key = replyKeyForTarget(replyTarget);
|
|
31633
|
+
let card;
|
|
31634
|
+
if (chunk.done) {
|
|
31635
|
+
if (chunk.reason !== void 0 && chunk.reason !== "completed") {
|
|
31636
|
+
discardWecomCard(key);
|
|
31637
|
+
} else {
|
|
31638
|
+
card = takeWecomCard(key);
|
|
30961
31639
|
}
|
|
31640
|
+
}
|
|
31641
|
+
await sendStreamFrame(connection, replyTarget, {
|
|
31642
|
+
text: chunk.text,
|
|
31643
|
+
done: chunk.done,
|
|
31644
|
+
card
|
|
30962
31645
|
});
|
|
30963
|
-
if (chunk.done) streamIdsByReqId.delete(
|
|
31646
|
+
if (chunk.done) streamIdsByReqId.delete(key);
|
|
30964
31647
|
},
|
|
30965
31648
|
resolveThreadId(message, binding) {
|
|
30966
31649
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -30994,6 +31677,9 @@ var wecomChannelAdapter = {
|
|
|
30994
31677
|
});
|
|
30995
31678
|
});
|
|
30996
31679
|
});
|
|
31680
|
+
client.on("event.template_card_event", (frame) => {
|
|
31681
|
+
handleTemplateCardEvent(frame, installation, client, router);
|
|
31682
|
+
});
|
|
30997
31683
|
client.on("authenticated", () => {
|
|
30998
31684
|
connection.attempts = 0;
|
|
30999
31685
|
});
|
|
@@ -31130,7 +31816,7 @@ var configureSwagger = async (app2, customSwaggerConfig, customSwaggerUiConfig)
|
|
|
31130
31816
|
|
|
31131
31817
|
// src/services/agent_task_consumer.ts
|
|
31132
31818
|
var import_node_crypto28 = require("crypto");
|
|
31133
|
-
var
|
|
31819
|
+
var import_core72 = require("@axiom-lattice/core");
|
|
31134
31820
|
var import_protocols32 = require("@axiom-lattice/protocols");
|
|
31135
31821
|
var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
31136
31822
|
const {
|
|
@@ -31150,7 +31836,7 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
|
31150
31836
|
`\u5F00\u59CB\u5904\u7406\u4EFB\u52A1 [assistant_id: ${assistant_id}, thread_id: ${thread_id}]`
|
|
31151
31837
|
);
|
|
31152
31838
|
const scope = (0, import_protocols32.resolveRunScope)(runConfig);
|
|
31153
|
-
const agent =
|
|
31839
|
+
const agent = import_core72.agentInstanceManager.getAgent({ assistant_id, thread_id, tenant_id, workspace_id: scope.workspaceId, project_id: scope.projectId, custom_run_config: runConfig });
|
|
31154
31840
|
if (callback_event) {
|
|
31155
31841
|
const callbackEvent = callback_event;
|
|
31156
31842
|
const messageId = typeof input?.id === "string" && input.id !== "" ? input.id : (0, import_node_crypto28.randomUUID)();
|
|
@@ -31171,13 +31857,13 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
|
31171
31857
|
const onCompleted = (evt) => {
|
|
31172
31858
|
if (!belongsToMessage(evt)) return;
|
|
31173
31859
|
settle(() => {
|
|
31174
|
-
|
|
31860
|
+
import_core72.eventBus.publish(callbackEvent, {
|
|
31175
31861
|
success: true,
|
|
31176
31862
|
state: evt.state
|
|
31177
31863
|
});
|
|
31178
31864
|
if (main_thread_id && main_tenant_id) {
|
|
31179
31865
|
try {
|
|
31180
|
-
const mainAgent =
|
|
31866
|
+
const mainAgent = import_core72.agentInstanceManager.getAgent({
|
|
31181
31867
|
assistant_id: main_assistant_id ?? assistant_id,
|
|
31182
31868
|
thread_id: main_thread_id,
|
|
31183
31869
|
tenant_id: main_tenant_id,
|
|
@@ -31210,7 +31896,7 @@ ${summary}`
|
|
|
31210
31896
|
const onInterrupted = (evt) => {
|
|
31211
31897
|
if (!belongsToMessage(evt)) return;
|
|
31212
31898
|
settle(() => {
|
|
31213
|
-
|
|
31899
|
+
import_core72.eventBus.publish(callbackEvent, {
|
|
31214
31900
|
success: true,
|
|
31215
31901
|
state: evt.state
|
|
31216
31902
|
});
|
|
@@ -31219,7 +31905,7 @@ ${summary}`
|
|
|
31219
31905
|
const onFailed = (evt) => {
|
|
31220
31906
|
if (!belongsToMessage(evt)) return;
|
|
31221
31907
|
settle(() => {
|
|
31222
|
-
|
|
31908
|
+
import_core72.eventBus.publish(callbackEvent, {
|
|
31223
31909
|
success: false,
|
|
31224
31910
|
error: evt?.error instanceof Error ? evt.error.message : typeof evt?.error === "string" ? evt.error : "Agent execution failed"
|
|
31225
31911
|
});
|
|
@@ -31234,13 +31920,13 @@ ${summary}`
|
|
|
31234
31920
|
agent.subscribe("message:interrupted", onInterrupted);
|
|
31235
31921
|
agent.subscribe("message:failed", onFailed);
|
|
31236
31922
|
try {
|
|
31237
|
-
await agent.addMessage({ input: { ...input, id: messageId }, command, custom_run_config: runConfig },
|
|
31923
|
+
await agent.addMessage({ input: { ...input, id: messageId }, command, custom_run_config: runConfig }, import_core72.QueueMode.STEER);
|
|
31238
31924
|
} catch (error) {
|
|
31239
31925
|
dispose();
|
|
31240
31926
|
throw error;
|
|
31241
31927
|
}
|
|
31242
31928
|
} else {
|
|
31243
|
-
await agent.addMessage({ input, command, custom_run_config: runConfig },
|
|
31929
|
+
await agent.addMessage({ input, command, custom_run_config: runConfig }, import_core72.QueueMode.STEER);
|
|
31244
31930
|
}
|
|
31245
31931
|
return true;
|
|
31246
31932
|
} catch (error) {
|
|
@@ -31259,7 +31945,7 @@ ${summary}`
|
|
|
31259
31945
|
return handleAgentTask(taskRequest, nextRetryCount);
|
|
31260
31946
|
}
|
|
31261
31947
|
if (callback_event) {
|
|
31262
|
-
|
|
31948
|
+
import_core72.eventBus.publish(callback_event, {
|
|
31263
31949
|
success: false,
|
|
31264
31950
|
error: error instanceof Error ? error.message : String(error)
|
|
31265
31951
|
});
|
|
@@ -31296,7 +31982,7 @@ var _AgentTaskConsumer = class _AgentTaskConsumer {
|
|
|
31296
31982
|
* 初始化事件监听和队列轮询
|
|
31297
31983
|
*/
|
|
31298
31984
|
initialize() {
|
|
31299
|
-
|
|
31985
|
+
import_core72.eventBus.subscribe(import_core72.AGENT_TASK_EVENT, this.trigger_agent_task.bind(this));
|
|
31300
31986
|
this.startPollingQueue();
|
|
31301
31987
|
console.log("Agent\u4EFB\u52A1\u6D88\u8D39\u8005\u5DF2\u542F\u52A8\u5E76\u76D1\u542C\u4EFB\u52A1\u4E8B\u4EF6\u548C\u961F\u5217");
|
|
31302
31988
|
}
|
|
@@ -31415,7 +32101,7 @@ var _AgentTaskConsumer = class _AgentTaskConsumer {
|
|
|
31415
32101
|
handleAgentTask(taskRequest).catch((error) => {
|
|
31416
32102
|
console.error("\u5904\u7406Agent\u4EFB\u52A1\u65F6\u53D1\u751F\u672A\u6355\u83B7\u7684\u9519\u8BEF:", error);
|
|
31417
32103
|
if (taskRequest.callback_event) {
|
|
31418
|
-
|
|
32104
|
+
import_core72.eventBus.publish(taskRequest.callback_event, {
|
|
31419
32105
|
success: false,
|
|
31420
32106
|
error: error instanceof Error ? error.message : String(error)
|
|
31421
32107
|
});
|
|
@@ -31464,13 +32150,13 @@ function createGracefulShutdown(options) {
|
|
|
31464
32150
|
}
|
|
31465
32151
|
|
|
31466
32152
|
// src/index.ts
|
|
31467
|
-
var
|
|
32153
|
+
var import_core100 = require("@axiom-lattice/core");
|
|
31468
32154
|
|
|
31469
32155
|
// src/channels/ChannelInfrastructure.ts
|
|
31470
|
-
var
|
|
32156
|
+
var import_core74 = require("@axiom-lattice/core");
|
|
31471
32157
|
|
|
31472
32158
|
// src/router/MessageRouter.ts
|
|
31473
|
-
var
|
|
32159
|
+
var import_core73 = require("@axiom-lattice/core");
|
|
31474
32160
|
var import_protocols33 = require("@axiom-lattice/protocols");
|
|
31475
32161
|
var import_crypto11 = require("crypto");
|
|
31476
32162
|
var BindingNotFoundError = class extends Error {
|
|
@@ -31486,6 +32172,7 @@ var ChannelInstallationNotFoundError = class extends Error {
|
|
|
31486
32172
|
}
|
|
31487
32173
|
};
|
|
31488
32174
|
var DEFAULT_STREAM_PLACEHOLDER = "\u6B63\u5728\u5904\u7406\u2026";
|
|
32175
|
+
var DEFAULT_STREAM_FAILURE_TEXT = "\u5904\u7406\u672A\u5B8C\u6210\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";
|
|
31489
32176
|
function streamPlaceholderFor(installation) {
|
|
31490
32177
|
const config = installation?.config;
|
|
31491
32178
|
if (config !== null && typeof config === "object" && !Array.isArray(config)) {
|
|
@@ -31494,6 +32181,14 @@ function streamPlaceholderFor(installation) {
|
|
|
31494
32181
|
}
|
|
31495
32182
|
return DEFAULT_STREAM_PLACEHOLDER;
|
|
31496
32183
|
}
|
|
32184
|
+
function streamFailureTextFor(installation) {
|
|
32185
|
+
const config = installation?.config;
|
|
32186
|
+
if (config !== null && typeof config === "object" && !Array.isArray(config)) {
|
|
32187
|
+
const value = config.streamFailureText;
|
|
32188
|
+
if (typeof value === "string") return value;
|
|
32189
|
+
}
|
|
32190
|
+
return DEFAULT_STREAM_FAILURE_TEXT;
|
|
32191
|
+
}
|
|
31497
32192
|
var InvalidChannelInstallationError = class extends Error {
|
|
31498
32193
|
constructor(message = "Channel installation is not valid for this message") {
|
|
31499
32194
|
super(message);
|
|
@@ -31765,7 +32460,7 @@ var _MessageRouter = class _MessageRouter {
|
|
|
31765
32460
|
channel: message.channel,
|
|
31766
32461
|
adapterChannel: adapter.channel
|
|
31767
32462
|
}, "Thread resolved by adapter strategy");
|
|
31768
|
-
const threadStore = (0,
|
|
32463
|
+
const threadStore = (0, import_core73.getStoreLattice)("default", "thread").store;
|
|
31769
32464
|
try {
|
|
31770
32465
|
await threadStore.createThread(
|
|
31771
32466
|
tenantId,
|
|
@@ -31802,7 +32497,7 @@ var _MessageRouter = class _MessageRouter {
|
|
|
31802
32497
|
}
|
|
31803
32498
|
}
|
|
31804
32499
|
if (!threadId) {
|
|
31805
|
-
const threadStore = (0,
|
|
32500
|
+
const threadStore = (0, import_core73.getStoreLattice)("default", "thread").store;
|
|
31806
32501
|
const newThreadId = (0, import_crypto11.randomUUID)();
|
|
31807
32502
|
console.log({
|
|
31808
32503
|
event: "dispatch:thread:create",
|
|
@@ -31842,7 +32537,7 @@ var _MessageRouter = class _MessageRouter {
|
|
|
31842
32537
|
senderId: message.sender.id,
|
|
31843
32538
|
contentLength: message.content.text.length
|
|
31844
32539
|
}, "Dispatching to agent");
|
|
31845
|
-
const agent =
|
|
32540
|
+
const agent = import_core73.agentInstanceManager.getAgent({
|
|
31846
32541
|
tenant_id: tenantId,
|
|
31847
32542
|
assistant_id: agentId,
|
|
31848
32543
|
thread_id: threadId,
|
|
@@ -31905,7 +32600,13 @@ var _MessageRouter = class _MessageRouter {
|
|
|
31905
32600
|
if (cleaned || !event.consumedInputMessageIds.includes(inputMessageId)) return;
|
|
31906
32601
|
cleanup();
|
|
31907
32602
|
if (event.inputMessageId !== inputMessageId) return;
|
|
31908
|
-
|
|
32603
|
+
if (replyAdapter.sendStreamChunk && streamState.finished) return;
|
|
32604
|
+
if (replyAdapter.sendStreamChunk) streamState.finished = true;
|
|
32605
|
+
const delivery = replyAdapter.sendStreamChunk ? replyAdapter.sendStreamChunk(
|
|
32606
|
+
replyTarget,
|
|
32607
|
+
{ text: event.outputText, done: true, reason: "completed" },
|
|
32608
|
+
installation
|
|
32609
|
+
) : replyAdapter.sendReply(replyTarget, {
|
|
31909
32610
|
text: event.outputText,
|
|
31910
32611
|
metadata: { inputMessageId, outputMessageId: event.outputMessageId }
|
|
31911
32612
|
}, installation);
|
|
@@ -32029,17 +32730,34 @@ var _MessageRouter = class _MessageRouter {
|
|
|
32029
32730
|
const send = adapter.sendStreamChunk;
|
|
32030
32731
|
if (!send) return;
|
|
32031
32732
|
let started = false;
|
|
32733
|
+
let normalEnd = false;
|
|
32032
32734
|
let accumulated = "";
|
|
32033
32735
|
let lastSentText = "";
|
|
32034
32736
|
let lastSentAt = 0;
|
|
32035
32737
|
let sent = 0;
|
|
32036
32738
|
const warn = (event, error) => console.warn({ event, inputMessageId, error: error instanceof Error ? error.message : String(error) });
|
|
32037
|
-
const push = (text, done) => send.call(
|
|
32739
|
+
const push = (text, done, reason) => send.call(
|
|
32740
|
+
adapter,
|
|
32741
|
+
replyTarget,
|
|
32742
|
+
reason ? { text, done, reason } : { text, done },
|
|
32743
|
+
installation
|
|
32744
|
+
).catch((error) => warn("dispatch:stream:failed", error));
|
|
32038
32745
|
const placeholder = streamPlaceholderFor(installation);
|
|
32746
|
+
const closeWith = async (reason) => {
|
|
32747
|
+
if (state.finished) return;
|
|
32748
|
+
state.finished = true;
|
|
32749
|
+
const text = accumulated || (reason === "completed" ? "" : streamFailureTextFor(installation) || placeholder);
|
|
32750
|
+
await push(text, true, reason);
|
|
32751
|
+
};
|
|
32752
|
+
const timer = setTimeout(() => {
|
|
32753
|
+
void closeWith("timeout");
|
|
32754
|
+
}, _MessageRouter.STREAM_TIMEOUT_MS);
|
|
32755
|
+
timer.unref?.();
|
|
32039
32756
|
try {
|
|
32040
32757
|
if (placeholder) await push(placeholder, false);
|
|
32041
32758
|
const stream = agent.chunkStream(inputMessageId, []);
|
|
32042
32759
|
for await (const chunk of stream) {
|
|
32760
|
+
if (state.finished) break;
|
|
32043
32761
|
if (!started) {
|
|
32044
32762
|
if (chunk?.type === import_protocols33.MessageChunkTypes.HUMAN && chunk?.data?.id === inputMessageId) {
|
|
32045
32763
|
started = true;
|
|
@@ -32047,12 +32765,19 @@ var _MessageRouter = class _MessageRouter {
|
|
|
32047
32765
|
continue;
|
|
32048
32766
|
}
|
|
32049
32767
|
if (chunk?.type === import_protocols33.MessageChunkTypes.MESSAGE_COMPLETED || chunk?.type === import_protocols33.MessageChunkTypes.MESSAGE_FAILED || chunk?.type === import_protocols33.MessageChunkTypes.INTERRUPT) {
|
|
32050
|
-
if (chunk.type
|
|
32051
|
-
|
|
32052
|
-
|
|
32053
|
-
|
|
32054
|
-
|
|
32055
|
-
|
|
32768
|
+
if (chunk.type === import_protocols33.MessageChunkTypes.MESSAGE_COMPLETED) {
|
|
32769
|
+
normalEnd = true;
|
|
32770
|
+
const grace = setTimeout(
|
|
32771
|
+
() => {
|
|
32772
|
+
void closeWith("completed");
|
|
32773
|
+
},
|
|
32774
|
+
_MessageRouter.COMPLETION_GRACE_MS
|
|
32775
|
+
);
|
|
32776
|
+
grace.unref?.();
|
|
32777
|
+
} else if (chunk.type === import_protocols33.MessageChunkTypes.MESSAGE_FAILED) {
|
|
32778
|
+
await closeWith("failed");
|
|
32779
|
+
} else {
|
|
32780
|
+
await closeWith("interrupted");
|
|
32056
32781
|
}
|
|
32057
32782
|
break;
|
|
32058
32783
|
}
|
|
@@ -32072,7 +32797,11 @@ var _MessageRouter = class _MessageRouter {
|
|
|
32072
32797
|
}
|
|
32073
32798
|
} catch (error) {
|
|
32074
32799
|
warn("dispatch:stream:error", error);
|
|
32800
|
+
await closeWith("failed");
|
|
32801
|
+
} finally {
|
|
32802
|
+
clearTimeout(timer);
|
|
32075
32803
|
}
|
|
32804
|
+
if (!normalEnd) await closeWith("failed");
|
|
32076
32805
|
}
|
|
32077
32806
|
/**
|
|
32078
32807
|
* Projects a pending HITL interrupt into the room as an independent bot message.
|
|
@@ -32097,15 +32826,30 @@ var _MessageRouter = class _MessageRouter {
|
|
|
32097
32826
|
}
|
|
32098
32827
|
}
|
|
32099
32828
|
};
|
|
32100
|
-
/**
|
|
32101
|
-
|
|
32102
|
-
|
|
32829
|
+
/**
|
|
32830
|
+
* 流式中途刷新的节流间隔与上限。
|
|
32831
|
+
*
|
|
32832
|
+
* 企业微信单会话限制 30 条/分钟(含占位、收尾和卡片)。2500ms 约 24 次
|
|
32833
|
+
* 刷新/分钟,再加最多 3 条生命周期消息仍留有余量。
|
|
32834
|
+
*/
|
|
32835
|
+
_MessageRouter.STREAM_CHUNK_INTERVAL_MS = 2500;
|
|
32836
|
+
_MessageRouter.MAX_STREAM_CHUNKS = 190;
|
|
32837
|
+
/** 流式回复的硬超时:企微要求 10 分钟内 `finish=true`,留 2 分钟余量。 */
|
|
32838
|
+
_MessageRouter.STREAM_TIMEOUT_MS = 8 * 6e4;
|
|
32839
|
+
/**
|
|
32840
|
+
* `MESSAGE_COMPLETED` 后等待 `reply:ready` 的宽限。
|
|
32841
|
+
*
|
|
32842
|
+
* 正常完成通常由 `reply:ready` 用权威全文收尾;但最终 AI 消息为空时
|
|
32843
|
+
* (例如模型只调用了 `wecom_card`、没有产出文字)不会触发 `reply:ready`,
|
|
32844
|
+
* 这里兜底自行收尾,避免流挂住、卡片丢失。
|
|
32845
|
+
*/
|
|
32846
|
+
_MessageRouter.COMPLETION_GRACE_MS = 3e3;
|
|
32103
32847
|
var MessageRouter = _MessageRouter;
|
|
32104
32848
|
|
|
32105
32849
|
// src/channels/room/RoomChannelAdapter.ts
|
|
32106
|
-
var
|
|
32850
|
+
var import_zod19 = require("zod");
|
|
32107
32851
|
var import_protocols34 = require("@axiom-lattice/protocols");
|
|
32108
|
-
var roomConfigSchema =
|
|
32852
|
+
var roomConfigSchema = import_zod19.z.object({}).strict();
|
|
32109
32853
|
function createRoomChannelAdapter(writer) {
|
|
32110
32854
|
return {
|
|
32111
32855
|
channel: "room",
|
|
@@ -32202,7 +32946,7 @@ function createChannelInfrastructure(deps) {
|
|
|
32202
32946
|
onMessageCommitted: deps.onMessageCommitted ?? (deps.realtime ? (message) => deps.realtime?.messageCreated(message) : void 0),
|
|
32203
32947
|
onCallbackFailure: (event) => deps.warn("project-room:message-commit-callback-failed", event)
|
|
32204
32948
|
};
|
|
32205
|
-
deps.adapterRegistry.register(createRoomChannelAdapter(new
|
|
32949
|
+
deps.adapterRegistry.register(createRoomChannelAdapter(new import_core74.RoomAgentMessageService(writerDeps)));
|
|
32206
32950
|
} catch (error) {
|
|
32207
32951
|
deps.warn("Room channel unavailable", { error: error instanceof Error ? error.message : String(error) });
|
|
32208
32952
|
}
|
|
@@ -32226,11 +32970,11 @@ async function prepareProjectTaskRuntime(runtime, log2) {
|
|
|
32226
32970
|
}
|
|
32227
32971
|
|
|
32228
32972
|
// src/services/plugins/PluginDeploymentRuntimeStartup.ts
|
|
32229
|
-
var
|
|
32973
|
+
var import_core77 = require("@axiom-lattice/core");
|
|
32230
32974
|
|
|
32231
32975
|
// src/services/plugins/PluginDeploymentService.ts
|
|
32232
32976
|
var import_node_crypto30 = require("crypto");
|
|
32233
|
-
var
|
|
32977
|
+
var import_core76 = require("@axiom-lattice/core");
|
|
32234
32978
|
|
|
32235
32979
|
// src/services/plugins/pluginDeploymentNaming.ts
|
|
32236
32980
|
var import_node_crypto29 = require("crypto");
|
|
@@ -32248,7 +32992,7 @@ function pluginSandboxName(tenantId, pluginType) {
|
|
|
32248
32992
|
}
|
|
32249
32993
|
|
|
32250
32994
|
// src/services/plugins/PluginDeploymentService.ts
|
|
32251
|
-
var PLUGIN_HOST_SERVER_PATH = `${
|
|
32995
|
+
var PLUGIN_HOST_SERVER_PATH = `${import_core76.PLUGIN_HOST_DIR}/server.js`;
|
|
32252
32996
|
var DEFAULT_PLUGIN_IDLE_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
32253
32997
|
var DEFAULT_PLUGIN_HEALTH_TIMEOUT_MS = 3e4;
|
|
32254
32998
|
var DEFAULT_PLUGIN_HEALTH_POLL_INTERVAL_MS = 500;
|
|
@@ -32267,7 +33011,7 @@ var PluginDeploymentError = class extends Error {
|
|
|
32267
33011
|
this.code = code;
|
|
32268
33012
|
}
|
|
32269
33013
|
};
|
|
32270
|
-
function
|
|
33014
|
+
function isRecord5(value) {
|
|
32271
33015
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32272
33016
|
}
|
|
32273
33017
|
function buildBootstrapEntrypoint(pluginType) {
|
|
@@ -32287,7 +33031,7 @@ var PluginDeploymentService = class {
|
|
|
32287
33031
|
this.catalog = deps.catalog;
|
|
32288
33032
|
this.installPluginHost = deps.installPluginHost;
|
|
32289
33033
|
this.lease = deps.lease;
|
|
32290
|
-
this.registry = deps.registry ?? new
|
|
33034
|
+
this.registry = deps.registry ?? new import_core76.PluginDeploymentRuntimeRegistry({ now: deps.clock ?? Date.now });
|
|
32291
33035
|
this.now = deps.clock ?? Date.now;
|
|
32292
33036
|
this.logger = deps.logger ?? { info: () => void 0 };
|
|
32293
33037
|
this.limits = deps.limits ?? {};
|
|
@@ -32821,7 +33565,7 @@ var PluginDeploymentService = class {
|
|
|
32821
33565
|
return { ok: false, error: `health responded with HTTP ${response.status}` };
|
|
32822
33566
|
}
|
|
32823
33567
|
const body = await response.json().catch(() => void 0);
|
|
32824
|
-
if (
|
|
33568
|
+
if (isRecord5(body) && body.ok === true) {
|
|
32825
33569
|
return { ok: true };
|
|
32826
33570
|
}
|
|
32827
33571
|
return { ok: false, error: "health returned an invalid envelope" };
|
|
@@ -33004,7 +33748,7 @@ function startPluginDeploymentRuntime(options) {
|
|
|
33004
33748
|
);
|
|
33005
33749
|
return { reconcile: Promise.resolve(), dispose: async () => void 0 };
|
|
33006
33750
|
}
|
|
33007
|
-
const register = options.register ?? ((service3) => (0,
|
|
33751
|
+
const register = options.register ?? ((service3) => (0, import_core77.setPluginDeploymentService)(service3));
|
|
33008
33752
|
const setIntervalFn = options.setIntervalFn ?? setInterval;
|
|
33009
33753
|
const clearIntervalFn = options.clearIntervalFn ?? clearInterval;
|
|
33010
33754
|
const watchdogIntervalMs = options.watchdogIntervalMs ?? DEFAULT_PLUGIN_WATCHDOG_INTERVAL_MS;
|
|
@@ -33287,11 +34031,11 @@ var DEFAULT_LOGGER_CONFIG = {
|
|
|
33287
34031
|
var loggerLattice = initializeLogger(DEFAULT_LOGGER_CONFIG);
|
|
33288
34032
|
var logger8 = loggerLattice.client;
|
|
33289
34033
|
function initializeLogger(config) {
|
|
33290
|
-
if (
|
|
33291
|
-
|
|
34034
|
+
if (import_core100.loggerLatticeManager.hasLattice("default")) {
|
|
34035
|
+
import_core100.loggerLatticeManager.removeLattice("default");
|
|
33292
34036
|
}
|
|
33293
|
-
(0,
|
|
33294
|
-
return (0,
|
|
34037
|
+
(0, import_core100.registerLoggerLattice)("default", config);
|
|
34038
|
+
return (0, import_core100.getLoggerLattice)("default");
|
|
33295
34039
|
}
|
|
33296
34040
|
var app = (0, import_fastify.default)({
|
|
33297
34041
|
logger: false,
|
|
@@ -33389,7 +34133,7 @@ app.setErrorHandler((error, request, reply) => {
|
|
|
33389
34133
|
var shutdownHandlersInstalled = false;
|
|
33390
34134
|
function getConfiguredSandboxProvider() {
|
|
33391
34135
|
const sandboxProviderType = process.env.SANDBOX_PROVIDER_TYPE || "microsandbox-remote";
|
|
33392
|
-
return (0,
|
|
34136
|
+
return (0, import_core100.createSandboxProvider)({
|
|
33393
34137
|
type: sandboxProviderType,
|
|
33394
34138
|
remoteBaseURL: process.env.SANDBOX_BASE_URL,
|
|
33395
34139
|
microsandboxServiceBaseURL: process.env.MICROSANDBOX_SERVICE_BASE_URL,
|
|
@@ -33405,7 +34149,7 @@ function getConfiguredSandboxProvider() {
|
|
|
33405
34149
|
}
|
|
33406
34150
|
async function restoreMcpConnections() {
|
|
33407
34151
|
try {
|
|
33408
|
-
const storeLattice = (0,
|
|
34152
|
+
const storeLattice = (0, import_core100.getStoreLattice)("default", "mcp");
|
|
33409
34153
|
const store2 = storeLattice.store;
|
|
33410
34154
|
if (!store2) {
|
|
33411
34155
|
logger8.info("MCP store not configured, skipping connection restoration");
|
|
@@ -33418,8 +34162,8 @@ async function restoreMcpConnections() {
|
|
|
33418
34162
|
logger8.info(`Restoring ${configs.length} MCP server connections...`);
|
|
33419
34163
|
const deps = {
|
|
33420
34164
|
store: store2,
|
|
33421
|
-
manager:
|
|
33422
|
-
convertToConnection:
|
|
34165
|
+
manager: import_core100.mcpManager,
|
|
34166
|
+
convertToConnection: import_core100.convertToConnection
|
|
33423
34167
|
};
|
|
33424
34168
|
const results = await Promise.allSettled(
|
|
33425
34169
|
configs.map(
|
|
@@ -33460,9 +34204,9 @@ var start = async (config) => {
|
|
|
33460
34204
|
let projectRoomRealtimeRuntime;
|
|
33461
34205
|
if (projectRoomRealtimeMode === "single-gateway") {
|
|
33462
34206
|
projectRoomRealtimeRuntime = createProjectRoomRealtimeRuntime({
|
|
33463
|
-
tasks: (0,
|
|
33464
|
-
rooms: (0,
|
|
33465
|
-
memberships: (0,
|
|
34207
|
+
tasks: (0, import_core100.getStoreLattice)("default", "task").store,
|
|
34208
|
+
rooms: (0, import_core100.getStoreLattice)("default", "projectRoom").store,
|
|
34209
|
+
memberships: (0, import_core100.getStoreLattice)("default", "projectBotMembership").store,
|
|
33466
34210
|
log: { warn: (message, context) => logger8.warn(message, context) }
|
|
33467
34211
|
});
|
|
33468
34212
|
}
|
|
@@ -33470,13 +34214,14 @@ var start = async (config) => {
|
|
|
33470
34214
|
const adapterRegistry = new ChannelAdapterRegistry();
|
|
33471
34215
|
adapterRegistry.register(larkChannelAdapter);
|
|
33472
34216
|
adapterRegistry.register(wecomChannelAdapter);
|
|
34217
|
+
registerWecomCardTool();
|
|
33473
34218
|
const { wechatChannelAdapter: wechatChannelAdapter2 } = await Promise.resolve().then(() => (init_WechatChannelAdapter(), WechatChannelAdapter_exports));
|
|
33474
34219
|
adapterRegistry.register(wechatChannelAdapter2);
|
|
33475
34220
|
try {
|
|
33476
34221
|
const infrastructure = createChannelInfrastructure({
|
|
33477
34222
|
adapterRegistry,
|
|
33478
|
-
getStore: ((kind) => (0,
|
|
33479
|
-
trustedDispatcher: (0,
|
|
34223
|
+
getStore: ((kind) => (0, import_core100.getStoreLattice)("default", kind).store),
|
|
34224
|
+
trustedDispatcher: (0, import_core100.createTrustedAgentMessageDispatcher)((scope) => import_core100.agentInstanceManager.getAgent(scope)),
|
|
33480
34225
|
middlewares: [
|
|
33481
34226
|
createDeduplicationMiddleware(),
|
|
33482
34227
|
createRateLimitMiddleware(),
|
|
@@ -33487,7 +34232,7 @@ var start = async (config) => {
|
|
|
33487
34232
|
});
|
|
33488
34233
|
const bindingStore = infrastructure.bindingRegistry;
|
|
33489
34234
|
const installationStore = infrastructure.installationStore;
|
|
33490
|
-
(0,
|
|
34235
|
+
(0, import_core99.setBindingRegistry)(bindingStore);
|
|
33491
34236
|
const router = infrastructure.router;
|
|
33492
34237
|
app.addHook("onClose", async () => router.dispose());
|
|
33493
34238
|
channelDeps = {
|
|
@@ -33503,10 +34248,10 @@ var start = async (config) => {
|
|
|
33503
34248
|
error: err instanceof Error ? err.message : String(err)
|
|
33504
34249
|
});
|
|
33505
34250
|
}
|
|
33506
|
-
(0,
|
|
34251
|
+
(0, import_core99.setEvalRunService)(evalRunner);
|
|
33507
34252
|
try {
|
|
33508
|
-
const menuStore = (0,
|
|
33509
|
-
(0,
|
|
34253
|
+
const menuStore = (0, import_core100.getStoreLattice)("default", "menu").store;
|
|
34254
|
+
(0, import_core99.setMenuRegistry)(menuStore);
|
|
33510
34255
|
logger8.info("Menu registry initialized");
|
|
33511
34256
|
} catch {
|
|
33512
34257
|
}
|
|
@@ -33523,10 +34268,10 @@ var start = async (config) => {
|
|
|
33523
34268
|
const { A2AAuthService: A2AAuthService2, parseEnvKeys: parseEnvKeys2 } = await Promise.resolve().then(() => (init_A2AAuthService(), A2AAuthService_exports));
|
|
33524
34269
|
const { registerA2AStandardRoutes: registerA2AStandardRoutes2 } = await Promise.resolve().then(() => (init_a2a_standard(), a2a_standard_exports));
|
|
33525
34270
|
const a2a = await Promise.resolve().then(() => (init_a2a(), a2a_exports));
|
|
33526
|
-
const a2aKeyStore = (0,
|
|
33527
|
-
const assistantStore = (0,
|
|
33528
|
-
const projectStore = (0,
|
|
33529
|
-
const taskStore = (0,
|
|
34271
|
+
const a2aKeyStore = (0, import_core100.getStoreLattice)("default", "a2aApiKey").store;
|
|
34272
|
+
const assistantStore = (0, import_core100.getStoreLattice)("default", "assistant").store;
|
|
34273
|
+
const projectStore = (0, import_core100.getStoreLattice)("default", "project").store;
|
|
34274
|
+
const taskStore = (0, import_core100.getStoreLattice)("default", "task").store;
|
|
33530
34275
|
const authService = new A2AAuthService2({
|
|
33531
34276
|
keyStore: a2aKeyStore,
|
|
33532
34277
|
assistantStore,
|
|
@@ -33566,8 +34311,8 @@ var start = async (config) => {
|
|
|
33566
34311
|
const { CollectionService: CollectionService2 } = await Promise.resolve().then(() => (init_collection_service(), collection_service_exports));
|
|
33567
34312
|
openLattice2.register(createKbProvider2(new CollectionService2()));
|
|
33568
34313
|
openLattice2.register(createOpenSandboxProvider2());
|
|
33569
|
-
const threadStore = (0,
|
|
33570
|
-
const assistantStore = (0,
|
|
34314
|
+
const threadStore = (0, import_core100.getStoreLattice)("default", "thread").store;
|
|
34315
|
+
const assistantStore = (0, import_core100.getStoreLattice)("default", "assistant").store;
|
|
33571
34316
|
openLattice2.register(
|
|
33572
34317
|
createAgentProvider2({
|
|
33573
34318
|
threadStore,
|
|
@@ -33612,15 +34357,15 @@ var start = async (config) => {
|
|
|
33612
34357
|
error: err instanceof Error ? err.message : String(err)
|
|
33613
34358
|
});
|
|
33614
34359
|
}
|
|
33615
|
-
if (!
|
|
33616
|
-
|
|
34360
|
+
if (!import_core100.sandboxLatticeManager.hasLattice("default")) {
|
|
34361
|
+
import_core100.sandboxLatticeManager.registerLattice("default", getConfiguredSandboxProvider());
|
|
33617
34362
|
logger8.info("Registered sandbox manager from env configuration");
|
|
33618
34363
|
}
|
|
33619
34364
|
if (isPluginDeploymentRuntimeEnabled()) {
|
|
33620
34365
|
try {
|
|
33621
|
-
const pluginDeploymentStore = (0,
|
|
33622
|
-
const tenantStore = (0,
|
|
33623
|
-
const leaseStore2 = (0,
|
|
34366
|
+
const pluginDeploymentStore = (0, import_core100.getStoreLattice)("default", "pluginDeployment").store;
|
|
34367
|
+
const tenantStore = (0, import_core100.getStoreLattice)("default", "tenant").store;
|
|
34368
|
+
const leaseStore2 = (0, import_core100.getStoreLattice)("default", "lease").store;
|
|
33624
34369
|
const listAllDeployments = async () => {
|
|
33625
34370
|
const tenants = await tenantStore.getAllTenants();
|
|
33626
34371
|
const lists = await Promise.all(
|
|
@@ -33633,9 +34378,9 @@ var start = async (config) => {
|
|
|
33633
34378
|
const pluginDeploymentRuntime = startPluginDeploymentRuntime({
|
|
33634
34379
|
wiring: {
|
|
33635
34380
|
store: pluginDeploymentStore,
|
|
33636
|
-
sandboxManager: (0,
|
|
33637
|
-
catalog: (0,
|
|
33638
|
-
installPluginHost:
|
|
34381
|
+
sandboxManager: (0, import_core100.getSandBoxManager)(),
|
|
34382
|
+
catalog: (0, import_core100.getSandboxPluginCatalog)(),
|
|
34383
|
+
installPluginHost: import_core100.installPluginHost,
|
|
33639
34384
|
limits: readPluginDeploymentLimits(),
|
|
33640
34385
|
serviceKey: process.env.MICROSANDBOX_API_KEY,
|
|
33641
34386
|
listAllDeployments,
|
|
@@ -33647,7 +34392,7 @@ var start = async (config) => {
|
|
|
33647
34392
|
}
|
|
33648
34393
|
},
|
|
33649
34394
|
lease: leaseStore2,
|
|
33650
|
-
holder: (0,
|
|
34395
|
+
holder: (0, import_core100.getReplicaId)(),
|
|
33651
34396
|
logger: logger8
|
|
33652
34397
|
});
|
|
33653
34398
|
app.addHook("onClose", async () => {
|
|
@@ -33662,11 +34407,11 @@ var start = async (config) => {
|
|
|
33662
34407
|
}
|
|
33663
34408
|
try {
|
|
33664
34409
|
const { ResourceController: ResourceController2 } = await Promise.resolve().then(() => (init_resources(), resources_exports));
|
|
33665
|
-
const sharedResourceStore = (0,
|
|
33666
|
-
const cache2 = new
|
|
34410
|
+
const sharedResourceStore = (0, import_core100.getStoreLattice)("default", "sharedResource").store;
|
|
34411
|
+
const cache2 = new import_core100.TokenCache();
|
|
33667
34412
|
const resourceController = new ResourceController2({
|
|
33668
34413
|
store: sharedResourceStore,
|
|
33669
|
-
sandboxManager:
|
|
34414
|
+
sandboxManager: import_core100.sandboxLatticeManager,
|
|
33670
34415
|
cache: cache2,
|
|
33671
34416
|
logger: logger8
|
|
33672
34417
|
});
|
|
@@ -33679,13 +34424,13 @@ var start = async (config) => {
|
|
|
33679
34424
|
}
|
|
33680
34425
|
if (channelDeps && process.env.CHANNELS_ENABLED !== "false") {
|
|
33681
34426
|
try {
|
|
33682
|
-
const channelLeader = new
|
|
33683
|
-
leaseStore: (0,
|
|
33684
|
-
owner: (0,
|
|
33685
|
-
connect: () => (0,
|
|
34427
|
+
const channelLeader = new import_core100.ChannelConnectionLeader({
|
|
34428
|
+
leaseStore: (0, import_core100.getStoreLattice)("default", "lease").store,
|
|
34429
|
+
owner: (0, import_core100.getReplicaId)(),
|
|
34430
|
+
connect: () => (0, import_core100.connectAllChannels)((channel) => adapterRegistry.get(channel), {
|
|
33686
34431
|
deps: { router: channelDeps.router }
|
|
33687
34432
|
}),
|
|
33688
|
-
disconnect: () => (0,
|
|
34433
|
+
disconnect: () => (0, import_core100.disconnectAllChannels)((channel) => adapterRegistry.get(channel)),
|
|
33689
34434
|
log: { warn: (message, context) => logger8.warn(message, context) }
|
|
33690
34435
|
});
|
|
33691
34436
|
app.addHook("onClose", async () => {
|
|
@@ -33699,45 +34444,52 @@ var start = async (config) => {
|
|
|
33699
34444
|
}
|
|
33700
34445
|
}
|
|
33701
34446
|
const target_port = config?.port || Number(process.env.PORT) || 4001;
|
|
33702
|
-
(0,
|
|
33703
|
-
const outboxStore = (0,
|
|
33704
|
-
|
|
33705
|
-
|
|
33706
|
-
(0,
|
|
34447
|
+
(0, import_core100.configureCoordinationLeaseStore)((0, import_core100.getStoreLattice)("default", "lease").store);
|
|
34448
|
+
const outboxStore = (0, import_core100.getStoreLattice)("default", "outbox").store;
|
|
34449
|
+
import_core100.taskLifecycleNotifier.setOutbox(outboxStore);
|
|
34450
|
+
import_core100.projectTaskAdmissionNotifier.setOutbox(outboxStore);
|
|
34451
|
+
(0, import_core100.configurePluginCatalogSync)({ outbox: outboxStore, owner: (0, import_core100.getReplicaId)() });
|
|
34452
|
+
(0, import_core100.configureCollectionSync)({ outbox: outboxStore, owner: (0, import_core100.getReplicaId)() });
|
|
33707
34453
|
bridgeAssistantEvents(
|
|
33708
|
-
(event, cb) =>
|
|
34454
|
+
(event, cb) => import_core100.eventBus.subscribe(event, cb),
|
|
33709
34455
|
outboxStore,
|
|
33710
|
-
(0,
|
|
34456
|
+
(0, import_core100.getReplicaId)()
|
|
33711
34457
|
);
|
|
33712
34458
|
if (projectRoomRealtimeRuntime) {
|
|
33713
34459
|
projectRoomRealtimeRuntime.broker.setBroadcastHook((scope, serialized, sourceKey) => {
|
|
33714
|
-
void publishRoomEvent(outboxStore, (0,
|
|
34460
|
+
void publishRoomEvent(outboxStore, (0, import_core100.getReplicaId)(), scope, serialized, sourceKey);
|
|
33715
34461
|
});
|
|
33716
34462
|
}
|
|
33717
|
-
const outboxPoller = new
|
|
34463
|
+
const outboxPoller = new import_core100.OutboxPoller({
|
|
33718
34464
|
store: outboxStore,
|
|
33719
|
-
owner: (0,
|
|
34465
|
+
owner: (0, import_core100.getReplicaId)(),
|
|
33720
34466
|
handlers: {
|
|
33721
|
-
"task-lifecycle": (payload) =>
|
|
33722
|
-
"project-task-admission": (payload) =>
|
|
34467
|
+
"task-lifecycle": (payload) => import_core100.taskLifecycleNotifier.deliverFromOutbox(payload),
|
|
34468
|
+
"project-task-admission": (payload) => import_core100.projectTaskAdmissionNotifier.deliverFromOutbox(payload),
|
|
33723
34469
|
[ROOM_EVENT_TOPIC]: async (payload) => {
|
|
33724
34470
|
if (projectRoomRealtimeRuntime) ingestRoomEvent(payload, projectRoomRealtimeRuntime.broker);
|
|
33725
34471
|
},
|
|
33726
34472
|
"assistant-changed": (payload) => handleAssistantChanged(payload, async (tenantId) => {
|
|
33727
|
-
await
|
|
34473
|
+
await import_core100.agentLatticeManager.initializeStoredAssistantsForTenant(tenantId);
|
|
33728
34474
|
invalidateAgentReflectionCache(tenantId);
|
|
33729
34475
|
invalidatePluginReflectionCache(tenantId);
|
|
33730
34476
|
}),
|
|
33731
34477
|
[A2A_KEY_CHANGED_TOPIC]: (payload) => handleA2AKeyChanged(payload, () => refreshStoreKeyMap()),
|
|
33732
34478
|
[MCP_CONFIG_CHANGED_TOPIC]: (payload) => reconcileMcpConfigChange(payload, {
|
|
33733
|
-
store: (0,
|
|
33734
|
-
manager:
|
|
33735
|
-
convertToConnection:
|
|
34479
|
+
store: (0, import_core100.getStoreLattice)("default", "mcp").store,
|
|
34480
|
+
manager: import_core100.mcpManager,
|
|
34481
|
+
convertToConnection: import_core100.convertToConnection
|
|
33736
34482
|
}),
|
|
33737
|
-
[
|
|
34483
|
+
[import_core100.COLLECTION_CHANGED_TOPIC]: async (payload) => {
|
|
34484
|
+
const tenantId = payload?.tenantId;
|
|
34485
|
+
if (typeof tenantId === "string" && tenantId.length > 0) {
|
|
34486
|
+
import_core100.vectorStoreLatticeManager.clearTenantVectorStores(tenantId);
|
|
34487
|
+
}
|
|
34488
|
+
},
|
|
34489
|
+
[import_core100.PLUGIN_CATALOG_CHANGED_TOPIC]: async (payload) => {
|
|
33738
34490
|
const tenantId = payload?.tenantId;
|
|
33739
34491
|
if (typeof tenantId === "string" && tenantId.length > 0) {
|
|
33740
|
-
(0,
|
|
34492
|
+
(0, import_core100.getSandboxPluginCatalog)().invalidate(tenantId);
|
|
33741
34493
|
invalidatePluginReflectionCache(tenantId);
|
|
33742
34494
|
invalidateAgentReflectionCache(tenantId);
|
|
33743
34495
|
await getMcpUiResourceResolver()?.invalidateTenantPlugins(tenantId);
|
|
@@ -33756,7 +34508,7 @@ var start = async (config) => {
|
|
|
33756
34508
|
} catch (err) {
|
|
33757
34509
|
logger8.warn("Outbox poller failed to start", { error: err instanceof Error ? err.message : String(err) });
|
|
33758
34510
|
}
|
|
33759
|
-
const leaseStore = (0,
|
|
34511
|
+
const leaseStore = (0, import_core100.getStoreLattice)("default", "lease").store;
|
|
33760
34512
|
if (leaseStore.constructor?.name === "InMemoryLeaseStore") {
|
|
33761
34513
|
logger8.warn(
|
|
33762
34514
|
"Startup recovery leader gate uses a non-distributed lease store (per-process only); configure a shared 'lease' store for multi-replica deployments",
|
|
@@ -33764,7 +34516,7 @@ var start = async (config) => {
|
|
|
33764
34516
|
);
|
|
33765
34517
|
}
|
|
33766
34518
|
warnMultiReplicaReadiness(logger8);
|
|
33767
|
-
const startup = await (0,
|
|
34519
|
+
const startup = await (0, import_core100.runAsLeader)(leaseStore, "startup-recovery", async () => {
|
|
33768
34520
|
if (routes.projectTaskRuntime) {
|
|
33769
34521
|
await prepareProjectTaskRuntime(routes.projectTaskRuntime, logger8);
|
|
33770
34522
|
}
|
|
@@ -33773,9 +34525,9 @@ var start = async (config) => {
|
|
|
33773
34525
|
const { createOrphanRecoveryRuntime: createOrphanRecoveryRuntime2 } = await Promise.resolve().then(() => (init_OrphanRecoveryRuntime(), OrphanRecoveryRuntime_exports));
|
|
33774
34526
|
const { createRecoveryCallerDeps: createRecoveryCallerDeps2 } = await Promise.resolve().then(() => (init_RecoveryCallerDeps(), RecoveryCallerDeps_exports));
|
|
33775
34527
|
const runtime = createOrphanRecoveryRuntime2({
|
|
33776
|
-
taskStore: (0,
|
|
33777
|
-
workItemStore: (0,
|
|
33778
|
-
tenantStore: (0,
|
|
34528
|
+
taskStore: (0, import_core100.getStoreLattice)("default", "task").store,
|
|
34529
|
+
workItemStore: (0, import_core100.getStoreLattice)("default", "taskWorkItem").store,
|
|
34530
|
+
tenantStore: (0, import_core100.getStoreLattice)("default", "tenant").store,
|
|
33779
34531
|
...createRecoveryCallerDeps2(),
|
|
33780
34532
|
log: logger8
|
|
33781
34533
|
});
|
|
@@ -33784,9 +34536,9 @@ var start = async (config) => {
|
|
|
33784
34536
|
logger8.warn("Task orphan recovery failed", { error: err instanceof Error ? err.message : String(err) });
|
|
33785
34537
|
}
|
|
33786
34538
|
}
|
|
33787
|
-
if (
|
|
34539
|
+
if (import_core100.scheduleLatticeManager.hasLattice("default")) {
|
|
33788
34540
|
try {
|
|
33789
|
-
const restored = await
|
|
34541
|
+
const restored = await import_core100.scheduleLatticeManager.getScheduleLattice("default").restore();
|
|
33790
34542
|
logger8.info("Scheduled tasks restored", { phase: "startup_recovery", restored });
|
|
33791
34543
|
} catch (err) {
|
|
33792
34544
|
logger8.warn("Scheduled task restore failed", {
|
|
@@ -33829,7 +34581,7 @@ var start = async (config) => {
|
|
|
33829
34581
|
steps: [
|
|
33830
34582
|
async () => {
|
|
33831
34583
|
await Promise.all(
|
|
33832
|
-
|
|
34584
|
+
import_core100.agentInstanceManager.getAllAgents().map((agent) => agent.abort().catch(() => void 0))
|
|
33833
34585
|
);
|
|
33834
34586
|
},
|
|
33835
34587
|
() => agentTaskConsumer?.stopPollingQueue(),
|