@axiom-lattice/core 4.4.0 → 6.0.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/index.d.mts +74 -43
- package/dist/index.d.ts +74 -43
- package/dist/index.js +550 -2077
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +537 -2062
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1811,7 +1811,6 @@ __export(index_exports, {
|
|
|
1811
1811
|
createSandboxProvider: () => createSandboxProvider,
|
|
1812
1812
|
createSandboxResolver: () => createSandboxResolver,
|
|
1813
1813
|
createSchedulerMiddleware: () => createSchedulerMiddleware,
|
|
1814
|
-
createSemanticMetricsMiddleware: () => createSemanticMetricsMiddleware,
|
|
1815
1814
|
createSharePayload: () => createSharePayload,
|
|
1816
1815
|
createTaskExecutionService: () => createTaskExecutionService,
|
|
1817
1816
|
createTaskLifecycleService: () => createTaskLifecycleService,
|
|
@@ -1895,6 +1894,7 @@ __export(index_exports, {
|
|
|
1895
1894
|
invokeWithRetry: () => invokeWithRetry,
|
|
1896
1895
|
isBuiltInSkill: () => isBuiltInSkill,
|
|
1897
1896
|
isDirectRoom: () => isDirectRoom,
|
|
1897
|
+
isMcpConnectionError: () => isMcpConnectionError,
|
|
1898
1898
|
isPluginSkillAuthorizedInSandbox: () => isPluginSkillAuthorizedInSandbox,
|
|
1899
1899
|
isPluginSkillManagedInSandbox: () => isPluginSkillManagedInSandbox,
|
|
1900
1900
|
isUsingDefaultKey: () => isUsingDefaultKey,
|
|
@@ -1917,7 +1917,6 @@ __export(index_exports, {
|
|
|
1917
1917
|
parallelLimit: () => parallelLimit,
|
|
1918
1918
|
parseCronExpression: () => parseCronExpression,
|
|
1919
1919
|
parseDirectRoomType: () => parseDirectRoomType,
|
|
1920
|
-
parseExternalDependency: () => parseExternalDependency,
|
|
1921
1920
|
parseJudgeVerdict: () => parseJudgeVerdict,
|
|
1922
1921
|
parsePackSize: () => parsePackSize,
|
|
1923
1922
|
parseQueuedExecutionMode: () => import_protocols2.parseQueuedExecutionMode,
|
|
@@ -1970,7 +1969,6 @@ __export(index_exports, {
|
|
|
1970
1969
|
sandboxLatticeManager: () => sandboxLatticeManager,
|
|
1971
1970
|
sanitizeToolCallId: () => sanitizeToolCallId,
|
|
1972
1971
|
scheduleLatticeManager: () => scheduleLatticeManager,
|
|
1973
|
-
semanticMetricsPlugin: () => semanticMetricsPlugin,
|
|
1974
1972
|
serializePluginMeta: () => serializePluginMeta,
|
|
1975
1973
|
serializeTaskMutationSuccess: () => serializeTaskMutationSuccess,
|
|
1976
1974
|
serializeTaskNormalizationFallback: () => serializeTaskNormalizationFallback,
|
|
@@ -2424,11 +2422,11 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
2424
2422
|
* @param key Lattice键名
|
|
2425
2423
|
* @param tool 已有的StructuredTool实例
|
|
2426
2424
|
*/
|
|
2427
|
-
registerExistingTool(key5,
|
|
2425
|
+
registerExistingTool(key5, tool68) {
|
|
2428
2426
|
const config = {
|
|
2429
|
-
name:
|
|
2430
|
-
description:
|
|
2431
|
-
schema:
|
|
2427
|
+
name: tool68.name,
|
|
2428
|
+
description: tool68.description,
|
|
2429
|
+
schema: tool68.schema,
|
|
2432
2430
|
// StructuredTool的schema已经是Zod兼容的
|
|
2433
2431
|
needUserApprove: false
|
|
2434
2432
|
// MCP工具默认不需要用户批准
|
|
@@ -2436,7 +2434,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
2436
2434
|
const toolLattice = {
|
|
2437
2435
|
key: key5,
|
|
2438
2436
|
config,
|
|
2439
|
-
client:
|
|
2437
|
+
client: tool68
|
|
2440
2438
|
};
|
|
2441
2439
|
this.register(key5, toolLattice);
|
|
2442
2440
|
}
|
|
@@ -2447,14 +2445,14 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
2447
2445
|
* @param key - tool lattice key (no tenant prefix)
|
|
2448
2446
|
* @param tool - the StructuredTool client
|
|
2449
2447
|
*/
|
|
2450
|
-
registerExistingToolWithTenant(tenantId2, key5,
|
|
2448
|
+
registerExistingToolWithTenant(tenantId2, key5, tool68) {
|
|
2451
2449
|
const config = {
|
|
2452
|
-
name:
|
|
2453
|
-
description:
|
|
2454
|
-
schema:
|
|
2450
|
+
name: tool68.name,
|
|
2451
|
+
description: tool68.description,
|
|
2452
|
+
schema: tool68.schema,
|
|
2455
2453
|
needUserApprove: false
|
|
2456
2454
|
};
|
|
2457
|
-
const toolLattice = { key: key5, config, client:
|
|
2455
|
+
const toolLattice = { key: key5, config, client: tool68 };
|
|
2458
2456
|
this.registerWithTenant(tenantId2, key5, toolLattice);
|
|
2459
2457
|
}
|
|
2460
2458
|
/**
|
|
@@ -2504,8 +2502,8 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
2504
2502
|
};
|
|
2505
2503
|
var toolLatticeManager = ToolLatticeManager.getInstance();
|
|
2506
2504
|
var registerToolLattice = (key5, config, executor) => toolLatticeManager.registerLattice(key5, config, executor);
|
|
2507
|
-
var registerExistingTool = (key5,
|
|
2508
|
-
var registerExistingToolWithTenant = (tenantId2, key5,
|
|
2505
|
+
var registerExistingTool = (key5, tool68) => toolLatticeManager.registerExistingTool(key5, tool68);
|
|
2506
|
+
var registerExistingToolWithTenant = (tenantId2, key5, tool68) => toolLatticeManager.registerExistingToolWithTenant(tenantId2, key5, tool68);
|
|
2509
2507
|
var getToolLattice = (key5) => toolLatticeManager.getToolLattice(key5);
|
|
2510
2508
|
var getToolClientWithTenant = (tenantId2, key5) => toolLatticeManager.getToolClientWithTenant(tenantId2, key5);
|
|
2511
2509
|
var getToolDefinition = (key5) => toolLatticeManager.getToolDefinition(key5);
|
|
@@ -3345,15 +3343,15 @@ ${body}` : `${frontmatter}
|
|
|
3345
3343
|
const resourcesDir = path.join(skillDir, "resources");
|
|
3346
3344
|
try {
|
|
3347
3345
|
const entries = await fs.readdir(resourcesDir, { withFileTypes: true, recursive: true });
|
|
3348
|
-
const
|
|
3346
|
+
const resources2 = [];
|
|
3349
3347
|
for (const entry of entries) {
|
|
3350
3348
|
if (!entry.isDirectory()) {
|
|
3351
3349
|
const fullPath = path.join(entry.path, entry.name);
|
|
3352
3350
|
const relativePath = path.relative(resourcesDir, fullPath);
|
|
3353
|
-
|
|
3351
|
+
resources2.push(relativePath.replace(/\\/g, "/"));
|
|
3354
3352
|
}
|
|
3355
3353
|
}
|
|
3356
|
-
return
|
|
3354
|
+
return resources2.sort();
|
|
3357
3355
|
} catch (error) {
|
|
3358
3356
|
if (error.code === "ENOENT") {
|
|
3359
3357
|
return [];
|
|
@@ -13632,11 +13630,11 @@ var PluginRegistry = class {
|
|
|
13632
13630
|
if (!isRecord2(rawDefinition) || typeof rawDefinition.version !== "string" || rawDefinition.version.trim().length === 0 || typeof rawDefinition.content !== "string") {
|
|
13633
13631
|
throw new Error(`Plugin "${key5}": skill "${name}" version and content must be a string`);
|
|
13634
13632
|
}
|
|
13635
|
-
const
|
|
13636
|
-
if (
|
|
13633
|
+
const resources2 = rawDefinition.resources;
|
|
13634
|
+
if (resources2 !== void 0 && !isRecord2(resources2)) {
|
|
13637
13635
|
throw new Error(`Plugin "${key5}": skill "${name}" resources must be an object`);
|
|
13638
13636
|
}
|
|
13639
|
-
for (const [path8, resource] of Object.entries(
|
|
13637
|
+
for (const [path8, resource] of Object.entries(resources2 ?? {})) {
|
|
13640
13638
|
try {
|
|
13641
13639
|
validateRelativePath(path8, "resource");
|
|
13642
13640
|
} catch {
|
|
@@ -14789,7 +14787,7 @@ function isSafeUiPath(path8) {
|
|
|
14789
14787
|
}
|
|
14790
14788
|
function validateSandboxPluginManifest(args) {
|
|
14791
14789
|
const diagnostics = [];
|
|
14792
|
-
const error = (code, message, pluginType,
|
|
14790
|
+
const error = (code, message, pluginType, tool68) => diagnostics.push({ level: "error", code, message, pluginType, tool: tool68 });
|
|
14793
14791
|
const raw = args.raw;
|
|
14794
14792
|
if (!isRecord5(raw)) {
|
|
14795
14793
|
error("MANIFEST_NOT_OBJECT", "manifest must be a JSON object", args.dirName);
|
|
@@ -15797,9 +15795,9 @@ function freezeMetadata(metadata) {
|
|
|
15797
15795
|
...resourceSelector ? { resourceSelector } : {}
|
|
15798
15796
|
});
|
|
15799
15797
|
}
|
|
15800
|
-
function toolName(
|
|
15801
|
-
if (typeof
|
|
15802
|
-
return typeof
|
|
15798
|
+
function toolName(tool68) {
|
|
15799
|
+
if (typeof tool68 !== "object" || tool68 === null || !("name" in tool68)) return void 0;
|
|
15800
|
+
return typeof tool68.name === "string" ? tool68.name : void 0;
|
|
15803
15801
|
}
|
|
15804
15802
|
function schemaHasConnectionKey(schema6) {
|
|
15805
15803
|
const definition = isRecord7(schema6._def) ? schema6._def : void 0;
|
|
@@ -15807,10 +15805,10 @@ function schemaHasConnectionKey(schema6) {
|
|
|
15807
15805
|
const fields = typeof shape === "function" ? shape() : shape;
|
|
15808
15806
|
return isRecord7(fields) && Object.prototype.hasOwnProperty.call(fields, "connectionKey");
|
|
15809
15807
|
}
|
|
15810
|
-
function hasConnectionKeySchema(
|
|
15811
|
-
if (!isRecord7(
|
|
15812
|
-
if (schemaHasConnectionKey(
|
|
15813
|
-
const definition = isRecord7(
|
|
15808
|
+
function hasConnectionKeySchema(tool68) {
|
|
15809
|
+
if (!isRecord7(tool68) || !isRecord7(tool68.schema)) return false;
|
|
15810
|
+
if (schemaHasConnectionKey(tool68.schema)) return true;
|
|
15811
|
+
const definition = isRecord7(tool68.schema._def) ? tool68.schema._def : void 0;
|
|
15814
15812
|
if (Array.isArray(definition?.options) && definition.options.length > 0) {
|
|
15815
15813
|
return definition.options.every(
|
|
15816
15814
|
(option) => isRecord7(option) && schemaHasConnectionKey(option)
|
|
@@ -15865,8 +15863,8 @@ var CapabilityToolRegistry = class {
|
|
|
15865
15863
|
* @remarks Standard connection authorization is captured only for tools whose
|
|
15866
15864
|
* schema declares `connectionKey`; legacy selectors remain explicit metadata.
|
|
15867
15865
|
*/
|
|
15868
|
-
register(name, metadata,
|
|
15869
|
-
this.registerInternal(name, metadata, hasConnectionKeySchema(
|
|
15866
|
+
register(name, metadata, tool68) {
|
|
15867
|
+
this.registerInternal(name, metadata, hasConnectionKeySchema(tool68));
|
|
15870
15868
|
}
|
|
15871
15869
|
/**
|
|
15872
15870
|
* Registers all tools actually exposed by a middleware instance.
|
|
@@ -15877,13 +15875,13 @@ var CapabilityToolRegistry = class {
|
|
|
15877
15875
|
* @returns Nothing.
|
|
15878
15876
|
*/
|
|
15879
15877
|
registerMiddleware(capabilityType, middleware, resourceSelectors = {}) {
|
|
15880
|
-
for (const
|
|
15881
|
-
const name = toolName(
|
|
15878
|
+
for (const tool68 of middleware.tools ?? []) {
|
|
15879
|
+
const name = toolName(tool68);
|
|
15882
15880
|
if (name) {
|
|
15883
15881
|
this.registerInternal(name, {
|
|
15884
15882
|
capabilityType,
|
|
15885
15883
|
resourceSelector: resourceSelectors[name]
|
|
15886
|
-
}, hasConnectionKeySchema(
|
|
15884
|
+
}, hasConnectionKeySchema(tool68));
|
|
15887
15885
|
}
|
|
15888
15886
|
}
|
|
15889
15887
|
}
|
|
@@ -16575,9 +16573,9 @@ var ReActAgentGraphBuilder = class {
|
|
|
16575
16573
|
*/
|
|
16576
16574
|
async build(agentLattice, params) {
|
|
16577
16575
|
const tools = params.tools.map((t) => {
|
|
16578
|
-
const
|
|
16579
|
-
return
|
|
16580
|
-
}).filter((
|
|
16576
|
+
const tool68 = getToolClientWithTenant(params.tenantId ?? "default", t.key);
|
|
16577
|
+
return tool68;
|
|
16578
|
+
}).filter((tool68) => tool68 !== void 0);
|
|
16581
16579
|
const stateSchema2 = createReactAgentSchema(params.stateSchema);
|
|
16582
16580
|
const middlewareConfigs = params.middleware || [];
|
|
16583
16581
|
const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
|
|
@@ -17734,8 +17732,8 @@ function validateCapability(value, index) {
|
|
|
17734
17732
|
fieldPath: `/capabilities/${index}/allowedTools`
|
|
17735
17733
|
});
|
|
17736
17734
|
}
|
|
17737
|
-
for (const [toolIndex,
|
|
17738
|
-
if (typeof
|
|
17735
|
+
for (const [toolIndex, tool68] of capability.allowedTools.entries()) {
|
|
17736
|
+
if (typeof tool68 !== "string") {
|
|
17739
17737
|
throw new CapabilityBundleValidationError(
|
|
17740
17738
|
"CAPABILITY_BUNDLE_INVALID_CAPABILITY",
|
|
17741
17739
|
"allowedTools entries must be strings",
|
|
@@ -17749,10 +17747,10 @@ function validateCapability(value, index) {
|
|
|
17749
17747
|
fieldPath: `/capabilities/${index}/allowedTools`
|
|
17750
17748
|
});
|
|
17751
17749
|
}
|
|
17752
|
-
const toolNames = new Set(plugin.meta.tools.map((
|
|
17753
|
-
for (const [toolIndex,
|
|
17754
|
-
if (typeof
|
|
17755
|
-
throw new CapabilityBundleValidationError("CAPABILITY_BUNDLE_UNKNOWN_TOOL", `Unknown tool '${String(
|
|
17750
|
+
const toolNames = new Set(plugin.meta.tools.map((tool68) => tool68.name));
|
|
17751
|
+
for (const [toolIndex, tool68] of capability.allowedTools.entries()) {
|
|
17752
|
+
if (typeof tool68 !== "string" || !toolNames.has(tool68)) {
|
|
17753
|
+
throw new CapabilityBundleValidationError("CAPABILITY_BUNDLE_UNKNOWN_TOOL", `Unknown tool '${String(tool68)}'`, {
|
|
17756
17754
|
capabilityType,
|
|
17757
17755
|
fieldPath: `/capabilities/${index}/allowedTools/${toolIndex}`
|
|
17758
17756
|
});
|
|
@@ -18235,7 +18233,7 @@ function applyStaticCeiling(capabilities, staticMiddleware) {
|
|
|
18235
18233
|
const projectTools = capability.allowedTools;
|
|
18236
18234
|
const staticTools = ceiling.allowedTools;
|
|
18237
18235
|
const effectiveStaticTools = staticTools?.length === 0 ? void 0 : staticTools;
|
|
18238
|
-
const allowedTools = projectTools === void 0 ? effectiveStaticTools : effectiveStaticTools === void 0 ? projectTools : projectTools.filter((
|
|
18236
|
+
const allowedTools = projectTools === void 0 ? effectiveStaticTools : effectiveStaticTools === void 0 ? projectTools : projectTools.filter((tool68) => effectiveStaticTools.includes(tool68));
|
|
18239
18237
|
runtime[capability.type] = structuredClone({
|
|
18240
18238
|
...capability,
|
|
18241
18239
|
config: applyStaticResourceCeiling(capability, ceiling),
|
|
@@ -23990,7 +23988,7 @@ var DeepAgentGraphBuilder = class {
|
|
|
23990
23988
|
const tools = params.tools.map((t) => {
|
|
23991
23989
|
const toolClient = getToolClientWithTenant(params.tenantId ?? "default", t.key);
|
|
23992
23990
|
return toolClient;
|
|
23993
|
-
}).filter((
|
|
23991
|
+
}).filter((tool68) => tool68 !== void 0);
|
|
23994
23992
|
const subagents = await Promise.all(params.subAgents.map(async (sa) => {
|
|
23995
23993
|
if (sa.client) {
|
|
23996
23994
|
return {
|
|
@@ -25642,7 +25640,7 @@ var TeamAgentGraphBuilder = class {
|
|
|
25642
25640
|
const tools = params.tools.map((t) => {
|
|
25643
25641
|
const toolClient = getToolClientWithTenant(params.tenantId ?? "default", t.key);
|
|
25644
25642
|
return toolClient;
|
|
25645
|
-
}).filter((
|
|
25643
|
+
}).filter((tool68) => tool68 !== void 0);
|
|
25646
25644
|
const teammates = params.subAgents.map((sa) => {
|
|
25647
25645
|
const baseConfig = sa.config;
|
|
25648
25646
|
return {
|
|
@@ -30039,7 +30037,7 @@ function requireSkillDeclaration(skillLoaded) {
|
|
|
30039
30037
|
return void 0;
|
|
30040
30038
|
}
|
|
30041
30039
|
async function validateAgentReferences(input, tenantId2) {
|
|
30042
|
-
const availableTools = getAvailableTools(tenantId2).map((
|
|
30040
|
+
const availableTools = getAvailableTools(tenantId2).map((tool68) => tool68.key);
|
|
30043
30041
|
const availableMiddlewareTypes = getAvailableMiddlewareTypes();
|
|
30044
30042
|
const availableCustomMiddlewareKeys = CustomMiddlewareRegistry.list().filter(
|
|
30045
30043
|
(key5) => CustomMiddlewareRegistry.get(key5) !== void 0
|
|
@@ -30806,7 +30804,7 @@ var agentArchitectConfig = {
|
|
|
30806
30804
|
"delete_agent",
|
|
30807
30805
|
"manage_binding"
|
|
30808
30806
|
],
|
|
30809
|
-
subAgents: ["document-parser-benchmark"],
|
|
30807
|
+
subAgents: ["document-parser", "document-parser-benchmark"],
|
|
30810
30808
|
middleware: [
|
|
30811
30809
|
{
|
|
30812
30810
|
id: "filesystem",
|
|
@@ -32515,6 +32513,7 @@ async function removeCollectionVectorStore(name, tenantId2) {
|
|
|
32515
32513
|
|
|
32516
32514
|
// src/mcp_lattice/McpLatticeManager.ts
|
|
32517
32515
|
var import_mcp_adapters = require("@langchain/mcp-adapters");
|
|
32516
|
+
var import_tools3 = require("@langchain/core/tools");
|
|
32518
32517
|
init_BaseLatticeManager();
|
|
32519
32518
|
|
|
32520
32519
|
// src/mcp_lattice/reconnectPolicy.ts
|
|
@@ -32524,6 +32523,13 @@ var DEFAULT_DELAY_MS = 1e3;
|
|
|
32524
32523
|
var MAX_BACKOFF_MS = 3e4;
|
|
32525
32524
|
var HEALTH_CHECK_INTERVAL_MS = 3e4;
|
|
32526
32525
|
var HEALTH_CHECK_TIMEOUT_MS = 5e3;
|
|
32526
|
+
function isMcpConnectionError(error) {
|
|
32527
|
+
const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
|
|
32528
|
+
if (!message) return false;
|
|
32529
|
+
return /not connected|connection closed|session not found|no session|maximum reconnection/i.test(
|
|
32530
|
+
message
|
|
32531
|
+
);
|
|
32532
|
+
}
|
|
32527
32533
|
function nextBackoffDelay(attempt, base = DEFAULT_DELAY_MS, max = MAX_BACKOFF_MS) {
|
|
32528
32534
|
if (attempt <= 0) return base;
|
|
32529
32535
|
return Math.min(base * Math.pow(2, attempt - 1), max);
|
|
@@ -32548,12 +32554,21 @@ async function withTimeout2(operation, ms, onTimeout) {
|
|
|
32548
32554
|
|
|
32549
32555
|
// src/mcp_lattice/McpLatticeManager.ts
|
|
32550
32556
|
var realClientFactory = ({ mcpServers }) => new import_mcp_adapters.MultiServerMCPClient({ mcpServers });
|
|
32557
|
+
function extractRawCall(tool68) {
|
|
32558
|
+
const rawCall = tool68._call;
|
|
32559
|
+
if (typeof rawCall === "function") return rawCall.bind(tool68);
|
|
32560
|
+
return async (...args) => {
|
|
32561
|
+
const invoke = tool68.invoke.bind(tool68);
|
|
32562
|
+
return invoke(args[0], args[2]);
|
|
32563
|
+
};
|
|
32564
|
+
}
|
|
32551
32565
|
var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
|
|
32552
32566
|
constructor() {
|
|
32553
32567
|
super(...arguments);
|
|
32554
32568
|
this.runtimes = /* @__PURE__ */ new Map();
|
|
32555
32569
|
this.clientFactory = realClientFactory;
|
|
32556
32570
|
this.healthCheckInFlight = false;
|
|
32571
|
+
this.reconnectPromises = /* @__PURE__ */ new Map();
|
|
32557
32572
|
}
|
|
32558
32573
|
static getInstance() {
|
|
32559
32574
|
if (!_McpLatticeManager._instance) {
|
|
@@ -32811,6 +32826,64 @@ var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
|
|
|
32811
32826
|
rt.attempt = 0;
|
|
32812
32827
|
await this.reconnectRuntime(rt);
|
|
32813
32828
|
}
|
|
32829
|
+
/**
|
|
32830
|
+
* Single-flight a forced reconnect per `(tenantId, serverKey)` so concurrent
|
|
32831
|
+
* tool calls that all hit the same dead session reconnect once, not once each.
|
|
32832
|
+
*/
|
|
32833
|
+
reconnectShared(rt) {
|
|
32834
|
+
const key5 = this.compositeKey(rt.id.tenantId, rt.id.serverKey);
|
|
32835
|
+
const existing = this.reconnectPromises.get(key5);
|
|
32836
|
+
if (existing) return existing;
|
|
32837
|
+
const work = this.reconnectServer(rt.id.tenantId, rt.id.serverKey).finally(() => {
|
|
32838
|
+
if (this.reconnectPromises.get(key5) === work) this.reconnectPromises.delete(key5);
|
|
32839
|
+
});
|
|
32840
|
+
this.reconnectPromises.set(key5, work);
|
|
32841
|
+
return work;
|
|
32842
|
+
}
|
|
32843
|
+
/**
|
|
32844
|
+
* Wrap a raw MCP tool so a call landing on a torn-down session
|
|
32845
|
+
* (`Not connected` / `Connection closed` / session expiry) transparently
|
|
32846
|
+
* forces a reconnect and retries once against the fresh client, instead of
|
|
32847
|
+
* failing the surrounding run. Non-connection errors propagate untouched.
|
|
32848
|
+
*/
|
|
32849
|
+
wrapToolForResilience(rt, raw) {
|
|
32850
|
+
const call = extractRawCall(raw);
|
|
32851
|
+
return new import_tools3.DynamicStructuredTool({
|
|
32852
|
+
name: raw.name,
|
|
32853
|
+
description: raw.description,
|
|
32854
|
+
schema: raw.schema,
|
|
32855
|
+
responseFormat: raw.responseFormat,
|
|
32856
|
+
defaultConfig: raw.defaultConfig,
|
|
32857
|
+
metadata: raw.metadata,
|
|
32858
|
+
returnDirect: raw.returnDirect,
|
|
32859
|
+
func: async (...args) => this.invokeResilient(rt, raw.name, call, args)
|
|
32860
|
+
});
|
|
32861
|
+
}
|
|
32862
|
+
async invokeResilient(rt, toolName2, call, args) {
|
|
32863
|
+
try {
|
|
32864
|
+
await this.ensureConnected(rt.id.tenantId, rt.id.serverKey);
|
|
32865
|
+
return await call(...args);
|
|
32866
|
+
} catch (error) {
|
|
32867
|
+
if (!isMcpConnectionError(error) || !this.isActive(rt)) throw error;
|
|
32868
|
+
console.warn(
|
|
32869
|
+
`[MCP] ${rt.id.tenantId}/${rt.id.serverKey}: tool "${toolName2}" hit a dead session; reconnecting and retrying once`,
|
|
32870
|
+
error instanceof Error ? error.message : error
|
|
32871
|
+
);
|
|
32872
|
+
try {
|
|
32873
|
+
await this.reconnectShared(rt);
|
|
32874
|
+
} catch (reconnectError) {
|
|
32875
|
+
console.warn(
|
|
32876
|
+
`[MCP] ${rt.id.tenantId}/${rt.id.serverKey}: reconnect for tool "${toolName2}" failed`,
|
|
32877
|
+
reconnectError instanceof Error ? reconnectError.message : reconnectError
|
|
32878
|
+
);
|
|
32879
|
+
throw error;
|
|
32880
|
+
}
|
|
32881
|
+
const fresh = await this.getRawTools(rt.id.tenantId, rt.id.serverKey);
|
|
32882
|
+
const match = fresh.find((t) => t.name === toolName2);
|
|
32883
|
+
if (!match) throw error;
|
|
32884
|
+
return await extractRawCall(match)(...args);
|
|
32885
|
+
}
|
|
32886
|
+
}
|
|
32814
32887
|
async checkHealth() {
|
|
32815
32888
|
if (this.healthCheckInFlight) return;
|
|
32816
32889
|
this.healthCheckInFlight = true;
|
|
@@ -32829,8 +32902,12 @@ var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
|
|
|
32829
32902
|
await withTimeout2(session.listTools(), HEALTH_CHECK_TIMEOUT_MS, async () => {
|
|
32830
32903
|
});
|
|
32831
32904
|
if (!this.isActive(rt) || rt.state !== "connected") continue;
|
|
32832
|
-
} catch {
|
|
32905
|
+
} catch (error) {
|
|
32833
32906
|
if (this.isActive(rt) && rt.state === "connected") {
|
|
32907
|
+
console.warn(
|
|
32908
|
+
`[MCP] ${rt.id.tenantId}/${rt.id.serverKey}: health check failed; scheduling reconnect`,
|
|
32909
|
+
error instanceof Error ? error.message : error
|
|
32910
|
+
);
|
|
32834
32911
|
rt.state = "failed";
|
|
32835
32912
|
this.scheduleReconnect(rt);
|
|
32836
32913
|
}
|
|
@@ -33029,15 +33106,16 @@ var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
|
|
|
33029
33106
|
const metaByName = new Map(metaList.map((m) => [m.name, m.meta]));
|
|
33030
33107
|
this.unregisterServerTools(tenantId2, serverKey);
|
|
33031
33108
|
const keys = [];
|
|
33032
|
-
for (const
|
|
33033
|
-
if (rt.selectedTools && !rt.selectedTools.includes(
|
|
33034
|
-
const meta = metaByName.get(
|
|
33109
|
+
for (const tool68 of tools) {
|
|
33110
|
+
if (rt.selectedTools && !rt.selectedTools.includes(tool68.name)) continue;
|
|
33111
|
+
const meta = metaByName.get(tool68.name);
|
|
33035
33112
|
const rawVisibility = meta?.ui?.visibility;
|
|
33036
33113
|
const visibility = Array.isArray(rawVisibility) ? rawVisibility : typeof rawVisibility === "string" ? [rawVisibility] : void 0;
|
|
33037
33114
|
if (visibility && !visibility.includes("model")) continue;
|
|
33038
33115
|
const ref = extractAppsRef(meta, serverKey);
|
|
33039
|
-
const
|
|
33040
|
-
const
|
|
33116
|
+
const resilient = this.wrapToolForResilience(rt, tool68);
|
|
33117
|
+
const registered = ref ? wrapMcpToolWithUi(resilient, ref) : resilient;
|
|
33118
|
+
const toolKey = _McpLatticeManager.buildToolKey(serverKey, tool68.name);
|
|
33041
33119
|
try {
|
|
33042
33120
|
toolLatticeManager.registerExistingToolWithTenant(tenantId2, toolKey, registered);
|
|
33043
33121
|
keys.push(toolKey);
|
|
@@ -33105,6 +33183,7 @@ var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
|
|
|
33105
33183
|
}
|
|
33106
33184
|
}
|
|
33107
33185
|
this.runtimes.clear();
|
|
33186
|
+
this.reconnectPromises.clear();
|
|
33108
33187
|
}
|
|
33109
33188
|
};
|
|
33110
33189
|
var mcpManager = McpLatticeManager.getInstance();
|
|
@@ -37316,14 +37395,6 @@ async function applyBeliefImpacts(taskStore, owner, impacts) {
|
|
|
37316
37395
|
}
|
|
37317
37396
|
return { description: current.description ?? "", task: current };
|
|
37318
37397
|
}
|
|
37319
|
-
function parseExternalDependency(value) {
|
|
37320
|
-
const row = (0, import_protocols31.snapshotExactRecord)(value, ["type", "summary", "requestedAt", "dependencyTaskIds"]);
|
|
37321
|
-
const ids = (0, import_protocols31.snapshotExactArray)(row?.dependencyTaskIds);
|
|
37322
|
-
if (!row || row.type !== "external_dependency" || typeof row.summary !== "string" || !row.summary.trim() || typeof row.requestedAt !== "string" || !Number.isFinite(Date.parse(row.requestedAt)) || !ids || ids.length === 0 || ids.some((id) => typeof id !== "string" || !id.trim())) return void 0;
|
|
37323
|
-
const trimmed = ids.map((id) => id.trim());
|
|
37324
|
-
if (new Set(trimmed).size !== trimmed.length) return void 0;
|
|
37325
|
-
return { type: "external_dependency", summary: row.summary, requestedAt: row.requestedAt, dependencyTaskIds: trimmed };
|
|
37326
|
-
}
|
|
37327
37398
|
function unsupportedTaskStatus() {
|
|
37328
37399
|
return failure2(
|
|
37329
37400
|
"TASK_STATUS_UNSUPPORTED",
|
|
@@ -37622,9 +37693,6 @@ var TaskLifecycleService = class {
|
|
|
37622
37693
|
if (interruption && typeof interruption === "object" && interruption.type === "review_required") {
|
|
37623
37694
|
return failure2("REVIEW_APPROVAL_REQUIRED", "Review interruption requires explicit approval or rejection.");
|
|
37624
37695
|
}
|
|
37625
|
-
if (interruption && typeof interruption === "object" && interruption.type === "external_dependency" && !parseExternalDependency(interruption)) {
|
|
37626
|
-
return failure2("INVALID_EXTERNAL_DEPENDENCY", "Stored external dependency interruption is malformed.");
|
|
37627
|
-
}
|
|
37628
37696
|
const previousInterruption = interruption && typeof interruption === "object" ? interruption : {};
|
|
37629
37697
|
const resumeKey = this.resumeEventKey(task);
|
|
37630
37698
|
const audit = { eventKey: resumeKey, previousInterruption };
|
|
@@ -37805,6 +37873,108 @@ var TaskLifecycleService = class {
|
|
|
37805
37873
|
detail: { previousStatus: "failed" }
|
|
37806
37874
|
});
|
|
37807
37875
|
}
|
|
37876
|
+
/**
|
|
37877
|
+
* Reopens a terminal agent task by returning it to in_progress.
|
|
37878
|
+
*
|
|
37879
|
+
* @param input Task, actor, and optional thread.
|
|
37880
|
+
* @returns Structured lifecycle result. `completed` and `cancelled` tasks
|
|
37881
|
+
* reopen to `in_progress`; an already-`in_progress` task is acknowledged
|
|
37882
|
+
* without mutation; any other status or a lost CAS yields
|
|
37883
|
+
* `TASK_STATUS_CONFLICT`.
|
|
37884
|
+
* @remarks This is the single reverse edge of the terminal-irreversibility
|
|
37885
|
+
* relaxation. It records the status change only; re-dispatch is owned by
|
|
37886
|
+
* the application layer and is never triggered here.
|
|
37887
|
+
*/
|
|
37888
|
+
async reopenTask(input) {
|
|
37889
|
+
return this.transitionAgentTask({
|
|
37890
|
+
...input,
|
|
37891
|
+
targetStatus: "in_progress",
|
|
37892
|
+
expectedStatuses: ["completed", "cancelled"],
|
|
37893
|
+
updates: { status: "in_progress", failureReason: null, result: null },
|
|
37894
|
+
summary: "Task reopened",
|
|
37895
|
+
detail: { type: "reopen" }
|
|
37896
|
+
});
|
|
37897
|
+
}
|
|
37898
|
+
/**
|
|
37899
|
+
* Transfers a human-authored task's ownership to a chosen Agent before dispatch.
|
|
37900
|
+
*
|
|
37901
|
+
* @param input Task, actor, destination Agent, and optional Task Thread.
|
|
37902
|
+
* @returns Structured result with the reassigned owner and an `owner_assigned` audit.
|
|
37903
|
+
* @remarks Only tasks with `context.source === "user"` can be assigned this way.
|
|
37904
|
+
* Repeated assignment to the same owner is idempotent (repair-writes the audit
|
|
37905
|
+
* without a CAS). This changes owner only, never status, so it publishes no
|
|
37906
|
+
* Project lifecycle notification.
|
|
37907
|
+
*/
|
|
37908
|
+
async assignOwner(input) {
|
|
37909
|
+
let task;
|
|
37910
|
+
try {
|
|
37911
|
+
task = await this.deps.taskStore.getById(input.tenantId, input.taskId);
|
|
37912
|
+
} catch {
|
|
37913
|
+
return failure2("TASK_STORE_READ_FAILED", "Failed to read task lifecycle state.");
|
|
37914
|
+
}
|
|
37915
|
+
if (!task) return failure2("TASK_NOT_FOUND", "Task was not found.");
|
|
37916
|
+
if (task.context?.source !== "user") {
|
|
37917
|
+
return failure2("TASK_NOT_HUMAN_MANAGED", "Only user-authored tasks can be assigned to an Agent.");
|
|
37918
|
+
}
|
|
37919
|
+
const storedThreadId = typeof task.context?.thread_id === "string" && task.context.thread_id.length > 0 ? task.context.thread_id : void 0;
|
|
37920
|
+
const effectiveThreadId = storedThreadId ?? input.threadId;
|
|
37921
|
+
const detail = { type: "owner_assigned", fromOwnerType: task.ownerType, toOwnerId: input.ownerId };
|
|
37922
|
+
if (task.ownerType === "agent" && task.ownerId === input.ownerId && (input.threadId === void 0 || storedThreadId === input.threadId)) {
|
|
37923
|
+
const eventKey2 = this.statusEventKey(task, "owner_assigned", detail);
|
|
37924
|
+
const event2 = await this.writeStatusEvent(
|
|
37925
|
+
task,
|
|
37926
|
+
input.actor,
|
|
37927
|
+
effectiveThreadId,
|
|
37928
|
+
"activity",
|
|
37929
|
+
"Task owner assigned",
|
|
37930
|
+
detail,
|
|
37931
|
+
eventKey2
|
|
37932
|
+
);
|
|
37933
|
+
return {
|
|
37934
|
+
success: true,
|
|
37935
|
+
task,
|
|
37936
|
+
mutated: false,
|
|
37937
|
+
eventKey: event2.eventKey,
|
|
37938
|
+
...event2.warning ? { warnings: [event2.warning] } : {}
|
|
37939
|
+
};
|
|
37940
|
+
}
|
|
37941
|
+
const context = { ...task.context ?? {} };
|
|
37942
|
+
if (input.threadId && !storedThreadId) context.thread_id = input.threadId;
|
|
37943
|
+
let updated;
|
|
37944
|
+
try {
|
|
37945
|
+
updated = await this.deps.taskStore.updateIfStatusAndUpdatedAt(
|
|
37946
|
+
input.tenantId,
|
|
37947
|
+
input.taskId,
|
|
37948
|
+
{ ownerType: "agent", ownerId: input.ownerId, context },
|
|
37949
|
+
[task.status],
|
|
37950
|
+
task.updatedAt
|
|
37951
|
+
);
|
|
37952
|
+
} catch {
|
|
37953
|
+
return failure2(
|
|
37954
|
+
"TASK_STORE_WRITE_FAILED",
|
|
37955
|
+
"Failed to assign the task owner.",
|
|
37956
|
+
"The store rejected the write."
|
|
37957
|
+
);
|
|
37958
|
+
}
|
|
37959
|
+
if (!updated) return failure2("TASK_STATUS_CONFLICT", "Task changed concurrently.");
|
|
37960
|
+
const eventKey = this.statusEventKey(updated, "owner_assigned", detail);
|
|
37961
|
+
const event = await this.writeStatusEvent(
|
|
37962
|
+
updated,
|
|
37963
|
+
input.actor,
|
|
37964
|
+
effectiveThreadId,
|
|
37965
|
+
"activity",
|
|
37966
|
+
"Task owner assigned",
|
|
37967
|
+
detail,
|
|
37968
|
+
eventKey
|
|
37969
|
+
);
|
|
37970
|
+
return {
|
|
37971
|
+
success: true,
|
|
37972
|
+
task: updated,
|
|
37973
|
+
mutated: true,
|
|
37974
|
+
eventKey: event.eventKey,
|
|
37975
|
+
...event.warning ? { warnings: [event.warning] } : {}
|
|
37976
|
+
};
|
|
37977
|
+
}
|
|
37808
37978
|
/** Atomically cancels a nonterminal agent task and records an idempotent status event. */
|
|
37809
37979
|
async cancelTask(input) {
|
|
37810
37980
|
return this.transitionAgentTask({
|
|
@@ -37885,19 +38055,7 @@ var TaskLifecycleService = class {
|
|
|
37885
38055
|
async interruptTask(input) {
|
|
37886
38056
|
const summary = input.summary.trim();
|
|
37887
38057
|
if (!summary) return failure2("MISSING_INTERRUPTION_SUMMARY", "Agent interruption requires a nonblank summary.");
|
|
37888
|
-
if (input.type !== "external_dependency" && input.dependencyTaskIds !== void 0) {
|
|
37889
|
-
return failure2("INVALID_EXTERNAL_DEPENDENCY", "dependencyTaskIds are only valid for external dependencies.");
|
|
37890
|
-
}
|
|
37891
38058
|
const requestedAt = this.now().toISOString();
|
|
37892
|
-
const external = input.type === "external_dependency" ? parseExternalDependency({
|
|
37893
|
-
type: input.type,
|
|
37894
|
-
summary,
|
|
37895
|
-
requestedAt,
|
|
37896
|
-
dependencyTaskIds: input.dependencyTaskIds
|
|
37897
|
-
}) : void 0;
|
|
37898
|
-
if (input.type === "external_dependency" && !external) {
|
|
37899
|
-
return failure2("INVALID_EXTERNAL_DEPENDENCY", "External dependencies require exact, unique nonblank task IDs.");
|
|
37900
|
-
}
|
|
37901
38059
|
let task;
|
|
37902
38060
|
try {
|
|
37903
38061
|
task = await this.deps.taskStore.getById(input.tenantId, input.taskId);
|
|
@@ -37911,29 +38069,17 @@ var TaskLifecycleService = class {
|
|
|
37911
38069
|
if (threadFailure) return threadFailure;
|
|
37912
38070
|
const currentInterruption = task.context?.interruption;
|
|
37913
38071
|
if (task.status === "interrupted" && currentInterruption && typeof currentInterruption === "object") {
|
|
37914
|
-
|
|
37915
|
-
if (input.type === "external_dependency") {
|
|
37916
|
-
if (!external || !storedExternal || storedExternal.summary !== external.summary || canonicalJson(storedExternal.dependencyTaskIds) !== canonicalJson(external.dependencyTaskIds)) {
|
|
37917
|
-
return failure2(
|
|
37918
|
-
"TASK_STATUS_CONFLICT",
|
|
37919
|
-
"Task is already interrupted by a different or malformed external dependency.",
|
|
37920
|
-
"Use manage_task get to inspect the existing interruption in task context.interruption."
|
|
37921
|
-
);
|
|
37922
|
-
}
|
|
37923
|
-
} else if (currentInterruption.type !== input.type || currentInterruption.summary !== summary) {
|
|
38072
|
+
if (currentInterruption.type !== input.type || currentInterruption.summary !== summary) {
|
|
37924
38073
|
return failure2(
|
|
37925
38074
|
"TASK_STATUS_CONFLICT",
|
|
37926
38075
|
"Task is already interrupted by a different request.",
|
|
37927
38076
|
"Use manage_task get to inspect the existing interruption, or resume it first."
|
|
37928
38077
|
);
|
|
37929
38078
|
}
|
|
37930
|
-
const detail =
|
|
38079
|
+
const detail = currentInterruption;
|
|
37931
38080
|
const eventKey2 = this.statusEventKey(task, "interrupted", detail);
|
|
37932
38081
|
const event2 = await this.writeStatusEvent(task, input.actor, input.threadId, "interrupted", summary, detail, eventKey2);
|
|
37933
38082
|
const warnings2 = event2.warning ? [event2.warning] : [];
|
|
37934
|
-
if (storedExternal && task.workspaceId && task.projectId) {
|
|
37935
|
-
return this.finishExternalDependencyInterruption(task, input, storedExternal, event2, warnings2, false);
|
|
37936
|
-
}
|
|
37937
38083
|
return {
|
|
37938
38084
|
success: true,
|
|
37939
38085
|
task,
|
|
@@ -37949,11 +38095,7 @@ var TaskLifecycleService = class {
|
|
|
37949
38095
|
"Only pending or in_progress tasks can be interrupted. Use manage_task get to check the current status."
|
|
37950
38096
|
);
|
|
37951
38097
|
}
|
|
37952
|
-
|
|
37953
|
-
const dependencyFailure = await this.validateExternalDependencies(task, external.dependencyTaskIds);
|
|
37954
|
-
if (dependencyFailure) return dependencyFailure;
|
|
37955
|
-
}
|
|
37956
|
-
const interruption = external ? { ...external } : { type: input.type, summary, requestedAt };
|
|
38098
|
+
const interruption = { type: input.type, summary, requestedAt };
|
|
37957
38099
|
let updated;
|
|
37958
38100
|
try {
|
|
37959
38101
|
updated = await this.deps.taskStore.updateIfStatusAndUpdatedAt(input.tenantId, input.taskId, {
|
|
@@ -37975,9 +38117,6 @@ var TaskLifecycleService = class {
|
|
|
37975
38117
|
const eventKey = this.statusEventKey(updated, "interrupted", interruption);
|
|
37976
38118
|
const event = await this.writeStatusEvent(updated, input.actor, input.threadId, "interrupted", summary, interruption, eventKey);
|
|
37977
38119
|
const warnings = event.warning ? [event.warning] : await this.notifyWinningTransition(updated, "interrupted", event);
|
|
37978
|
-
if (external && updated.workspaceId && updated.projectId) {
|
|
37979
|
-
return this.finishExternalDependencyInterruption(updated, input, external, event, warnings, true);
|
|
37980
|
-
}
|
|
37981
38120
|
return {
|
|
37982
38121
|
success: true,
|
|
37983
38122
|
task: updated,
|
|
@@ -39216,7 +39355,9 @@ var TaskLifecycleService = class {
|
|
|
39216
39355
|
};
|
|
39217
39356
|
}
|
|
39218
39357
|
if (!input.expectedStatuses.includes(task.status)) return failure2("TASK_STATUS_CONFLICT", "Task status cannot make this transition.");
|
|
39219
|
-
const
|
|
39358
|
+
const clearedContext = clearInterruptionContext(task.context);
|
|
39359
|
+
const withThread = input.threadId && task.context?.thread_id === void 0 ? { ...clearedContext ?? {}, thread_id: input.threadId } : clearedContext;
|
|
39360
|
+
const updates = { ...input.updates, context: withThread };
|
|
39220
39361
|
let updated;
|
|
39221
39362
|
try {
|
|
39222
39363
|
updated = await this.deps.taskStore.updateIfStatusAndUpdatedAt(
|
|
@@ -39304,85 +39445,6 @@ var TaskLifecycleService = class {
|
|
|
39304
39445
|
return [{ code: "LIFECYCLE_NOTIFICATION_FAILED", taskId: task.id, eventKey: event.eventKey }];
|
|
39305
39446
|
}
|
|
39306
39447
|
}
|
|
39307
|
-
async validateExternalDependencies(task, dependencyTaskIds) {
|
|
39308
|
-
const declared = new Set(task.dependencies ?? []);
|
|
39309
|
-
if (dependencyTaskIds.some((id) => id === task.id || !declared.has(id))) {
|
|
39310
|
-
return failure2("INVALID_EXTERNAL_DEPENDENCY", "External dependency IDs must be declared non-self dependencies.");
|
|
39311
|
-
}
|
|
39312
|
-
try {
|
|
39313
|
-
for (const id of dependencyTaskIds) {
|
|
39314
|
-
const dependency = await this.deps.taskStore.getById(task.tenantId, id);
|
|
39315
|
-
if (!dependency || dependency.workspaceId !== task.workspaceId || dependency.projectId !== task.projectId || dependency.status === "completed") {
|
|
39316
|
-
return failure2("INVALID_EXTERNAL_DEPENDENCY", "External dependencies must exist, remain incomplete, and share exact scope.");
|
|
39317
|
-
}
|
|
39318
|
-
}
|
|
39319
|
-
} catch {
|
|
39320
|
-
return failure2("TASK_STORE_READ_FAILED", "Failed to validate external dependencies.");
|
|
39321
|
-
}
|
|
39322
|
-
return void 0;
|
|
39323
|
-
}
|
|
39324
|
-
async externalDependencyReadiness(task, dependencyTaskIds) {
|
|
39325
|
-
try {
|
|
39326
|
-
for (const id of dependencyTaskIds) {
|
|
39327
|
-
const dependency = await this.deps.taskStore.getById(task.tenantId, id);
|
|
39328
|
-
if (!dependency || dependency.workspaceId !== task.workspaceId || dependency.projectId !== task.projectId || dependency.status !== "completed") return { kind: "blocked" };
|
|
39329
|
-
}
|
|
39330
|
-
return { kind: "ready" };
|
|
39331
|
-
} catch {
|
|
39332
|
-
return {
|
|
39333
|
-
kind: "error",
|
|
39334
|
-
warning: { code: "DEPENDENCY_READ_FAILED", taskId: task.id }
|
|
39335
|
-
};
|
|
39336
|
-
}
|
|
39337
|
-
}
|
|
39338
|
-
async finishExternalDependencyInterruption(task, input, interruption, event, warnings, mutated) {
|
|
39339
|
-
if (event.warning) {
|
|
39340
|
-
return { success: true, task, mutated, eventKey: event.eventKey, warnings };
|
|
39341
|
-
}
|
|
39342
|
-
const readiness = await this.externalDependencyReadiness(task, interruption.dependencyTaskIds);
|
|
39343
|
-
if (readiness.kind === "blocked") {
|
|
39344
|
-
return { success: true, task, mutated, eventKey: event.eventKey, ...warnings.length ? { warnings } : {} };
|
|
39345
|
-
}
|
|
39346
|
-
if (readiness.kind === "error") {
|
|
39347
|
-
return {
|
|
39348
|
-
success: true,
|
|
39349
|
-
task,
|
|
39350
|
-
mutated,
|
|
39351
|
-
eventKey: event.eventKey,
|
|
39352
|
-
warnings: [...warnings, { ...readiness.warning, eventKey: event.eventKey }]
|
|
39353
|
-
};
|
|
39354
|
-
}
|
|
39355
|
-
const resumed = await this.resumeInterruption({
|
|
39356
|
-
tenantId: input.tenantId,
|
|
39357
|
-
taskId: input.taskId,
|
|
39358
|
-
actor: input.actor,
|
|
39359
|
-
threadId: input.threadId
|
|
39360
|
-
});
|
|
39361
|
-
if (resumed.success) {
|
|
39362
|
-
const combined = [...warnings, ...resumed.warnings ?? []];
|
|
39363
|
-
return {
|
|
39364
|
-
...resumed,
|
|
39365
|
-
mutated: mutated || resumed.mutated,
|
|
39366
|
-
...combined.length ? { warnings: combined } : {}
|
|
39367
|
-
};
|
|
39368
|
-
}
|
|
39369
|
-
let current;
|
|
39370
|
-
try {
|
|
39371
|
-
current = await this.deps.taskStore.getById(input.tenantId, input.taskId);
|
|
39372
|
-
} catch {
|
|
39373
|
-
return resumed;
|
|
39374
|
-
}
|
|
39375
|
-
if (current?.status === "in_progress" && (!current.context?.thread_id || current.context?.thread_id === input.threadId)) {
|
|
39376
|
-
return {
|
|
39377
|
-
success: true,
|
|
39378
|
-
task: current,
|
|
39379
|
-
mutated,
|
|
39380
|
-
eventKey: event.eventKey,
|
|
39381
|
-
...warnings.length ? { warnings } : {}
|
|
39382
|
-
};
|
|
39383
|
-
}
|
|
39384
|
-
return resumed;
|
|
39385
|
-
}
|
|
39386
39448
|
async clearAuditMarker(task, key5) {
|
|
39387
39449
|
const context = withoutContextKey(task.context, key5);
|
|
39388
39450
|
try {
|
|
@@ -40826,10 +40888,10 @@ var createLoadSkillContentTool = (pluginSkills, pluginSkillOwnersOrStaticSelecti
|
|
|
40826
40888
|
lockIdentity
|
|
40827
40889
|
);
|
|
40828
40890
|
let result2 = pluginSkill.definition.content;
|
|
40829
|
-
const
|
|
40830
|
-
if (
|
|
40891
|
+
const resources2 = Object.entries(pluginSkill.definition.resources ?? {});
|
|
40892
|
+
if (resources2.length > 0) {
|
|
40831
40893
|
result2 += "\n\n---\n\n**Resources** (synced to the sandbox; use `read_file` to access):\n";
|
|
40832
|
-
for (const [resourcePath, resource] of
|
|
40894
|
+
for (const [resourcePath, resource] of resources2) {
|
|
40833
40895
|
result2 += `- ${resourcePath} (mime type: ${resource.mimeType ?? "not specified"})
|
|
40834
40896
|
`;
|
|
40835
40897
|
}
|
|
@@ -40856,10 +40918,10 @@ var createLoadSkillContentTool = (pluginSkills, pluginSkillOwnersOrStaticSelecti
|
|
|
40856
40918
|
`/root/.agents/skills/${input.skill_name}/resources`,
|
|
40857
40919
|
{ recursive: false }
|
|
40858
40920
|
);
|
|
40859
|
-
const
|
|
40860
|
-
if (
|
|
40921
|
+
const resources2 = resourcesResult.files.map((f) => f.path.split("/").pop()).filter(Boolean);
|
|
40922
|
+
if (resources2.length > 0) {
|
|
40861
40923
|
result += "\n\n---\n\n**Resources** (use `read_file` tool to access):\n";
|
|
40862
|
-
|
|
40924
|
+
resources2.forEach((r) => {
|
|
40863
40925
|
result += `- ${r}
|
|
40864
40926
|
`;
|
|
40865
40927
|
});
|
|
@@ -41181,1553 +41243,12 @@ var skillPlugin = {
|
|
|
41181
41243
|
})
|
|
41182
41244
|
};
|
|
41183
41245
|
|
|
41184
|
-
// src/middlewares/semanticMetricsMiddleware.ts
|
|
41185
|
-
var import_langchain70 = require("langchain");
|
|
41186
|
-
|
|
41187
|
-
// src/tool_lattice/semantic_metrics/metrics_datasource_tool.ts
|
|
41188
|
-
var import_zod55 = __toESM(require("zod"));
|
|
41189
|
-
var import_langchain67 = require("langchain");
|
|
41190
|
-
|
|
41191
|
-
// src/tool_lattice/semantic_metrics/types.ts
|
|
41192
|
-
function readToolRunConfig(exeConfig) {
|
|
41193
|
-
return exeConfig?.configurable?.runConfig;
|
|
41194
|
-
}
|
|
41195
|
-
function resolveDatasourceId(input, exeConfig) {
|
|
41196
|
-
const id = input.datasourceId ?? readToolRunConfig(exeConfig)?.metricsDataSource?.datasourceId;
|
|
41197
|
-
if (id === void 0 || id === null || id === "") {
|
|
41198
|
-
throw new Error("datasourceId is required (provide it or set runConfig.metricsDataSource.datasourceId)");
|
|
41199
|
-
}
|
|
41200
|
-
return Number(id);
|
|
41201
|
-
}
|
|
41202
|
-
function assertDatasourceSelected(scope, datasourceId) {
|
|
41203
|
-
if (scope.unrestricted) return;
|
|
41204
|
-
if (!scope.ids.includes(datasourceId)) {
|
|
41205
|
-
throw new Error(
|
|
41206
|
-
`DATASOURCE_NOT_SELECTED: datasource ${datasourceId} is not in the effective scope [${scope.ids.join(", ")}]`
|
|
41207
|
-
);
|
|
41208
|
-
}
|
|
41209
|
-
}
|
|
41210
|
-
function effectiveDatasourceScope(connectionScope) {
|
|
41211
|
-
return connectionScope.length > 0 ? { unrestricted: false, ids: [...connectionScope] } : { unrestricted: true, ids: [] };
|
|
41212
|
-
}
|
|
41213
|
-
var DDL_DML_KEYWORDS = [
|
|
41214
|
-
"insert",
|
|
41215
|
-
"update",
|
|
41216
|
-
"delete",
|
|
41217
|
-
"drop",
|
|
41218
|
-
"alter",
|
|
41219
|
-
"create",
|
|
41220
|
-
"truncate",
|
|
41221
|
-
"grant",
|
|
41222
|
-
"revoke",
|
|
41223
|
-
"merge",
|
|
41224
|
-
"replace",
|
|
41225
|
-
"upsert"
|
|
41226
|
-
];
|
|
41227
|
-
var DDL_DML_RE = new RegExp(`\\b(?:${DDL_DML_KEYWORDS.join("|")})\\b`, "i");
|
|
41228
|
-
var SELECT_INTO_RE = /\bselect\b[\s\S]*?\binto\b/i;
|
|
41229
|
-
function validateSql(sql) {
|
|
41230
|
-
const trimmed = sql.trim();
|
|
41231
|
-
if (!trimmed) {
|
|
41232
|
-
return { ok: false, reason: "SQL is empty" };
|
|
41233
|
-
}
|
|
41234
|
-
const withoutComments = trimmed.replace(/--[^\n]*/g, " ").replace(/\/\*[\s\S]*?\*\//g, " ");
|
|
41235
|
-
const statements = withoutComments.split(";").map((s) => s.trim()).filter(Boolean);
|
|
41236
|
-
if (statements.length > 1) {
|
|
41237
|
-
return { ok: false, reason: "Multiple statements are not allowed" };
|
|
41238
|
-
}
|
|
41239
|
-
const firstKeyword = withoutComments.trim().split(/\s+/)[0].toLowerCase();
|
|
41240
|
-
if (firstKeyword !== "select" && firstKeyword !== "with") {
|
|
41241
|
-
return { ok: false, reason: `Only SELECT or WITH queries are allowed (got "${firstKeyword}")` };
|
|
41242
|
-
}
|
|
41243
|
-
if (SELECT_INTO_RE.test(withoutComments)) {
|
|
41244
|
-
return { ok: false, reason: "SELECT INTO is not allowed (creates a table)" };
|
|
41245
|
-
}
|
|
41246
|
-
if (DDL_DML_RE.test(withoutComments)) {
|
|
41247
|
-
return { ok: false, reason: "Only read-only queries are allowed (DML/DDL detected)" };
|
|
41248
|
-
}
|
|
41249
|
-
return { ok: true };
|
|
41250
|
-
}
|
|
41251
|
-
|
|
41252
|
-
// src/tool_lattice/semantic_metrics/SemanticMetricsV2Client.ts
|
|
41253
|
-
var NO_CONNECTION_HINT = "No semantic-metrics connection is configured for this tenant. Add a connection of type 'semantic-metrics' for the tenant, then select it (connections) or enable connectAll in the agent's middleware config.";
|
|
41254
|
-
async function resolveMetricsClientFromSelector(selector, scope, connectionKey) {
|
|
41255
|
-
let resolved;
|
|
41256
|
-
try {
|
|
41257
|
-
resolved = await resolvePluginConnections(selector.connectionType, selector, scope);
|
|
41258
|
-
} catch (error) {
|
|
41259
|
-
if (error instanceof Error && error.message === "ConnectionStore not configured") {
|
|
41260
|
-
throw new Error(NO_CONNECTION_HINT);
|
|
41261
|
-
}
|
|
41262
|
-
throw error;
|
|
41263
|
-
}
|
|
41264
|
-
const available = resolved.map((c) => c.key).join(", ");
|
|
41265
|
-
if (resolved.length === 0) {
|
|
41266
|
-
throw new Error(NO_CONNECTION_HINT);
|
|
41267
|
-
}
|
|
41268
|
-
const key5 = connectionKey?.trim() || (resolved.length === 1 ? resolved[0].key : "");
|
|
41269
|
-
if (!key5) {
|
|
41270
|
-
throw new Error(
|
|
41271
|
-
`connectionKey is required. Available connections: ${available}`
|
|
41272
|
-
);
|
|
41273
|
-
}
|
|
41274
|
-
const entry = resolved.find((c) => c.key === key5);
|
|
41275
|
-
if (!entry) {
|
|
41276
|
-
throw new Error(`Connection "${key5}" not found. Available connections: ${available}`);
|
|
41277
|
-
}
|
|
41278
|
-
const config = entry.config;
|
|
41279
|
-
return new SemanticMetricsV2Client(config);
|
|
41280
|
-
}
|
|
41281
|
-
var SemanticMetricsV2Client = class {
|
|
41282
|
-
/**
|
|
41283
|
-
* @param config - Connection configuration (server URL, optional API key and headers).
|
|
41284
|
-
*/
|
|
41285
|
-
constructor(config) {
|
|
41286
|
-
this.config = config;
|
|
41287
|
-
this.baseUrl = config.serverUrl.replace(/\/$/, "");
|
|
41288
|
-
}
|
|
41289
|
-
/**
|
|
41290
|
-
* Build default request headers: `Accept: application/json`, custom headers,
|
|
41291
|
-
* and a Bearer `Authorization` header when an API key is configured.
|
|
41292
|
-
*
|
|
41293
|
-
* @returns Merged headers.
|
|
41294
|
-
*/
|
|
41295
|
-
getHeaders() {
|
|
41296
|
-
const headers = {
|
|
41297
|
-
Accept: "application/json",
|
|
41298
|
-
...this.config.headers ?? {}
|
|
41299
|
-
};
|
|
41300
|
-
if (this.config.apiKey) {
|
|
41301
|
-
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
41302
|
-
}
|
|
41303
|
-
return headers;
|
|
41304
|
-
}
|
|
41305
|
-
/**
|
|
41306
|
-
* Numeric selected resource ids of this connection (normalized).
|
|
41307
|
-
*
|
|
41308
|
-
* Reads `selectedEntities` — the standard connection resource-selection
|
|
41309
|
-
* field written by the connection UI (`connection.discover` + selection).
|
|
41310
|
-
*
|
|
41311
|
-
* @returns The selected resource ids; empty when unrestricted.
|
|
41312
|
-
*/
|
|
41313
|
-
getSelectedEntities() {
|
|
41314
|
-
const raw = this.config.selectedEntities;
|
|
41315
|
-
if (!Array.isArray(raw)) return [];
|
|
41316
|
-
return raw.map((v) => Number(v)).filter((n) => Number.isFinite(n));
|
|
41317
|
-
}
|
|
41318
|
-
/**
|
|
41319
|
-
* Perform a JSON request against the base URL.
|
|
41320
|
-
*
|
|
41321
|
-
* The Metrics Server wraps every response as `{ code, message, data }`. A
|
|
41322
|
-
* `code` of 200 resolves to `data`; any other `code` throws a business error
|
|
41323
|
-
* carrying the server message (regardless of HTTP status). Non-envelope
|
|
41324
|
-
* bodies are returned as-is.
|
|
41325
|
-
*
|
|
41326
|
-
* @param path - Path appended to the base URL (must start with `/`).
|
|
41327
|
-
* @param init - Optional `fetch` init overrides (method, body, per-call headers).
|
|
41328
|
-
* @returns The unwrapped `data` payload of the response envelope.
|
|
41329
|
-
* @throws When the server returns a non-200 `code`, or the HTTP response is not OK.
|
|
41330
|
-
*/
|
|
41331
|
-
async request(path8, init = {}) {
|
|
41332
|
-
const response = await fetch(`${this.baseUrl}${path8}`, {
|
|
41333
|
-
...init,
|
|
41334
|
-
method: init.method ?? "GET",
|
|
41335
|
-
headers: { ...this.getHeaders(), ...init.headers ?? {} }
|
|
41336
|
-
});
|
|
41337
|
-
const text = await response.text().catch(() => "");
|
|
41338
|
-
const parsed = this.parseBody(text);
|
|
41339
|
-
if (parsed?.envelope === true) {
|
|
41340
|
-
if (parsed.code !== 200) {
|
|
41341
|
-
throw new Error(`API ${parsed.code}: ${parsed.message || "Unknown error"}`);
|
|
41342
|
-
}
|
|
41343
|
-
return parsed.data;
|
|
41344
|
-
}
|
|
41345
|
-
if (!response.ok) {
|
|
41346
|
-
throw new Error(`HTTP ${response.status}: ${text || response.statusText}`);
|
|
41347
|
-
}
|
|
41348
|
-
return parsed?.value ?? void 0;
|
|
41349
|
-
}
|
|
41350
|
-
/**
|
|
41351
|
-
* Parse a response body text. Detects the server envelope `{ code, message, data }`.
|
|
41352
|
-
*
|
|
41353
|
-
* @param text - Raw response body text.
|
|
41354
|
-
* @returns `{ envelope: true, code, message, data }` for an envelope body,
|
|
41355
|
-
* `{ envelope: false, value }` for anything else (or `{ envelope: false }` when empty/invalid).
|
|
41356
|
-
*/
|
|
41357
|
-
parseBody(text) {
|
|
41358
|
-
if (!text.trim()) return { envelope: false };
|
|
41359
|
-
try {
|
|
41360
|
-
const value = JSON.parse(text);
|
|
41361
|
-
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
41362
|
-
const record = value;
|
|
41363
|
-
if (typeof record.code === "number") {
|
|
41364
|
-
return {
|
|
41365
|
-
envelope: true,
|
|
41366
|
-
code: record.code,
|
|
41367
|
-
message: typeof record.message === "string" ? record.message : void 0,
|
|
41368
|
-
data: record.data
|
|
41369
|
-
};
|
|
41370
|
-
}
|
|
41371
|
-
}
|
|
41372
|
-
return { envelope: false, value };
|
|
41373
|
-
} catch {
|
|
41374
|
-
return { envelope: false, value: text };
|
|
41375
|
-
}
|
|
41376
|
-
}
|
|
41377
|
-
/**
|
|
41378
|
-
* POST a JSON body to a path.
|
|
41379
|
-
*
|
|
41380
|
-
* @param path - Path appended to the base URL.
|
|
41381
|
-
* @param body - Payload serialized as JSON.
|
|
41382
|
-
* @returns Parsed JSON response body.
|
|
41383
|
-
*/
|
|
41384
|
-
post(path8, body) {
|
|
41385
|
-
return this.request(path8, {
|
|
41386
|
-
method: "POST",
|
|
41387
|
-
headers: { "Content-Type": "application/json" },
|
|
41388
|
-
body: JSON.stringify(body)
|
|
41389
|
-
});
|
|
41390
|
-
}
|
|
41391
|
-
/**
|
|
41392
|
-
* PUT a JSON body to a path.
|
|
41393
|
-
*
|
|
41394
|
-
* @param path - Path appended to the base URL.
|
|
41395
|
-
* @param body - Payload serialized as JSON.
|
|
41396
|
-
* @returns Parsed JSON response body.
|
|
41397
|
-
*/
|
|
41398
|
-
put(path8, body) {
|
|
41399
|
-
return this.request(path8, {
|
|
41400
|
-
method: "PUT",
|
|
41401
|
-
headers: { "Content-Type": "application/json" },
|
|
41402
|
-
body: JSON.stringify(body)
|
|
41403
|
-
});
|
|
41404
|
-
}
|
|
41405
|
-
/**
|
|
41406
|
-
* List all datasources.
|
|
41407
|
-
*
|
|
41408
|
-
* @returns Parsed JSON response body.
|
|
41409
|
-
*/
|
|
41410
|
-
listDatasources() {
|
|
41411
|
-
return this.request("/datasources");
|
|
41412
|
-
}
|
|
41413
|
-
/**
|
|
41414
|
-
* Get table grants for a datasource.
|
|
41415
|
-
*
|
|
41416
|
-
* @param datasourceId - Datasource identifier.
|
|
41417
|
-
* @returns Parsed JSON response body.
|
|
41418
|
-
*/
|
|
41419
|
-
getTableGrants(datasourceId) {
|
|
41420
|
-
return this.request(`/datasources/${encodeURIComponent(datasourceId)}/table-grants`);
|
|
41421
|
-
}
|
|
41422
|
-
/**
|
|
41423
|
-
* Run a read-only SQL query against a datasource.
|
|
41424
|
-
*
|
|
41425
|
-
* @param datasourceId - Datasource identifier.
|
|
41426
|
-
* @param input - Query input: `sql` (SELECT/WITH only), optional `params`, `maxRows`, `debug`.
|
|
41427
|
-
* @returns Parsed JSON response body.
|
|
41428
|
-
* @throws When `sql` fails read-only validation (rejected before any fetch).
|
|
41429
|
-
*/
|
|
41430
|
-
async queryDatasource(datasourceId, input) {
|
|
41431
|
-
const validation = validateSql(input.sql);
|
|
41432
|
-
if (!validation.ok) throw new Error(`SQL_NOT_ALLOWED: ${validation.reason}`);
|
|
41433
|
-
return this.post(`/datasources/${encodeURIComponent(datasourceId)}/query`, input);
|
|
41434
|
-
}
|
|
41435
|
-
/**
|
|
41436
|
-
* Test a datasource connection.
|
|
41437
|
-
*
|
|
41438
|
-
* @param datasourceId - Datasource identifier.
|
|
41439
|
-
* @returns Parsed JSON response body.
|
|
41440
|
-
*/
|
|
41441
|
-
testDatasource(datasourceId) {
|
|
41442
|
-
return this.post(`/datasources/${encodeURIComponent(datasourceId)}/test`, {});
|
|
41443
|
-
}
|
|
41444
|
-
/**
|
|
41445
|
-
* Get connection-pool status for a datasource.
|
|
41446
|
-
*
|
|
41447
|
-
* @param datasourceId - Datasource identifier.
|
|
41448
|
-
* @returns Parsed JSON response body.
|
|
41449
|
-
*/
|
|
41450
|
-
getPoolStatus(datasourceId) {
|
|
41451
|
-
return this.request(`/datasources/${encodeURIComponent(datasourceId)}/pool`);
|
|
41452
|
-
}
|
|
41453
|
-
/**
|
|
41454
|
-
* List table metadata for a datasource, auto-paginating.
|
|
41455
|
-
*
|
|
41456
|
-
* The server pages this collection (`page`/`pageSize`, default page size 20),
|
|
41457
|
-
* so requests aggregate every page into one `{ items, total }` result.
|
|
41458
|
-
*
|
|
41459
|
-
* @param datasourceId - Datasource identifier.
|
|
41460
|
-
* @returns `{ items: [...], total }` covering all pages.
|
|
41461
|
-
*/
|
|
41462
|
-
async listTables(datasourceId) {
|
|
41463
|
-
return this.listMetaPage(`/datasources/${encodeURIComponent(datasourceId)}/meta/tables`);
|
|
41464
|
-
}
|
|
41465
|
-
/**
|
|
41466
|
-
* Shared pagination walk for the paged meta collections (`{items,total,page,pageSize}`).
|
|
41467
|
-
*
|
|
41468
|
-
* @param basePath - Collection path (tables or metrics).
|
|
41469
|
-
* @returns `{ items, total }` aggregated across all pages.
|
|
41470
|
-
*/
|
|
41471
|
-
async listMetaPage(basePath) {
|
|
41472
|
-
const pageSize = 100;
|
|
41473
|
-
const items = [];
|
|
41474
|
-
let total = Number.POSITIVE_INFINITY;
|
|
41475
|
-
for (let page = 1; items.length < total; page += 1) {
|
|
41476
|
-
const body = await this.request(`${basePath}?page=${page}&pageSize=${pageSize}`);
|
|
41477
|
-
const record = body !== null && typeof body === "object" ? body : {};
|
|
41478
|
-
const batch = Array.isArray(record.items) ? record.items : [];
|
|
41479
|
-
items.push(...batch);
|
|
41480
|
-
total = typeof record.total === "number" ? record.total : items.length;
|
|
41481
|
-
if (batch.length === 0) break;
|
|
41482
|
-
}
|
|
41483
|
-
return { items, total: items.length };
|
|
41484
|
-
}
|
|
41485
|
-
/**
|
|
41486
|
-
* Get metadata for a single table.
|
|
41487
|
-
*
|
|
41488
|
-
* @param datasourceId - Datasource identifier.
|
|
41489
|
-
* @param tableKey - Table key.
|
|
41490
|
-
* @returns Parsed JSON response body.
|
|
41491
|
-
*/
|
|
41492
|
-
getTable(datasourceId, tableKey) {
|
|
41493
|
-
return this.request(
|
|
41494
|
-
`/datasources/${encodeURIComponent(datasourceId)}/meta/tables/${encodeURIComponent(tableKey)}`
|
|
41495
|
-
);
|
|
41496
|
-
}
|
|
41497
|
-
/**
|
|
41498
|
-
* Create a table definition for a datasource.
|
|
41499
|
-
*
|
|
41500
|
-
* @param datasourceId - Datasource identifier.
|
|
41501
|
-
* @param payload - Table definition payload.
|
|
41502
|
-
* @returns Parsed JSON response body.
|
|
41503
|
-
*/
|
|
41504
|
-
createTable(datasourceId, payload) {
|
|
41505
|
-
return this.post(`/datasources/${encodeURIComponent(datasourceId)}/meta/tables`, payload);
|
|
41506
|
-
}
|
|
41507
|
-
/**
|
|
41508
|
-
* Update a table definition for a datasource.
|
|
41509
|
-
*
|
|
41510
|
-
* @param datasourceId - Datasource identifier.
|
|
41511
|
-
* @param tableKey - Table key.
|
|
41512
|
-
* @param payload - Table definition payload.
|
|
41513
|
-
* @returns Parsed JSON response body.
|
|
41514
|
-
*/
|
|
41515
|
-
/**
|
|
41516
|
-
* Update a published table meta via read-modify-write.
|
|
41517
|
-
*
|
|
41518
|
-
* The server's PUT replaces the whole payload, so the current payload is
|
|
41519
|
-
* fetched first and the incoming fields are merged on top; fields not
|
|
41520
|
-
* mentioned are preserved.
|
|
41521
|
-
*/
|
|
41522
|
-
async updateTable(datasourceId, tableKey, payload) {
|
|
41523
|
-
const existing = await this.readMetaPayload(`${this.baseUrl}/datasources/${encodeURIComponent(datasourceId)}/meta/tables/${encodeURIComponent(tableKey)}`);
|
|
41524
|
-
return this.put(
|
|
41525
|
-
`/datasources/${encodeURIComponent(datasourceId)}/meta/tables/${encodeURIComponent(tableKey)}`,
|
|
41526
|
-
{ payload: { ...existing, ...payload } }
|
|
41527
|
-
);
|
|
41528
|
-
}
|
|
41529
|
-
/**
|
|
41530
|
-
* List metric definitions for a datasource.
|
|
41531
|
-
*
|
|
41532
|
-
* @param datasourceId - Datasource identifier.
|
|
41533
|
-
* @returns Parsed JSON response body.
|
|
41534
|
-
*/
|
|
41535
|
-
/**
|
|
41536
|
-
* List metric metadata for a datasource, auto-paginating.
|
|
41537
|
-
*
|
|
41538
|
-
* The server pages this collection (`page`/`pageSize`, default page size 20),
|
|
41539
|
-
* so requests aggregate every page into one `{ items, total }` result.
|
|
41540
|
-
*
|
|
41541
|
-
* @param datasourceId - Datasource identifier.
|
|
41542
|
-
* @returns `{ items: [...], total }` covering all pages.
|
|
41543
|
-
*/
|
|
41544
|
-
async listMetrics(datasourceId) {
|
|
41545
|
-
return this.listMetaPage(`/datasources/${encodeURIComponent(datasourceId)}/meta/metrics`);
|
|
41546
|
-
}
|
|
41547
|
-
/**
|
|
41548
|
-
* Get a single metric definition.
|
|
41549
|
-
*
|
|
41550
|
-
* @param datasourceId - Datasource identifier.
|
|
41551
|
-
* @param metricKey - Metric key.
|
|
41552
|
-
* @returns Parsed JSON response body.
|
|
41553
|
-
*/
|
|
41554
|
-
getMetric(datasourceId, metricKey) {
|
|
41555
|
-
return this.request(
|
|
41556
|
-
`/datasources/${encodeURIComponent(datasourceId)}/meta/metrics/${encodeURIComponent(metricKey)}`
|
|
41557
|
-
);
|
|
41558
|
-
}
|
|
41559
|
-
/**
|
|
41560
|
-
* Create a metric definition for a datasource.
|
|
41561
|
-
*
|
|
41562
|
-
* @param datasourceId - Datasource identifier.
|
|
41563
|
-
* @param payload - Metric definition payload.
|
|
41564
|
-
* @returns Parsed JSON response body.
|
|
41565
|
-
*/
|
|
41566
|
-
createMetric(datasourceId, payload) {
|
|
41567
|
-
return this.post(`/datasources/${encodeURIComponent(datasourceId)}/meta/metrics`, payload);
|
|
41568
|
-
}
|
|
41569
|
-
/**
|
|
41570
|
-
* Update a metric definition for a datasource.
|
|
41571
|
-
*
|
|
41572
|
-
* @param datasourceId - Datasource identifier.
|
|
41573
|
-
* @param metricKey - Metric key.
|
|
41574
|
-
* @param payload - Metric definition payload.
|
|
41575
|
-
* @returns Parsed JSON response body.
|
|
41576
|
-
*/
|
|
41577
|
-
/**
|
|
41578
|
-
* Update a published metric meta via read-modify-write.
|
|
41579
|
-
*
|
|
41580
|
-
* The server's PUT replaces the whole payload, so the current payload is
|
|
41581
|
-
* fetched first and the incoming fields are merged on top; fields not
|
|
41582
|
-
* mentioned are preserved.
|
|
41583
|
-
*/
|
|
41584
|
-
async updateMetric(datasourceId, metricKey, payload) {
|
|
41585
|
-
const existing = await this.readMetaPayload(`${this.baseUrl}/datasources/${encodeURIComponent(datasourceId)}/meta/metrics/${encodeURIComponent(metricKey)}`);
|
|
41586
|
-
return this.put(
|
|
41587
|
-
`/datasources/${encodeURIComponent(datasourceId)}/meta/metrics/${encodeURIComponent(metricKey)}`,
|
|
41588
|
-
{ payload: { ...existing, ...payload } }
|
|
41589
|
-
);
|
|
41590
|
-
}
|
|
41591
|
-
/**
|
|
41592
|
-
* Fetch the current `payload` object of a published meta entry.
|
|
41593
|
-
*
|
|
41594
|
-
* The single-entry read returns `{ code, data: [entry] }` (already unwrapped
|
|
41595
|
-
* to the array by {@link request}); the payload lives on the first entry.
|
|
41596
|
-
*
|
|
41597
|
-
* @param absoluteUrl - Full URL of the single-entry meta read.
|
|
41598
|
-
* @returns The stored payload object (empty when none exists).
|
|
41599
|
-
*/
|
|
41600
|
-
async readMetaPayload(absoluteUrl) {
|
|
41601
|
-
const response = await fetch(absoluteUrl, { headers: this.getHeaders() });
|
|
41602
|
-
const text = await response.text().catch(() => "");
|
|
41603
|
-
if (!response.ok) {
|
|
41604
|
-
throw new Error(`HTTP ${response.status}: ${text || response.statusText}`);
|
|
41605
|
-
}
|
|
41606
|
-
const parsed = this.parseBody(text);
|
|
41607
|
-
const data = parsed?.envelope === true ? parsed.data : parsed?.value;
|
|
41608
|
-
const entry = Array.isArray(data) ? data[0] : data;
|
|
41609
|
-
const payload = entry?.payload;
|
|
41610
|
-
return payload !== null && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
41611
|
-
}
|
|
41612
|
-
/**
|
|
41613
|
-
* Get runtime metadata for a datasource.
|
|
41614
|
-
*
|
|
41615
|
-
* @param datasourceId - Datasource identifier.
|
|
41616
|
-
* @returns Parsed JSON response body.
|
|
41617
|
-
*/
|
|
41618
|
-
getRuntimeMeta(datasourceId) {
|
|
41619
|
-
return this.request(`/datasources/${encodeURIComponent(datasourceId)}/meta`);
|
|
41620
|
-
}
|
|
41621
|
-
/**
|
|
41622
|
-
* Run a metrics query.
|
|
41623
|
-
*
|
|
41624
|
-
* @param request - Metrics query request payload.
|
|
41625
|
-
* @returns Parsed JSON response body.
|
|
41626
|
-
*/
|
|
41627
|
-
queryMetrics(request) {
|
|
41628
|
-
return this.post("/metrics/query", request);
|
|
41629
|
-
}
|
|
41630
|
-
/**
|
|
41631
|
-
* Run an ad-hoc custom SQL query, validated as read-only before sending.
|
|
41632
|
-
*
|
|
41633
|
-
* @param request - Request with `datasourceId`, `customSql` (SELECT/WITH only),
|
|
41634
|
-
* and optional `limit` / `debug`.
|
|
41635
|
-
* @returns Parsed JSON response body.
|
|
41636
|
-
* @throws When `customSql` fails read-only validation (rejected before any fetch).
|
|
41637
|
-
*/
|
|
41638
|
-
async customSql(request) {
|
|
41639
|
-
const validation = validateSql(request.customSql);
|
|
41640
|
-
if (!validation.ok) throw new Error(`SQL_NOT_ALLOWED: ${validation.reason}`);
|
|
41641
|
-
return this.post("/metrics/query", request);
|
|
41642
|
-
}
|
|
41643
|
-
};
|
|
41644
|
-
|
|
41645
|
-
// src/tool_lattice/semantic_metrics/metrics_datasource_tool.ts
|
|
41646
|
-
var DESCRIPTION = `PHYSICAL LAYER EXPLORATION \u2014 the only tool for probing raw datasource structure (Builder/Admin only; business agents do not need it).
|
|
41647
|
-
|
|
41648
|
-
OWNS: discovering datasources, reading table-grants (the exploration boundary for this tenant), and running read-only SQL (SELECT/WITH only) to inspect physical tables, columns, sample rows, and value distributions. Also: per-datasource connection test and pool status.
|
|
41649
|
-
|
|
41650
|
-
DOES NOT OWN:
|
|
41651
|
-
- Published semantic assets (table meta / metric meta) \u2192 use metrics_meta_tool.
|
|
41652
|
-
- Runtime meta and business metric queries \u2192 use metrics_runtime_tool.
|
|
41653
|
-
|
|
41654
|
-
USE WHEN: starting a modeling task \u2014 \`list_datasources\` is always the FIRST step: it returns the datasource ids that every other action and tool requires (get_grants, query_sql here; read_semantic_catalog, query_metrics in metrics_runtime_tool; the meta actions in metrics_meta_tool). Read grants next, then probe tables, columns, samples, and distributions within the grant. If a field's business meaning is unclear, probe sample values and distributions here before publishing anything.
|
|
41655
|
-
|
|
41656
|
-
COMMON MISTAKES (do not):
|
|
41657
|
-
- Do not answer business metric questions here (e.g. "monthly sales by region") \u2014 that is metrics_runtime_tool \`query\` against published metrics, NOT this tool's \`query_sql\` (physical-table SQL).
|
|
41658
|
-
- Do not read or publish semantic meta through this tool \u2014 metrics_meta_tool owns the semantic layer.
|
|
41659
|
-
- Do not probe tables outside the tenant's table-grants; un-granted probes are rejected and break the exploration boundary.
|
|
41660
|
-
- Do not attempt writes \u2014 SQL is validated read-only and rejected before sending.`;
|
|
41661
|
-
function createMetricsDatasourceTool(params) {
|
|
41662
|
-
const { connectionType, connections, connectAll } = params;
|
|
41663
|
-
return (0, import_langchain67.tool)(
|
|
41664
|
-
async (input, exeConfig) => {
|
|
41665
|
-
try {
|
|
41666
|
-
const client = await resolveMetricsClientFromSelector(
|
|
41667
|
-
{ connectionType, connections, connectAll },
|
|
41668
|
-
readToolRunConfig(exeConfig) ?? {},
|
|
41669
|
-
input.connectionKey
|
|
41670
|
-
);
|
|
41671
|
-
const scope = effectiveDatasourceScope(client.getSelectedEntities());
|
|
41672
|
-
switch (input.action) {
|
|
41673
|
-
case "list_datasources": {
|
|
41674
|
-
const result = await client.listDatasources();
|
|
41675
|
-
const filtered = scope.unrestricted ? result : result.filter((d) => scope.ids.includes(Number(d.id)));
|
|
41676
|
-
const safe = filtered.map((d) => ({
|
|
41677
|
-
id: d.id,
|
|
41678
|
-
name: d.name,
|
|
41679
|
-
sourceType: d.sourceType,
|
|
41680
|
-
description: d.description,
|
|
41681
|
-
statusLabel: d.statusLabel
|
|
41682
|
-
}));
|
|
41683
|
-
return JSON.stringify(safe, null, 2);
|
|
41684
|
-
}
|
|
41685
|
-
case "get_grants": {
|
|
41686
|
-
const ds = resolveDatasourceId(input, exeConfig);
|
|
41687
|
-
assertDatasourceSelected(scope, ds);
|
|
41688
|
-
const result = await client.getTableGrants(ds);
|
|
41689
|
-
return JSON.stringify(result, null, 2);
|
|
41690
|
-
}
|
|
41691
|
-
case "query_sql": {
|
|
41692
|
-
const ds = resolveDatasourceId(input, exeConfig);
|
|
41693
|
-
assertDatasourceSelected(scope, ds);
|
|
41694
|
-
if (!input.sql) throw new Error("sql is required for the 'query_sql' action");
|
|
41695
|
-
const result = await client.queryDatasource(ds, {
|
|
41696
|
-
sql: input.sql,
|
|
41697
|
-
params: input.params,
|
|
41698
|
-
maxRows: input.maxRows
|
|
41699
|
-
});
|
|
41700
|
-
return JSON.stringify(result, null, 2);
|
|
41701
|
-
}
|
|
41702
|
-
case "test_connection": {
|
|
41703
|
-
const ds = resolveDatasourceId(input, exeConfig);
|
|
41704
|
-
assertDatasourceSelected(scope, ds);
|
|
41705
|
-
const result = await client.testDatasource(ds);
|
|
41706
|
-
return JSON.stringify(result, null, 2);
|
|
41707
|
-
}
|
|
41708
|
-
case "pool_status": {
|
|
41709
|
-
const ds = resolveDatasourceId(input, exeConfig);
|
|
41710
|
-
assertDatasourceSelected(scope, ds);
|
|
41711
|
-
const result = await client.getPoolStatus(ds);
|
|
41712
|
-
return JSON.stringify(result, null, 2);
|
|
41713
|
-
}
|
|
41714
|
-
}
|
|
41715
|
-
} catch (error) {
|
|
41716
|
-
return `Error: ${error instanceof Error ? error.message : String(error)}`;
|
|
41717
|
-
}
|
|
41718
|
-
},
|
|
41719
|
-
{
|
|
41720
|
-
name: "metrics_datasource_tool",
|
|
41721
|
-
description: DESCRIPTION,
|
|
41722
|
-
schema: import_zod55.default.object({
|
|
41723
|
-
action: import_zod55.default.enum(["list_datasources", "get_grants", "query_sql", "test_connection", "pool_status"]).describe(
|
|
41724
|
-
"list_datasources: list datasources \u2014 ALWAYS call this first to obtain the datasource id used by every other action and tool; get_grants: read table-grants; query_sql: run read-only SQL against PHYSICAL tables (note: this is query_sql, NOT the semantic 'query' action of metrics_runtime_tool); test_connection: test the datasource; pool_status: connection-pool status"
|
|
41725
|
-
),
|
|
41726
|
-
connectionKey: import_zod55.default.string().optional().describe("Connection key. Omit when only one semantic-metrics connection exists"),
|
|
41727
|
-
datasourceId: import_zod55.default.coerce.number().optional().describe("Numeric datasource id, e.g. 15 (required for all actions except list_datasources; optional if set in runConfig.metricsDataSource)"),
|
|
41728
|
-
sql: import_zod55.default.string().optional().describe("Read-only SQL (SELECT/WITH only). Required for the query action. Metadata templates \u2014 PostgreSQL/SQL Server columns: select column_name, data_type from information_schema.columns where table_schema = :schemaName and table_name = :tableName order by ordinal_position; HANA columns: select column_name, data_type_name from table_columns where schema_name = :schemaName and table_name = :tableName order by position; distributions: select <dim>, count(*) as row_count from <table> group by <dim> order by row_count desc limit :maxRows"),
|
|
41729
|
-
params: import_zod55.default.record(import_zod55.default.union([import_zod55.default.string(), import_zod55.default.number(), import_zod55.default.boolean()])).optional().describe("Named :param values for the SQL"),
|
|
41730
|
-
maxRows: import_zod55.default.number().optional().describe("Max rows to return")
|
|
41731
|
-
})
|
|
41732
|
-
}
|
|
41733
|
-
);
|
|
41734
|
-
}
|
|
41735
|
-
|
|
41736
|
-
// src/tool_lattice/semantic_metrics/metrics_meta_tool.ts
|
|
41737
|
-
var import_zod56 = __toESM(require("zod"));
|
|
41738
|
-
var import_langchain68 = require("langchain");
|
|
41739
|
-
var DESCRIPTION2 = `SEMANTIC ASSET REGISTRY (Builder/Admin only) \u2014 the only tool for reading and publishing the runtime's semantic layer: table meta (meta/tables) and metric meta (meta/metrics).
|
|
41740
|
-
|
|
41741
|
-
OWNS: listing published tables and metrics, reading one by objectKey, publishing a semantic table (create_table: columns tagged with role dimension|measure), publishing a metric (create_metric: a metric_index payload then a metric_detail payload using the SQL-free calculation DSL), and correcting published assets (update_table / update_metric).
|
|
41742
|
-
|
|
41743
|
-
DOES NOT OWN:
|
|
41744
|
-
- Running queries or reading the aggregated runtime view \u2192 metrics_runtime_tool (get_meta / query / custom_sql).
|
|
41745
|
-
- Probing physical tables, columns, grants, or samples \u2192 metrics_datasource_tool.
|
|
41746
|
-
|
|
41747
|
-
USE WHEN: physical exploration is done and the model has been proposed and confirmed by the user \u2014 to publish the semantic table and metrics, or to correct published assets afterwards.
|
|
41748
|
-
|
|
41749
|
-
COMMON MISTAKES (do not):
|
|
41750
|
-
- Do not call get_meta here \u2014 that action belongs to metrics_runtime_tool, not this tool.
|
|
41751
|
-
- Do not try to "query numbers" through this tool \u2014 list/read actions return definitions only; use metrics_runtime_tool query for data.
|
|
41752
|
-
- Do not publish a metric whose sourceTable has no published table meta, or whose dimensions are not published columns with role dimension \u2014 the server will reject it.
|
|
41753
|
-
- The builder assistant must load the semantic-metrics-modeling skill and pass modelingSkillLoaded: true on write actions; no removal actions are exposed on purpose.`;
|
|
41754
|
-
var MODELING_SKILL_NAME = "semantic-metrics-modeling";
|
|
41755
|
-
var BUILDER_ASSISTANT_ID = "semantic-metrics-builder";
|
|
41756
|
-
function requireModelingSkillLoaded(action, input, exeConfig) {
|
|
41757
|
-
const isWriteAction = action === "create_table" || action === "update_table" || action === "create_metric" || action === "update_metric";
|
|
41758
|
-
if (!isWriteAction) return void 0;
|
|
41759
|
-
const runConfig = readToolRunConfig(exeConfig);
|
|
41760
|
-
const assistantId = runConfig?.assistant_id;
|
|
41761
|
-
if (assistantId === BUILDER_ASSISTANT_ID && input.modelingSkillLoaded !== true) {
|
|
41762
|
-
return JSON.stringify({
|
|
41763
|
-
success: false,
|
|
41764
|
-
error: `Load the '${MODELING_SKILL_NAME}' skill before publishing meta.`
|
|
41765
|
-
});
|
|
41766
|
-
}
|
|
41767
|
-
return void 0;
|
|
41768
|
-
}
|
|
41769
|
-
function actionRequiresPayload(action) {
|
|
41770
|
-
return action === "create_table" || action === "update_table" || action === "create_metric" || action === "update_metric";
|
|
41771
|
-
}
|
|
41772
|
-
function createMetricsMetaTool(params) {
|
|
41773
|
-
const { connectionType, connections, connectAll } = params;
|
|
41774
|
-
return (0, import_langchain68.tool)(
|
|
41775
|
-
async (input, exeConfig) => {
|
|
41776
|
-
try {
|
|
41777
|
-
const guardError = requireModelingSkillLoaded(input.action, input, exeConfig);
|
|
41778
|
-
if (guardError !== void 0) return guardError;
|
|
41779
|
-
const client = await resolveMetricsClientFromSelector(
|
|
41780
|
-
{ connectionType, connections, connectAll },
|
|
41781
|
-
readToolRunConfig(exeConfig) ?? {},
|
|
41782
|
-
input.connectionKey
|
|
41783
|
-
);
|
|
41784
|
-
const ds = resolveDatasourceId(input, exeConfig);
|
|
41785
|
-
assertDatasourceSelected(effectiveDatasourceScope(client.getSelectedEntities()), ds);
|
|
41786
|
-
if (actionRequiresPayload(input.action) && input.payload === void 0) {
|
|
41787
|
-
throw new Error(`payload is required for ${input.action}`);
|
|
41788
|
-
}
|
|
41789
|
-
const payload = input.payload ?? {};
|
|
41790
|
-
switch (input.action) {
|
|
41791
|
-
case "list_tables": {
|
|
41792
|
-
return JSON.stringify(await client.listTables(ds), null, 2);
|
|
41793
|
-
}
|
|
41794
|
-
case "read_table_meta": {
|
|
41795
|
-
if (!input.objectKey) throw new Error("objectKey is required for read_table_meta");
|
|
41796
|
-
return JSON.stringify(await client.getTable(ds, input.objectKey), null, 2);
|
|
41797
|
-
}
|
|
41798
|
-
case "create_table": {
|
|
41799
|
-
return JSON.stringify(await client.createTable(ds, payload), null, 2);
|
|
41800
|
-
}
|
|
41801
|
-
case "update_table": {
|
|
41802
|
-
if (!input.objectKey) throw new Error("objectKey is required for update_table");
|
|
41803
|
-
return JSON.stringify(await client.updateTable(ds, input.objectKey, payload), null, 2);
|
|
41804
|
-
}
|
|
41805
|
-
case "list_metrics": {
|
|
41806
|
-
return JSON.stringify(await client.listMetrics(ds), null, 2);
|
|
41807
|
-
}
|
|
41808
|
-
case "read_metric_meta": {
|
|
41809
|
-
if (!input.objectKey) throw new Error("objectKey is required for read_metric_meta");
|
|
41810
|
-
return JSON.stringify(await client.getMetric(ds, input.objectKey), null, 2);
|
|
41811
|
-
}
|
|
41812
|
-
case "create_metric": {
|
|
41813
|
-
return JSON.stringify(await client.createMetric(ds, payload), null, 2);
|
|
41814
|
-
}
|
|
41815
|
-
case "update_metric": {
|
|
41816
|
-
if (!input.objectKey) throw new Error("objectKey is required for update_metric");
|
|
41817
|
-
return JSON.stringify(await client.updateMetric(ds, input.objectKey, payload), null, 2);
|
|
41818
|
-
}
|
|
41819
|
-
}
|
|
41820
|
-
} catch (error) {
|
|
41821
|
-
return `Error: ${error instanceof Error ? error.message : String(error)}`;
|
|
41822
|
-
}
|
|
41823
|
-
},
|
|
41824
|
-
{
|
|
41825
|
-
name: "metrics_meta_tool",
|
|
41826
|
-
description: DESCRIPTION2,
|
|
41827
|
-
schema: import_zod56.default.object({
|
|
41828
|
-
action: import_zod56.default.enum([
|
|
41829
|
-
"list_tables",
|
|
41830
|
-
"read_table_meta",
|
|
41831
|
-
"create_table",
|
|
41832
|
-
"update_table",
|
|
41833
|
-
"list_metrics",
|
|
41834
|
-
"read_metric_meta",
|
|
41835
|
-
"create_metric",
|
|
41836
|
-
"update_metric"
|
|
41837
|
-
]).describe(
|
|
41838
|
-
"Actions ONLY in this meta tool (runtime query actions like get_meta/query belong to metrics_runtime_tool): list_tables/list_metrics (browse published assets), read_table_meta/read_metric_meta (details by objectKey), create_table/create_metric (publish), update_table/update_metric (correct)"
|
|
41839
|
-
),
|
|
41840
|
-
connectionKey: import_zod56.default.string().optional().describe("Connection key. Omit when only one semantic-metrics connection exists"),
|
|
41841
|
-
datasourceId: import_zod56.default.coerce.number().optional().describe("Numeric datasource id, e.g. 15 (optional if set in runConfig.metricsDataSource)"),
|
|
41842
|
-
objectKey: import_zod56.default.string().optional().describe("Semantic table/metric key (required for read_table_meta/update_table/read_metric_meta/update_metric)"),
|
|
41843
|
-
payload: import_zod56.default.record(import_zod56.default.unknown()).optional().describe("Meta payload (required for create/update actions; objectType/objectKey/status/payload/accessGrant)"),
|
|
41844
|
-
modelingSkillLoaded: import_zod56.default.literal(true).optional().describe("Set true after loading the semantic-metrics-modeling skill (required for the builder assistant on write actions)")
|
|
41845
|
-
})
|
|
41846
|
-
}
|
|
41847
|
-
);
|
|
41848
|
-
}
|
|
41849
|
-
|
|
41850
|
-
// src/tool_lattice/semantic_metrics/metrics_runtime_tool.ts
|
|
41851
|
-
var import_zod57 = __toESM(require("zod"));
|
|
41852
|
-
var import_langchain69 = require("langchain");
|
|
41853
|
-
var DESCRIPTION3 = `RUNTIME QUERY SURFACE \u2014 read what is published and answer business questions with numbers. Business agents use ONLY this tool; Builder agents also use it to verify freshly published metrics.
|
|
41854
|
-
|
|
41855
|
-
OWNS: list_datasources (self-contained datasource discovery \u2014 redacted output, the first step before anything else), read_semantic_catalog (the published semantic model for a datasource: tables, metrics, dimensions, filters) and query_metrics (the semantic metric query: metrics / groupBy / filters / orderBy / limit \u2014 the server generates the SQL, so there is no free-form SQL here).
|
|
41856
|
-
|
|
41857
|
-
DOES NOT OWN:
|
|
41858
|
-
- Publishing or correcting semantic tables/metrics \u2192 metrics_meta_tool (create_table/update_table/create_metric/update_metric/list_tables/read_table_meta/list_metrics/read_metric_meta).
|
|
41859
|
-
- Physical exploration of raw tables, grants, or samples \u2192 metrics_datasource_tool (query_sql).
|
|
41860
|
-
- Free-form custom SQL \u2014 intentionally not provided; use query against published metrics.
|
|
41861
|
-
|
|
41862
|
-
USE WHEN: read_semantic_catalog to see what is published before asking numbers; query_metrics to answer a business question from already-published metrics (Business) or to verify a just-published metric against its acceptance evidence (Builder).
|
|
41863
|
-
|
|
41864
|
-
COMMON MISTAKES (do not):
|
|
41865
|
-
- Do not call meta-tool actions here (create_table / update_table / create_metric / update_metric / list_tables / read_table_meta / list_metrics / read_metric_meta) \u2014 they live in metrics_meta_tool and will fail schema validation here.
|
|
41866
|
-
- Do not look for a custom-SQL action \u2014 there is none; explore physical data with metrics_datasource_tool query_sql, and query business numbers with the semantic query action.
|
|
41867
|
-
- Metrics and dimensions in query_metrics must already be published; querying an unpublished metric fails with "not found in catalog".`;
|
|
41868
|
-
function createMetricsRuntimeTool(params) {
|
|
41869
|
-
const { connectionType, connections, connectAll } = params;
|
|
41870
|
-
return (0, import_langchain69.tool)(
|
|
41871
|
-
async (input, exeConfig) => {
|
|
41872
|
-
try {
|
|
41873
|
-
const client = await resolveMetricsClientFromSelector(
|
|
41874
|
-
{ connectionType, connections, connectAll },
|
|
41875
|
-
readToolRunConfig(exeConfig) ?? {},
|
|
41876
|
-
input.connectionKey
|
|
41877
|
-
);
|
|
41878
|
-
const scope = effectiveDatasourceScope(client.getSelectedEntities());
|
|
41879
|
-
switch (input.action) {
|
|
41880
|
-
case "list_datasources": {
|
|
41881
|
-
const result = await client.listDatasources();
|
|
41882
|
-
const filtered = scope.unrestricted ? result : result.filter((d) => scope.ids.includes(Number(d.id)));
|
|
41883
|
-
const safe = filtered.map((d) => ({
|
|
41884
|
-
id: d.id,
|
|
41885
|
-
name: d.name,
|
|
41886
|
-
sourceType: d.sourceType,
|
|
41887
|
-
description: d.description,
|
|
41888
|
-
statusLabel: d.statusLabel
|
|
41889
|
-
}));
|
|
41890
|
-
return JSON.stringify(safe, null, 2);
|
|
41891
|
-
}
|
|
41892
|
-
case "read_semantic_catalog": {
|
|
41893
|
-
const ds = resolveDatasourceId(input, exeConfig);
|
|
41894
|
-
assertDatasourceSelected(scope, ds);
|
|
41895
|
-
return JSON.stringify(await client.getRuntimeMeta(ds), null, 2);
|
|
41896
|
-
}
|
|
41897
|
-
case "query_metrics": {
|
|
41898
|
-
if (!input.query) throw new Error("query is required for the 'query_metrics' action");
|
|
41899
|
-
const bodyDatasourceId = input.query.datasourceId;
|
|
41900
|
-
if (bodyDatasourceId !== void 0) {
|
|
41901
|
-
assertDatasourceSelected(scope, Number(bodyDatasourceId));
|
|
41902
|
-
}
|
|
41903
|
-
return JSON.stringify(await client.queryMetrics(input.query), null, 2);
|
|
41904
|
-
}
|
|
41905
|
-
}
|
|
41906
|
-
} catch (error) {
|
|
41907
|
-
return `Error: ${error instanceof Error ? error.message : String(error)}`;
|
|
41908
|
-
}
|
|
41909
|
-
},
|
|
41910
|
-
{
|
|
41911
|
-
name: "metrics_runtime_tool",
|
|
41912
|
-
description: DESCRIPTION3,
|
|
41913
|
-
schema: import_zod57.default.object({
|
|
41914
|
-
action: import_zod57.default.enum(["list_datasources", "read_semantic_catalog", "query_metrics"]).describe(
|
|
41915
|
-
"Actions ONLY in this runtime tool: list_datasources (list available datasources \u2014 ALWAYS call this first to obtain the datasourceId; output is redacted to non-sensitive fields), read_semantic_catalog (read the published semantic model: tables, metrics, dimensions), query_metrics (run a semantic metric query \u2014 the only way to get business numbers). Do NOT put meta-tool actions (list_tables/read_table_meta/create_table/update_table/list_metrics/read_metric_meta/create_metric/update_metric) here"
|
|
41916
|
-
),
|
|
41917
|
-
connectionKey: import_zod57.default.string().optional().describe("Connection key. Omit when only one semantic-metrics connection exists"),
|
|
41918
|
-
datasourceId: import_zod57.default.coerce.number().optional().describe("Numeric datasource id, e.g. 15 (required for read_semantic_catalog; optional if set in runConfig.metricsDataSource)"),
|
|
41919
|
-
query: import_zod57.default.record(import_zod57.default.unknown()).optional().describe('Semantic metric query request. Required for the query_metrics action, e.g. { datasourceId: 15, metrics: ["sell_in_nes"], groupBy: ["sales_team"], filters: [{ dimension: "posting_year", operator: "GTE", values: [2024] }], limit: 10 }')
|
|
41920
|
-
})
|
|
41921
|
-
}
|
|
41922
|
-
);
|
|
41923
|
-
}
|
|
41924
|
-
|
|
41925
|
-
// src/middlewares/semanticMetricsModelingSkill.ts
|
|
41926
|
-
var CONTENT = `---
|
|
41927
|
-
name: semantic-metrics-modeling
|
|
41928
|
-
description: Builder policy for turning a granted datasource into published semantic tables and metrics. Defines the orchestrator/worker contract \u2014 the orchestrator agrees goals, proposes the model, plans persistent tasks, and delegates execution to general-purpose workers with self-contained briefs; workers execute one bound brief each. Governs goal agreement, delegation, FEP verification, belief-state reconciliation, and continuous refinement until acceptance evidence is met.
|
|
41929
|
-
---
|
|
41930
|
-
|
|
41931
|
-
# Semantic Metrics Modeling
|
|
41932
|
-
|
|
41933
|
-
You are the Semantic Metrics Builder. You turn physical datasource tables into reusable
|
|
41934
|
-
**semantic tables** and **business metrics** on a Metrics Server (\`/api/v1\`). Work is
|
|
41935
|
-
governed, observable, and continuously refined \u2014 never a one-shot guess.
|
|
41936
|
-
|
|
41937
|
-
You always operate in exactly ONE of two roles:
|
|
41938
|
-
|
|
41939
|
-
- **Orchestrator** (default; no \`## Bound Task\` section in your context): you face the
|
|
41940
|
-
user. You agree the Goal Model, propose the model, plan persistent tasks, dispatch
|
|
41941
|
-
execution to workers, reconcile belief, and own every user interaction.
|
|
41942
|
-
- **Worker** (your context contains a \`## Bound Task\` section naming you executor of one
|
|
41943
|
-
task): you execute that task's brief only. See **Worker mode** \u2014 its rules override the
|
|
41944
|
-
orchestrator policy.
|
|
41945
|
-
|
|
41946
|
-
## Goal Model
|
|
41947
|
-
|
|
41948
|
-
Before any exploration or publishing, agree with the user on:
|
|
41949
|
-
- **Real goal**: the business outcome (which metrics, for what decision), not just "make a table".
|
|
41950
|
-
- **Consumer**: who reads the result and how.
|
|
41951
|
-
- **Usable state**: observable conditions that make the published meta useful.
|
|
41952
|
-
- **Scope**: which datasource/tables, and what is explicitly out of scope.
|
|
41953
|
-
- **Acceptance evidence**: objective criteria (e.g. "metric \`sell_in_nes\` returns sane monthly
|
|
41954
|
-
totals for 2024") used to decide success. Verbatim acceptance evidence is required later by
|
|
41955
|
-
the Verify dispatch \u2014 record it exactly.
|
|
41956
|
-
Do not guess material goals, consumers, or acceptance evidence.
|
|
41957
|
-
|
|
41958
|
-
**Vague requests** (e.g. "build the metric layer") \u2014 do not act and do not ask blind questions.
|
|
41959
|
-
First run cheap read-only observations (\`list_datasources\`, \`get_grants\`, \`list_metrics\`) to
|
|
41960
|
-
see what is authorized and already published, then ask focused questions that carry that
|
|
41961
|
-
context and offer concrete options (which datasource/tables, which business questions, extend
|
|
41962
|
-
existing metrics or build new). Every clarification question must include enough context and
|
|
41963
|
-
options for the user to answer in one step. Only after the user picks a direction does the
|
|
41964
|
-
Goal Model become confirmable \u2014 record it, create the task, and proceed to the workflow.
|
|
41965
|
-
|
|
41966
|
-
## Target model and quality bar
|
|
41967
|
-
|
|
41968
|
-
Your goal is a specific, verifiable artifact, not "some tables and metrics".
|
|
41969
|
-
|
|
41970
|
-
**Target shape** \u2014 one delivery is:
|
|
41971
|
-
- a published \`table_view_detail\` meta per logical table, with every column tagged
|
|
41972
|
-
\`role\` (dimension | measure) and a business-readable \`label\`;
|
|
41973
|
-
- a \`metric_index\` + \`metric_detail\` pair per metric, using the SQL-free \`calculation\` DSL;
|
|
41974
|
-
- the set, taken together, answers the user's concrete business question.
|
|
41975
|
-
|
|
41976
|
-
**Publish gate (self-check every metric before create)** \u2014 if any fails, do **not** publish; go
|
|
41977
|
-
explore or ask the user:
|
|
41978
|
-
1. measure: an aggregation is chosen **and** its business meaning is confirmed (net/gross, currency, dedupe or not);
|
|
41979
|
-
2. dimension: has a business meaning and a grain (day/month/year/\u2026);
|
|
41980
|
-
3. \`displayName\`/\`label\` are business-readable;
|
|
41981
|
-
4. the metric answers one concrete question from the user's stated goal;
|
|
41982
|
-
5. a runtime \`query\` returns numbers consistent with the confirmed meaning.
|
|
41983
|
-
|
|
41984
|
-
**Intent gaps first** \u2014 before diving into exploration, list the inputs you still need to meet the
|
|
41985
|
-
quality bar (business meaning, grain, target metric list, table scope, consumer) and ask for them
|
|
41986
|
-
explicitly. Exploration and user questions are both driven by this target shape and quality bar:
|
|
41987
|
-
missing business meaning \u2192 ask; unclear field semantics \u2192 probe or ask; right shape but it does not
|
|
41988
|
-
answer the business question \u2192 do not publish.
|
|
41989
|
-
|
|
41990
|
-
## FEP Loop
|
|
41991
|
-
|
|
41992
|
-
Apply this loop to every step (explore, publish table, publish metric, verify):
|
|
41993
|
-
**OBSERVE \u2192 HYPOTHESIZE \u2192 ACT \u2192 VERIFY \u2192 DECIDE \u2192 RECONCILE**
|
|
41994
|
-
|
|
41995
|
-
- **Observe**: current state, grants, published meta, and decision-relevant uncertainty.
|
|
41996
|
-
- **Hypothesize**: what evidence should appear if your model is right, and how each outcome changes the decision.
|
|
41997
|
-
- **Act**: one proportional action \u2014 no more than necessary.
|
|
41998
|
-
- **Verify**: compare the observed result (e.g. a runtime \`query\`) against the prediction.
|
|
41999
|
-
- **Decide**: classify as **RETAIN** (confirmed), **REVERT** (rejected), or **INCONCLUSIVE**.
|
|
42000
|
-
- **Reconcile**: update the belief state and plan, then repeat while decision-relevant action remains.
|
|
42001
|
-
|
|
42002
|
-
The orchestrator applies the loop **between dispatches** (each observation updates the plan
|
|
42003
|
-
before the next brief is written). A worker applies it **inside its brief**.
|
|
42004
|
-
|
|
42005
|
-
Renew user approval when a foundational assumption or the goal changes.
|
|
42006
|
-
|
|
42007
|
-
## Orchestrator: Task Policy
|
|
42008
|
-
|
|
42009
|
-
You are an orchestrator, not the hands. Exactly five duties:
|
|
42010
|
-
|
|
42011
|
-
1. **Goal Model agreement** \u2014 including cheap read-only observation for vague requests
|
|
42012
|
-
(\`list_datasources\`, \`get_grants\`, \`list_metrics\`). This is your ONLY inline datasource
|
|
42013
|
-
access; do not use \`write_todos\`.
|
|
42014
|
-
2. **Propose the model** and get user approval.
|
|
42015
|
-
3. **Task tree** \u2014 parent task = contract + \`## Belief State\`; child tasks = independently
|
|
42016
|
-
verifiable outcomes (explore / publish-table / publish-metric / verify), one per dispatch.
|
|
42017
|
-
See the \`task-definition\` skill for \`manage_task\` operation details.
|
|
42018
|
-
4. **Dispatch and collect** \u2014 \`task { taskId, agentId: "general-purpose" }\`; read the
|
|
42019
|
-
observation; record the \`executionResultId\` on the child task with \`manage_task update\` or
|
|
42020
|
-
\`add_activity\`; reconcile \`## Belief State\`.
|
|
42021
|
-
5. **HITL** \u2014 every \`ask_user_to_clarify\` is yours. Workers never ask the user.
|
|
42022
|
-
|
|
42023
|
-
Hard rules:
|
|
42024
|
-
- Never run exploration SQL inline. Never build or publish payloads inline (sole exception:
|
|
42025
|
-
the Publish/Verify inline fallback below).
|
|
42026
|
-
- **Belief State: you are the sole writer.** Workers return findings in their results; you
|
|
42027
|
-
update \`## Belief State\` via \`manage_task update\` on the parent task. Workers never touch it.
|
|
42028
|
-
- **Dispatch serially** \u2014 one worker at a time; reconcile belief before writing the next brief.
|
|
42029
|
-
- **Distinguish dispatch failure from worker outcome**: a dispatch failure is a tool-level
|
|
42030
|
-
error where the worker never ran. A worker returning INCONCLUSIVE or failed is a normal FEP
|
|
42031
|
-
input \u2014 reconcile it, never treat it as a dispatch failure.
|
|
42032
|
-
|
|
42033
|
-
Dispatch failure handling (worker never ran, tool error):
|
|
42034
|
-
1. Retry the dispatch once (recreate the child task if the store reports it unusable).
|
|
42035
|
-
2. **Explore: never execute inline.** If the retry fails, stop and ask the user via
|
|
42036
|
-
\`ask_user_to_clarify\` (report what is blocked and why).
|
|
42037
|
-
3. **Publish/Verify: after a failed retry you MAY execute inline** to preserve delivery \u2014
|
|
42038
|
-
the payload decisions are already in your context. Follow the same gate self-check as a
|
|
42039
|
-
worker would.
|
|
42040
|
-
|
|
42041
|
-
## Delegation Protocol
|
|
42042
|
-
|
|
42043
|
-
Mechanics every brief must be designed around:
|
|
42044
|
-
|
|
42045
|
-
- A worker sees ONLY: its task title + description, the parent task's description, and the
|
|
42046
|
-
results of completed dependency tasks. It does NOT see this conversation.
|
|
42047
|
-
- Therefore **every brief is self-contained**: all decisions, boundaries, and evidence travel
|
|
42048
|
-
inside the task description.
|
|
42049
|
-
- Dispatch is synchronous: \`task { taskId, agentId: "general-purpose" }\` returns an
|
|
42050
|
-
observation (the worker's final message, truncated at ~8k chars) and an
|
|
42051
|
-
\`executionResultId\`. Record the id on the child task (\`manage_task update\`/\`add_activity\`).
|
|
42052
|
-
- The worker settles its own task (\`set_status\` with \`result\`/\`failureReason\`). Read both the
|
|
42053
|
-
observation and the task result before reconciling.
|
|
42054
|
-
|
|
42055
|
-
Write briefs as field checklists adapted to the situation \u2014 decisions and evidence, not prose.
|
|
42056
|
-
The worker assembles payloads from the reference sections of this skill; the brief carries the
|
|
42057
|
-
approved decisions, never full payload JSON.
|
|
42058
|
-
|
|
42059
|
-
### Explore brief (\`Explore <schema>.<table> for <goal>\`)
|
|
42060
|
-
|
|
42061
|
-
Required fields:
|
|
42062
|
-
1. Datasource: serverKey/connectionKey + datasourceId (and \`runConfig.metricsDataSource\` preset if present).
|
|
42063
|
-
2. Grant boundary: the allowed schema + table pattern from \`get_grants\`, verbatim; never probe outside it.
|
|
42064
|
-
3. Target table(s): schema-qualified names; one brief per table.
|
|
42065
|
-
4. Question list: per column (or column group) \u2014 business meaning candidates, expected role
|
|
42066
|
-
(dimension | measure | time), net/gross, grain.
|
|
42067
|
-
5. Method: read-only SELECT/WITH only; use the \`references/metadata-sql.md\` templates
|
|
42068
|
-
(columns, sample rows, value distribution); cap sample size (e.g. \u22641000 rows, \u226450 groups).
|
|
42069
|
-
Prefer targeted queries over bulk catalog dumps. A large single read (e.g. full
|
|
42070
|
-
\`read_semantic_catalog\` detail) is allowed \u2014 your isolation protects the orchestrator's
|
|
42071
|
-
context \u2014 but findings must be compressed to conclusion level.
|
|
42072
|
-
6. Output contract: structured findings \u2014 per column: observed type, sample values,
|
|
42073
|
-
distribution highlights, role candidate + evidence, \`INCONCLUSIVE\` marking for unresolved
|
|
42074
|
-
semantics.
|
|
42075
|
-
7. Invariants: read-only only; grant boundary absolute; never guess \u2014 \`INCONCLUSIVE\` instead.
|
|
42076
|
-
8. Closing: settle the task (\`set_status completed\`, result = findings summary); final message
|
|
42077
|
-
= the structured findings (it becomes the observation).
|
|
42078
|
-
|
|
42079
|
-
### Publish-table brief (\`Publish table meta <objectKey>\`)
|
|
42080
|
-
|
|
42081
|
-
Required fields:
|
|
42082
|
-
1. Approved decisions: full column list (name/type/role/label/description), grain,
|
|
42083
|
-
displayName/docType/shortDesc/sourceSystem/sourceTables.
|
|
42084
|
-
2. Identity: \`objectKey\` (stable, unique per datasource) + \`schemaName.tableName\`.
|
|
42085
|
-
3. Assembly instruction: full \`table_view_detail\` payload per **Publish table meta** below,
|
|
42086
|
-
plus the identity twin (\`table_catalog\`, same \`objectKey\`), plus an EXACT \`accessGrant\`
|
|
42087
|
-
matching the tenant grant.
|
|
42088
|
-
4. Gate self-check: publish gate items 1\u20133 \u2014 do not publish if any fails.
|
|
42089
|
-
5. Publish via \`metrics_meta_tool\` \`create_table\`; then \`get_meta\` to confirm visibility.
|
|
42090
|
-
6. Mistakes: fix with \`update_table\`; never leave a partial publish.
|
|
42091
|
-
7. Invariants: EXACT patternType; every column tagged and labeled.
|
|
42092
|
-
8. Closing: settle the task; final message = receipts (objectKeys + get_meta confirmation).
|
|
42093
|
-
|
|
42094
|
-
### Publish-metric brief (\`Publish metric <objectKey>\`)
|
|
42095
|
-
|
|
42096
|
-
Required fields (per metric):
|
|
42097
|
-
1. Identity: \`objectKey\` = \`metric_name\`, display_name, domain, description, data_type, format.
|
|
42098
|
-
2. Source: schema-qualified \`source.table_view\` (must match the published table meta).
|
|
42099
|
-
3. Calculation: aggregate (\`aggregation\` + \`measure\`, with the confirmed business meaning) or
|
|
42100
|
-
derived (ratio references / formula) \u2014 exactly as approved in Propose the model.
|
|
42101
|
-
4. \`supported_dimensions\`: array of objects \`{dim_id, field_name, label, data_type}\`,
|
|
42102
|
-
including the time dimension.
|
|
42103
|
-
5. \`default_time_context\`: time_dimension + granularity + supported_grains (+ window if requested).
|
|
42104
|
-
6. \`ai_agent_context\`: polarity, synonyms, human_readable_explanation.
|
|
42105
|
-
7. Assembly instruction: \`metric_index\` then \`metric_detail\` in the FULL runtime style per
|
|
42106
|
-
**Publish metric meta** below; publish via \`metrics_meta_tool\` \`create_metric\`.
|
|
42107
|
-
8. Gate self-check + smoke \`query\` (one grouping by the default time grain) + \`get_meta\`
|
|
42108
|
-
receipts; closing = settle the task, final message = receipts.
|
|
42109
|
-
|
|
42110
|
-
### Verify brief (\`Verify <metric> against acceptance evidence\`)
|
|
42111
|
-
|
|
42112
|
-
Required fields:
|
|
42113
|
-
1. Acceptance evidence verbatim (from the Goal Model).
|
|
42114
|
-
2. Queries to run (semantic \`query\` via \`metrics_runtime_tool\`) and the expected shape/values.
|
|
42115
|
-
3. Report contract: PASS/FAIL verdict + actual vs expected; on FAIL include the differences
|
|
42116
|
-
and a suspicion list \u2014 do NOT modify meta (fixes are new Publish tasks).
|
|
42117
|
-
4. Invariants: read-only only.
|
|
42118
|
-
5. Closing: settle the task; final message = the verdict summary.
|
|
42119
|
-
|
|
42120
|
-
### Brief closing (all types)
|
|
42121
|
-
|
|
42122
|
-
- Invariants line: grant boundary + read-only SQL + publish gate before any create.
|
|
42123
|
-
- Result structure: the structured summary the orchestrator expects back.
|
|
42124
|
-
- Finish by settling the task (\`set_status completed\` with result, or \`failed\` with
|
|
42125
|
-
failureReason) and making the final message that structured summary.
|
|
42126
|
-
|
|
42127
|
-
## Worker mode
|
|
42128
|
-
|
|
42129
|
-
Trigger: your context contains \`## Bound Task\`. You are a worker; these rules override the
|
|
42130
|
-
orchestrator policy (Safety and the reference sections still apply):
|
|
42131
|
-
|
|
42132
|
-
- Execute the bound task's brief only. Read the contract with \`manage_task get\`; the task
|
|
42133
|
-
description is authoritative. Load this skill if the bootstrap asks \u2014 you need its payload
|
|
42134
|
-
reference sections.
|
|
42135
|
-
- Do NOT: re-agree the Goal Model, create sibling or child tasks, dispatch \`task\`, call
|
|
42136
|
-
\`ask_user_to_clarify\`, or update the parent task's \`## Belief State\`.
|
|
42137
|
-
- Apply the FEP loop inside the brief; obey the grant boundary and read-only SQL; run the
|
|
42138
|
-
publish gate before any create.
|
|
42139
|
-
- Unclear semantics: mark \`INCONCLUSIVE\` with candidates + evidence in your findings. Never
|
|
42140
|
-
guess, never publish on a guess.
|
|
42141
|
-
- Finish: \`set_status completed\` with a structured result (or \`failed\` with failureReason),
|
|
42142
|
-
and make your final message the structured summary \u2014 it is the observation your
|
|
42143
|
-
orchestrator reads.
|
|
42144
|
-
|
|
42145
|
-
## Belief State (orchestrator-owned)
|
|
42146
|
-
|
|
42147
|
-
The parent task's description carries a \`## Belief State\` section as a Markdown table:
|
|
42148
|
-
|
|
42149
|
-
\`\`\`
|
|
42150
|
-
| Belief Key | Probability | Target | Basis |
|
|
42151
|
-
|---|---|---|---|
|
|
42152
|
-
| sell-in-nes-source-table | 70% | 100% | column \`nes\` probed as numeric measure in grant |
|
|
42153
|
-
\`\`\`
|
|
42154
|
-
|
|
42155
|
-
Rules: belief keys are lowercase kebab-case; probability/target are percentages 0\u2013100% that
|
|
42156
|
-
represent evidence support, not calibrated probability. Only the orchestrator writes this
|
|
42157
|
-
section \u2014 after each dispatch it folds the worker's findings into the table so the parent
|
|
42158
|
-
task always reflects the current evidence.
|
|
42159
|
-
|
|
42160
|
-
## Workflow
|
|
42161
|
-
|
|
42162
|
-
1. **Pick the datasource + cheap observation.** \`metrics_datasource_tool\` action
|
|
42163
|
-
\`list_datasources\`, or the preset \`runConfig.metricsDataSource\` (\`serverKey\`\u2192connectionKey,
|
|
42164
|
-
\`datasourceId\`). Inline, read-only.
|
|
42165
|
-
2. **Agree the Goal Model.** (HITL)
|
|
42166
|
-
3. **Create the parent task** \u2014 contract + \`## Belief State\` (seeded from the Goal Model).
|
|
42167
|
-
4. **Explore by dispatch** \u2014 one Explore brief per table, serial; collect findings; reconcile
|
|
42168
|
-
\`## Belief State\`; collect \`INCONCLUSIVE\` columns.
|
|
42169
|
-
5. **Propose the model** (HITL) \u2014 present table columns (with \`role: dimension | measure\`)
|
|
42170
|
-
and the metrics (aggregate/derived) for approval; include clarify questions for
|
|
42171
|
-
\`INCONCLUSIVE\` columns in the same ask.
|
|
42172
|
-
6. **Publish tables by dispatch** \u2014 one Publish-table brief per table; check receipts.
|
|
42173
|
-
7. **Publish metrics by dispatch** \u2014 one Publish-metric brief per metric; receipts + smoke query.
|
|
42174
|
-
8. **Verify by dispatch** \u2014 Verify brief against acceptance evidence. FAIL \u2192 reconcile
|
|
42175
|
-
belief \u2192 fix decisions \u2192 new Publish task (\`update_table\`/\`update_metric\`) \u2192 re-Verify.
|
|
42176
|
-
PASS \u2192 complete the parent task (result = acceptance evidence met).
|
|
42177
|
-
|
|
42178
|
-
## Explore (reference)
|
|
42179
|
-
|
|
42180
|
-
Read \`table-grants\`, then probe with \`query\`. SQL is validated read-only by the client and the
|
|
42181
|
-
server enforces the grant; un-granted tables return \`TABLE_NOT_GRANTED\`. Prefer the
|
|
42182
|
-
\`references/metadata-sql.md\` templates because dialect varies (PostgreSQL / SQL Server / HANA).
|
|
42183
|
-
If the user provides a data dictionary or sample data file, read it with filesystem and
|
|
42184
|
-
reconcile it against the probed columns.
|
|
42185
|
-
|
|
42186
|
-
## Unclear field semantics
|
|
42187
|
-
|
|
42188
|
-
A probed column name may not reveal its business meaning (e.g. whether \`nes\` is a net amount to
|
|
42189
|
-
sum, a rate to average, or an enum to filter). Publishing meta on a misunderstood field pollutes
|
|
42190
|
-
the runtime and every downstream metric that depends on it, and delete is not available. Treat this
|
|
42191
|
-
as FEP **INCONCLUSIVE** \u2014 never guess, and never publish on an unverified guess.
|
|
42192
|
-
|
|
42193
|
-
Resolve in order of increasing cost (inside the Explore brief):
|
|
42194
|
-
1. **Probe sample values and distribution** (\`query\`, templates in \`references/metadata-sql.md\`):
|
|
42195
|
-
- numbers in (0,1) or clustered near 100 \u2192 likely a ratio/percentage \u2192 dimension or \`avg\`, rarely \`sum\`;
|
|
42196
|
-
- large additive amounts (currency, counts) \u2192 measure with \`sum\`;
|
|
42197
|
-
- small enumerations (year 2023/2024, 0/1 flags, codes) \u2192 dimension.
|
|
42198
|
-
The share of zeros/negatives and the value scale usually disambiguate semantics.
|
|
42199
|
-
2. **Read user-provided docs**: if the user supplied a data dictionary or sample file, read it via
|
|
42200
|
-
filesystem and reconcile it against the probed columns.
|
|
42201
|
-
3. **Cross-field correlation**: compare the unclear field with fields whose semantics are confirmed.
|
|
42202
|
-
|
|
42203
|
-
If evidence is still INCONCLUSIVE:
|
|
42204
|
-
- Do **not** publish meta that depends on the unclear field.
|
|
42205
|
-
- The worker marks the column \`INCONCLUSIVE\` (candidates + evidence) in its findings; the
|
|
42206
|
-
**orchestrator** lists it with candidate interpretations in the **Propose the model** step
|
|
42207
|
-
and asks the user to confirm its semantics (role, value meaning, net/gross) via
|
|
42208
|
-
\`ask_user_to_clarify\`. The user does not need to see the table \u2014 probed schema, samples, and
|
|
42209
|
-
candidates are enough.
|
|
42210
|
-
- The orchestrator records a low-probability belief entry (e.g.
|
|
42211
|
-
\`| sales-nes-semantics | 40% | 100% | user must confirm role / net amount |\`) so verify/refine
|
|
42212
|
-
can revisit it later instead of assuming it is settled.
|
|
42213
|
-
|
|
42214
|
-
## Publish table meta (\`create_table\`)
|
|
42215
|
-
|
|
42216
|
-
Publish the authoritative shape below (objectType \`table_view_detail\`, with an EXACT accessGrant):
|
|
42217
|
-
|
|
42218
|
-
\`\`\`json
|
|
42219
|
-
{
|
|
42220
|
-
"objectType": "table_view_detail",
|
|
42221
|
-
"objectKey": "hankel_view_sales_summary",
|
|
42222
|
-
"status": 1,
|
|
42223
|
-
"payload": {
|
|
42224
|
-
"schemaName": "public",
|
|
42225
|
-
"tableName": "hankel_view_sales_summary",
|
|
42226
|
-
"displayName": "Hankel Sales Summary",
|
|
42227
|
-
"docType": "Sales Summary",
|
|
42228
|
-
"docTypeEn": "Sales Summary",
|
|
42229
|
-
"shortDesc": "Sales-level progress summary.",
|
|
42230
|
-
"grain": "canonical_sales_name",
|
|
42231
|
-
"sourceSystem": "Hankel Run for Gold",
|
|
42232
|
-
"sourceTables": ["hankel_project_opportunity_lines", "hankel_new_order_lines"],
|
|
42233
|
-
"columns": [
|
|
42234
|
-
{ "name": "canonical_sales_name", "label": "Canonical Sales Name", "type": "string", "role": "dimension", "description": "Standardized sales name used for grouping." },
|
|
42235
|
-
{ "name": "nes", "label": "NES", "type": "number", "role": "measure", "description": "Net external sales amount." },
|
|
42236
|
-
{ "name": "report_cutoff_date", "label": "Report Cutoff Date", "type": "date", "role": "time", "description": "Cutoff date of the report snapshot." }
|
|
42237
|
-
]
|
|
42238
|
-
},
|
|
42239
|
-
"accessGrant": {
|
|
42240
|
-
"schemaName": "public",
|
|
42241
|
-
"tablePattern": "hankel_view_sales_summary",
|
|
42242
|
-
"patternType": "EXACT",
|
|
42243
|
-
"caseSensitive": false,
|
|
42244
|
-
"status": 1
|
|
42245
|
-
}
|
|
42246
|
-
}
|
|
42247
|
-
\`\`\`
|
|
42248
|
-
|
|
42249
|
-
Design rules:
|
|
42250
|
-
- \`objectKey\` is stable and unique per datasource (the view/table key).
|
|
42251
|
-
- \`columns[].role\` has THREE values: \`dimension\` (grouping/filtering), \`measure\` (aggregated numbers), \`time\` (the report cutoff/snapshot date used by default_time_context).
|
|
42252
|
-
- Give every column a business \`description\`.
|
|
42253
|
-
- Lineage fields (\`docType\`, \`shortDesc\`, \`grain\`, \`sourceSystem\`, \`sourceTables\`) make the asset findable and trustworthy \u2014 fill them from exploration evidence.
|
|
42254
|
-
- Runtime table publication uses \`patternType: "EXACT"\` (\`PREFIX\` is only for datasource-level exploration scopes).
|
|
42255
|
-
- For each semantic table also publish the identity twin: the same body with \`objectType: "table_catalog"\` and the same \`objectKey\` (same or richer payload).
|
|
42256
|
-
|
|
42257
|
-
## Publish metric meta (\`create_metric\`)
|
|
42258
|
-
|
|
42259
|
-
Two steps for the same \`objectKey\`.
|
|
42260
|
-
|
|
42261
|
-
### 3a. Metric index (for lists/search)
|
|
42262
|
-
|
|
42263
|
-
\`\`\`json
|
|
42264
|
-
{
|
|
42265
|
-
"objectType": "metric_index",
|
|
42266
|
-
"objectKey": "sell_in_nes",
|
|
42267
|
-
"status": 1,
|
|
42268
|
-
"payload": {
|
|
42269
|
-
"metric_name": "sell_in_nes",
|
|
42270
|
-
"display_name": "Sell-in NES",
|
|
42271
|
-
"domain": "sales",
|
|
42272
|
-
"short_desc": "Net external sales amount from distributor sell-in rows.",
|
|
42273
|
-
"search_keywords": ["sell in", "nes", "net external sales"],
|
|
42274
|
-
"source_type": "cdp_postgres",
|
|
42275
|
-
"source": { "table_view": "public.hankel_distr_sell_in" }
|
|
42276
|
-
}
|
|
42277
|
-
}
|
|
42278
|
-
\`\`\`
|
|
42279
|
-
|
|
42280
|
-
\`search_keywords\` drive metric retrieval for natural-language questions \u2014 include business synonyms.
|
|
42281
|
-
|
|
42282
|
-
### 3b. Metric detail (the calculation)
|
|
42283
|
-
|
|
42284
|
-
IMPORTANT \u2014 runtime schema requirement: the Metrics Server query runtime only recognizes metrics
|
|
42285
|
-
published in the FULL runtime style below (the same shape as existing working metrics, with
|
|
42286
|
-
snake_case fields like \`metric_name\`, \`source.table_view\`, \`supported_dimensions\` objects, and
|
|
42287
|
-
\`default_time_context\`). A minimal \`{name, sourceTable, calculation, dimensions}\` payload is
|
|
42288
|
-
accepted by the publish API but is NOT queryable \u2014 querying it returns 403 "not authorized".
|
|
42289
|
-
|
|
42290
|
-
Aggregate metric (full runtime style):
|
|
42291
|
-
|
|
42292
|
-
\`\`\`json
|
|
42293
|
-
{
|
|
42294
|
-
"objectType": "metric_detail",
|
|
42295
|
-
"objectKey": "sell_in_nes",
|
|
42296
|
-
"status": 1,
|
|
42297
|
-
"payload": {
|
|
42298
|
-
"metric_name": "sell_in_nes",
|
|
42299
|
-
"display_name": "Sell-in NES",
|
|
42300
|
-
"domain": "sales",
|
|
42301
|
-
"description": "Net external sales amount from distributor sell-in rows.",
|
|
42302
|
-
"data_type": "numeric",
|
|
42303
|
-
"format": "currency",
|
|
42304
|
-
"source_type": "cdp_postgres",
|
|
42305
|
-
"source": { "table_view": "public.hankel_distr_sell_in", "base_filters": [] },
|
|
42306
|
-
"calculation": { "type": "aggregate", "aggregation": "sum", "measure": "nes" },
|
|
42307
|
-
"supported_dimensions": [
|
|
42308
|
-
{ "dim_id": "posting_year", "field_name": "posting_year", "label": "Posting Year", "data_type": "number" },
|
|
42309
|
-
{ "dim_id": "sales_team", "field_name": "sales_team", "label": "Sales Team", "data_type": "string" }
|
|
42310
|
-
],
|
|
42311
|
-
"default_time_context": {
|
|
42312
|
-
"time_dimension": "posting_date",
|
|
42313
|
-
"label": "Posting date",
|
|
42314
|
-
"granularity": "month",
|
|
42315
|
-
"window": "YTD",
|
|
42316
|
-
"supported_grains": ["month", "year"]
|
|
42317
|
-
},
|
|
42318
|
-
"ai_agent_context": {
|
|
42319
|
-
"polarity": "positive",
|
|
42320
|
-
"synonyms": ["sell in", "nes", "net external sales"],
|
|
42321
|
-
"human_readable_explanation": "Higher sell-in NES means more goods purchased from the distributor."
|
|
42322
|
-
}
|
|
42323
|
-
}
|
|
42324
|
-
}
|
|
42325
|
-
\`\`\`
|
|
42326
|
-
|
|
42327
|
-
Derived ratio metric (references two aggregate metrics):
|
|
42328
|
-
|
|
42329
|
-
\`\`\`json
|
|
42330
|
-
{
|
|
42331
|
-
"objectType": "metric_detail",
|
|
42332
|
-
"objectKey": "gross_margin_rate",
|
|
42333
|
-
"status": 1,
|
|
42334
|
-
"payload": {
|
|
42335
|
-
"metric_name": "gross_margin_rate",
|
|
42336
|
-
"display_name": "Gross Margin Rate",
|
|
42337
|
-
"description": "Gross margin divided by sell-in NES.",
|
|
42338
|
-
"domain": "sales",
|
|
42339
|
-
"data_type": "numeric",
|
|
42340
|
-
"format": "percent",
|
|
42341
|
-
"source_type": "cdp_postgres",
|
|
42342
|
-
"source": { "table_view": "public.hankel_distr_sell_in", "base_filters": [] },
|
|
42343
|
-
"calculation": { "type": "derived", "operator": "ratio", "numerator": "gross_margin", "denominator": "sell_in_nes" },
|
|
42344
|
-
"supported_dimensions": [
|
|
42345
|
-
{ "dim_id": "posting_year", "field_name": "posting_year", "label": "Posting Year", "data_type": "number" }
|
|
42346
|
-
],
|
|
42347
|
-
"default_time_context": { "time_dimension": "posting_date", "granularity": "month", "supported_grains": ["month", "year"] }
|
|
42348
|
-
}
|
|
42349
|
-
}
|
|
42350
|
-
\`\`\`
|
|
42351
|
-
|
|
42352
|
-
Design rules:
|
|
42353
|
-
- \`objectKey\` unique per datasource (index and detail share it).
|
|
42354
|
-
- \`payload.metric_name\` must equal \`objectKey\`.
|
|
42355
|
-
- \`source.table_view\` must be schema-qualified and match the published table meta's physical table.
|
|
42356
|
-
- \`supported_dimensions\` is an array of OBJECTS ({dim_id, field_name, label, data_type}); include the time dimension too; each must be a published column of that table meta.
|
|
42357
|
-
- \`calculation.type: "aggregate"\` = one measure + aggregation (sum/avg/count/min/max/count_distinct).
|
|
42358
|
-
- \`calculation.type: "derived"\` operator \`ratio\` references existing metric objectKeys (numerator/denominator); a \`formula\` variant takes an expression of metric names, numbers, parentheses, and + - * / \u2014 referenced metrics must share the same source.table_view.
|
|
42359
|
-
- \`default_time_context\` (\`time_dimension\` + \`granularity\` + \`supported_grains\`, optionally \`window\`) is required by the query runtime; its \`time_dimension\` must appear in supported_dimensions.
|
|
42360
|
-
- \`ai_agent_context\` (\`polarity\`, \`synonyms\`, \`human_readable_explanation\`) improves natural-language metric retrieval \u2014 always provide it.
|
|
42361
|
-
- One semantic query can only combine metrics sharing the same source.table_view; groupBy values must be dim_ids or time-grain expressions like \`posting_date__month\`.
|
|
42362
|
-
- Do not inline raw SQL for new DB-backed metrics (complex logic belongs in a view).
|
|
42363
|
-
- Use \`update_metric\` / \`update_table\` to correct mistakes; no removal actions are exposed.
|
|
42364
|
-
|
|
42365
|
-
## Verify and refine
|
|
42366
|
-
|
|
42367
|
-
- Verify is **dispatched** (Verify brief). The worker runs \`get_meta\` \u2192 confirms the table and
|
|
42368
|
-
metric are visible, then \`query\`es the metric against acceptance evidence.
|
|
42369
|
-
- On FAIL the worker reports differences; the **orchestrator** applies the FEP reconcile:
|
|
42370
|
-
update \`## Belief State\`, fix the decisions, and dispatch a new Publish task
|
|
42371
|
-
(\`update_table\`/\`update_metric\`) \u2014 then re-Verify \u2014 until acceptance evidence is met.
|
|
42372
|
-
|
|
42373
|
-
## Troubleshooting
|
|
42374
|
-
|
|
42375
|
-
| Symptom | Cause / fix |
|
|
42376
|
-
|---|---|
|
|
42377
|
-
| \`TABLE_NOT_GRANTED\` | SQL referenced a table outside the tenant grant; pick an in-grant table |
|
|
42378
|
-
| metric create fails: sourceTable missing | publish the table meta first |
|
|
42379
|
-
| metric create fails: unknown dimension | publish the dimension column with \`role: dimension\` |
|
|
42380
|
-
| derived metric create fails | numerator/denominator metrics don't exist yet \u2014 publish them first |
|
|
42381
|
-
| datasource \`query\` rejected | SQL was not read-only (SELECT/WITH only) or multi-statement |
|
|
42382
|
-
| \`403 Metric is not authorized\` on query_metrics | the metric meta is not in the queryable runtime schema (e.g. missing \`source.table_view\` / \`supported_dimensions\` / \`default_time_context\`) or genuinely unauthorized \u2014 re-publish with the full runtime payload and verify; never retry blindly |
|
|
42383
|
-
| worker observation truncated | findings exceeded ~8k chars; worker must keep the final message a compact structured summary |
|
|
42384
|
-
| dispatch failed (tool error) | retry once; Explore never goes inline \u2014 ask the user; Publish/Verify may go inline after the failed retry |
|
|
42385
|
-
|
|
42386
|
-
## Safety
|
|
42387
|
-
|
|
42388
|
-
- Only query tables that match the tenant's \`table-grants\`.
|
|
42389
|
-
- Never return a full physical-table inventory or reveal whether an un-granted table exists.
|
|
42390
|
-
- SQL is validated read-only; let the server reject anything outside that.
|
|
42391
|
-
`;
|
|
42392
|
-
var resources = {
|
|
42393
|
-
"references/metadata-sql.md": {
|
|
42394
|
-
content: `# Datasource exploration SQL templates (read-only)
|
|
42395
|
-
|
|
42396
|
-
Pick the block matching the server's database. These run through the datasource \`query\` action;
|
|
42397
|
-
the SQL is validated read-only.
|
|
42398
|
-
|
|
42399
|
-
## PostgreSQL
|
|
42400
|
-
- Tables: \`select table_schema, table_name from information_schema.tables where table_schema not in ('pg_catalog','information_schema') order by table_schema, table_name\`
|
|
42401
|
-
- Columns: \`select column_name, data_type from information_schema.columns where table_schema = :schemaName and table_name = :tableName order by ordinal_position\`
|
|
42402
|
-
- Sample: \`select * from :schemaName.:tableName limit :maxRows\` \u2014 pass a concrete table, not a bound param, if the server does not support binding identifiers.
|
|
42403
|
-
|
|
42404
|
-
## SQL Server
|
|
42405
|
-
- Tables: \`select table_schema, table_name from information_schema.tables order by table_schema, table_name\`
|
|
42406
|
-
- Columns: \`select column_name, data_type from information_schema.columns where table_schema = :schemaName and table_name = :tableName order by ordinal_position\`
|
|
42407
|
-
|
|
42408
|
-
## HANA
|
|
42409
|
-
- Tables: \`select schema_name, table_name from sys.tables where schema_name = :schemaName order by table_name\`
|
|
42410
|
-
- Columns: \`select column_name, data_type_name from table_columns where schema_name = :schemaName and table_name = :tableName order by position\`
|
|
42411
|
-
|
|
42412
|
-
## Value distribution (any dialect)
|
|
42413
|
-
\`select <dim>, count(*) as row_count from <table> group by <dim> order by row_count desc limit :maxRows\`
|
|
42414
|
-
`
|
|
42415
|
-
},
|
|
42416
|
-
"examples/table-meta.json": {
|
|
42417
|
-
content: `{
|
|
42418
|
-
"objectType": "table_view_detail",
|
|
42419
|
-
"objectKey": "hankel_distr_sell_in",
|
|
42420
|
-
"status": 1,
|
|
42421
|
-
"payload": {
|
|
42422
|
-
"schemaName": "public",
|
|
42423
|
-
"tableName": "hankel_distr_sell_in",
|
|
42424
|
-
"displayName": "Hankel Distributor Sell In",
|
|
42425
|
-
"description": "Distributor sell-in transaction rows for the Hankel tenant.",
|
|
42426
|
-
"columns": [
|
|
42427
|
-
{ "name": "posting_year", "label": "Posting Year", "type": "number", "role": "dimension" },
|
|
42428
|
-
{ "name": "posting_month", "label": "Posting Month", "type": "number", "role": "dimension" },
|
|
42429
|
-
{ "name": "sales_team", "label": "Sales Team", "type": "string", "role": "dimension" },
|
|
42430
|
-
{ "name": "region", "label": "Region", "type": "string", "role": "dimension" },
|
|
42431
|
-
{ "name": "nes", "label": "Net External Sales", "type": "number", "role": "measure" },
|
|
42432
|
-
{ "name": "gross_margin", "label": "Gross Margin", "type": "number", "role": "measure" }
|
|
42433
|
-
]
|
|
42434
|
-
}
|
|
42435
|
-
}
|
|
42436
|
-
`
|
|
42437
|
-
},
|
|
42438
|
-
"examples/metric-aggregate.json": {
|
|
42439
|
-
content: `{
|
|
42440
|
-
"objectType": "metric_detail",
|
|
42441
|
-
"objectKey": "sell_in_nes",
|
|
42442
|
-
"status": 1,
|
|
42443
|
-
"payload": {
|
|
42444
|
-
"metric_name": "sell_in_nes",
|
|
42445
|
-
"display_name": "Sell-in NES",
|
|
42446
|
-
"domain": "sales",
|
|
42447
|
-
"description": "Net external sales amount from distributor sell-in rows.",
|
|
42448
|
-
"data_type": "numeric",
|
|
42449
|
-
"format": "currency",
|
|
42450
|
-
"source_type": "cdp_postgres",
|
|
42451
|
-
"source": { "table_view": "public.hankel_distr_sell_in", "base_filters": [] },
|
|
42452
|
-
"calculation": { "type": "aggregate", "aggregation": "sum", "measure": "nes" },
|
|
42453
|
-
"supported_dimensions": [
|
|
42454
|
-
{ "dim_id": "posting_year", "field_name": "posting_year", "label": "Posting Year", "data_type": "number" },
|
|
42455
|
-
{ "dim_id": "sales_team", "field_name": "sales_team", "label": "Sales Team", "data_type": "string" },
|
|
42456
|
-
{ "dim_id": "posting_date", "field_name": "posting_date", "label": "Posting Date", "data_type": "string" }
|
|
42457
|
-
],
|
|
42458
|
-
"default_time_context": {
|
|
42459
|
-
"time_dimension": "posting_date",
|
|
42460
|
-
"label": "Posting date",
|
|
42461
|
-
"granularity": "month",
|
|
42462
|
-
"window": "YTD",
|
|
42463
|
-
"supported_grains": ["month", "year"]
|
|
42464
|
-
},
|
|
42465
|
-
"ai_agent_context": {
|
|
42466
|
-
"polarity": "positive",
|
|
42467
|
-
"synonyms": ["sell in", "nes", "net external sales"],
|
|
42468
|
-
"human_readable_explanation": "Higher sell-in NES means more goods purchased from the distributor."
|
|
42469
|
-
}
|
|
42470
|
-
}
|
|
42471
|
-
}
|
|
42472
|
-
`
|
|
42473
|
-
},
|
|
42474
|
-
"examples/metric-derived.json": {
|
|
42475
|
-
content: `{
|
|
42476
|
-
"objectType": "metric_detail",
|
|
42477
|
-
"objectKey": "gross_margin_rate",
|
|
42478
|
-
"status": 1,
|
|
42479
|
-
"payload": {
|
|
42480
|
-
"metric_name": "gross_margin_rate",
|
|
42481
|
-
"display_name": "Gross Margin Rate",
|
|
42482
|
-
"domain": "sales",
|
|
42483
|
-
"description": "Gross margin divided by sell-in NES.",
|
|
42484
|
-
"data_type": "numeric",
|
|
42485
|
-
"format": "percent",
|
|
42486
|
-
"source_type": "cdp_postgres",
|
|
42487
|
-
"source": { "table_view": "public.hankel_distr_sell_in", "base_filters": [] },
|
|
42488
|
-
"calculation": { "type": "derived", "operator": "ratio", "numerator": "gross_margin", "denominator": "sell_in_nes" },
|
|
42489
|
-
"supported_dimensions": [
|
|
42490
|
-
{ "dim_id": "posting_year", "field_name": "posting_year", "label": "Posting Year", "data_type": "number" },
|
|
42491
|
-
{ "dim_id": "posting_date", "field_name": "posting_date", "label": "Posting Date", "data_type": "string" }
|
|
42492
|
-
],
|
|
42493
|
-
"default_time_context": {
|
|
42494
|
-
"time_dimension": "posting_date",
|
|
42495
|
-
"label": "Posting date",
|
|
42496
|
-
"granularity": "month",
|
|
42497
|
-
"supported_grains": ["month", "year"]
|
|
42498
|
-
},
|
|
42499
|
-
"ai_agent_context": {
|
|
42500
|
-
"polarity": "positive",
|
|
42501
|
-
"synonyms": ["gross margin rate", "margin rate"],
|
|
42502
|
-
"human_readable_explanation": "Gross margin rate divides gross margin by sell-in NES; higher means more margin retained on sold-in goods."
|
|
42503
|
-
}
|
|
42504
|
-
}
|
|
42505
|
-
}
|
|
42506
|
-
`
|
|
42507
|
-
}
|
|
42508
|
-
};
|
|
42509
|
-
var SEMANTIC_METRICS_MODELING_SKILL = {
|
|
42510
|
-
version: "1.1.2",
|
|
42511
|
-
content: CONTENT,
|
|
42512
|
-
resources
|
|
42513
|
-
};
|
|
42514
|
-
|
|
42515
|
-
// src/middlewares/semanticMetricsBuilderPrompt.ts
|
|
42516
|
-
var SEMANTIC_METRICS_BUILDER_PROMPT = `You are the Semantic Metrics Builder.
|
|
42517
|
-
|
|
42518
|
-
CRITICAL FIRST ACTION: Before any response or other action, call the \`skill\`
|
|
42519
|
-
tool with skill_name: "semantic-metrics-modeling" to load semantic-metrics-modeling and follow it.
|
|
42520
|
-
Never announce the skill load. If it fails, retry once, then stop and explicitly
|
|
42521
|
-
report that the required Semantic Metrics Builder skill could not be loaded.`;
|
|
42522
|
-
|
|
42523
|
-
// src/middlewares/semanticMetricsMiddleware.ts
|
|
42524
|
-
var import_protocols33 = require("@axiom-lattice/protocols");
|
|
42525
|
-
function createSemanticMetricsMiddleware(config) {
|
|
42526
|
-
const connections = config.connections ?? [];
|
|
42527
|
-
const connectAll = config.connectAll === true;
|
|
42528
|
-
const selector = { connectionType: "semantic-metrics", connections, connectAll };
|
|
42529
|
-
return (0, import_langchain70.createMiddleware)({
|
|
42530
|
-
name: "SemanticMetrics",
|
|
42531
|
-
contextSchema,
|
|
42532
|
-
tools: [
|
|
42533
|
-
createMetricsDatasourceTool(selector),
|
|
42534
|
-
createMetricsMetaTool(selector),
|
|
42535
|
-
createMetricsRuntimeTool(selector)
|
|
42536
|
-
]
|
|
42537
|
-
});
|
|
42538
|
-
}
|
|
42539
|
-
function buildConnectionHeaders(config) {
|
|
42540
|
-
const headers = {
|
|
42541
|
-
Accept: "application/json",
|
|
42542
|
-
...config.headers !== void 0 && config.headers !== null ? config.headers : {}
|
|
42543
|
-
};
|
|
42544
|
-
if (config.apiKey) headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
42545
|
-
return headers;
|
|
42546
|
-
}
|
|
42547
|
-
function resolveBaseUrl(config) {
|
|
42548
|
-
const serverUrl = config.serverUrl;
|
|
42549
|
-
if (!serverUrl) {
|
|
42550
|
-
throw new Error("serverUrl is required");
|
|
42551
|
-
}
|
|
42552
|
-
return serverUrl.replace(/\/$/, "");
|
|
42553
|
-
}
|
|
42554
|
-
var semanticMetricsPlugin = {
|
|
42555
|
-
meta: {
|
|
42556
|
-
type: "semantic-metrics",
|
|
42557
|
-
category: "data",
|
|
42558
|
-
capabilityBundleEligible: true,
|
|
42559
|
-
openExpose: [
|
|
42560
|
-
// Query-only surface: no writes reach either tool (SQL is read-only).
|
|
42561
|
-
{ name: "metrics_datasource_tool", readOnly: true },
|
|
42562
|
-
{ name: "metrics_runtime_tool", readOnly: true }
|
|
42563
|
-
],
|
|
42564
|
-
name: "Semantic Metrics",
|
|
42565
|
-
description: "Semantic metrics datasource exploration, meta publishing, and runtime querying. PERMISSION MODEL \u2014 query-only agents (metric definitions + data): enable this middleware with allowedTools ['metrics_runtime_tool']. Metric designers (Builder): keep all three tools (metrics_datasource_tool, metrics_meta_tool, metrics_runtime_tool) for exploration, publishing, and verification, or use the built-in 'semantic-metrics-builder' agent.",
|
|
42566
|
-
version: "1.0.0",
|
|
42567
|
-
tools: [
|
|
42568
|
-
{ name: "metrics_datasource_tool", description: "Explore datasource structure within the tenant's granted scope" },
|
|
42569
|
-
{ name: "metrics_meta_tool", description: "Publish and maintain runtime semantic tables and metrics" },
|
|
42570
|
-
{ name: "metrics_runtime_tool", description: "Read runtime meta and execute semantic metric queries" }
|
|
42571
|
-
],
|
|
42572
|
-
configSchema: {
|
|
42573
|
-
type: "object",
|
|
42574
|
-
title: "Semantic Metrics Configuration",
|
|
42575
|
-
description: "First select connections (connections or connectAll). Then scope tools by role via allowedTools: QUERY-ONLY agents (metric definitions + data) set allowedTools to ['metrics_runtime_tool'] \u2014 it is self-contained (list_datasources, read_semantic_catalog, query_metrics); metric DESIGNERS keep all three tools (datasource exploration, meta publishing, runtime verification).",
|
|
42576
|
-
properties: {
|
|
42577
|
-
connections: {
|
|
42578
|
-
type: "array",
|
|
42579
|
-
title: "Connections",
|
|
42580
|
-
items: { type: "string" },
|
|
42581
|
-
widget: "connectionSelect"
|
|
42582
|
-
},
|
|
42583
|
-
connectAll: {
|
|
42584
|
-
type: "boolean",
|
|
42585
|
-
title: "Connect All",
|
|
42586
|
-
default: false,
|
|
42587
|
-
widget: "switch"
|
|
42588
|
-
}
|
|
42589
|
-
}
|
|
42590
|
-
},
|
|
42591
|
-
defaultConfig: { connections: [], connectAll: false }
|
|
42592
|
-
},
|
|
42593
|
-
connection: {
|
|
42594
|
-
// PluginConnectionFieldSchema.type supports only string/number/boolean/password,
|
|
42595
|
-
// so headers is NOT a form field; the V2 client still reads config.headers at runtime.
|
|
42596
|
-
fields: [
|
|
42597
|
-
{ key: "serverUrl", type: "string", title: "Metrics Server Base URL (include /api/v1)", required: true },
|
|
42598
|
-
{ key: "apiKey", type: "password", title: "API Key (optional)" }
|
|
42599
|
-
],
|
|
42600
|
-
test: async (config) => {
|
|
42601
|
-
try {
|
|
42602
|
-
const baseUrl = resolveBaseUrl(config);
|
|
42603
|
-
const res = await fetch(`${baseUrl}/datasources`, {
|
|
42604
|
-
headers: buildConnectionHeaders(config)
|
|
42605
|
-
});
|
|
42606
|
-
const text = await res.text().catch(() => "");
|
|
42607
|
-
let ok = res.ok;
|
|
42608
|
-
let detail = "";
|
|
42609
|
-
try {
|
|
42610
|
-
const parsed = JSON.parse(text);
|
|
42611
|
-
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
42612
|
-
const code = parsed.code;
|
|
42613
|
-
if (typeof code === "number") {
|
|
42614
|
-
ok = res.ok && code === 200;
|
|
42615
|
-
if (!ok) detail = ` (${parsed.message ?? code})`;
|
|
42616
|
-
}
|
|
42617
|
-
}
|
|
42618
|
-
} catch {
|
|
42619
|
-
}
|
|
42620
|
-
return {
|
|
42621
|
-
ok,
|
|
42622
|
-
message: ok ? `Reachable at ${baseUrl}` : `HTTP ${res.status}${detail}`
|
|
42623
|
-
};
|
|
42624
|
-
} catch (err) {
|
|
42625
|
-
return {
|
|
42626
|
-
ok: false,
|
|
42627
|
-
message: `Cannot connect: ${err instanceof Error ? err.message : String(err)}`
|
|
42628
|
-
};
|
|
42629
|
-
}
|
|
42630
|
-
},
|
|
42631
|
-
discover: async (config) => {
|
|
42632
|
-
try {
|
|
42633
|
-
const baseUrl = resolveBaseUrl(config);
|
|
42634
|
-
const res = await fetch(`${baseUrl}/datasources`, {
|
|
42635
|
-
headers: buildConnectionHeaders(config)
|
|
42636
|
-
});
|
|
42637
|
-
const text = await res.text();
|
|
42638
|
-
if (!res.ok) {
|
|
42639
|
-
throw new Error(`HTTP ${res.status}${text ? `: ${text.slice(0, 200)}` : ""}`);
|
|
42640
|
-
}
|
|
42641
|
-
const parsed = JSON.parse(text);
|
|
42642
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
42643
|
-
throw new Error("Metrics server returned an unexpected payload (expected a JSON envelope)");
|
|
42644
|
-
}
|
|
42645
|
-
const envelope = parsed;
|
|
42646
|
-
if (typeof envelope.code === "number" && envelope.code !== 200) {
|
|
42647
|
-
throw new Error(envelope.message || `API ${envelope.code}`);
|
|
42648
|
-
}
|
|
42649
|
-
const data = envelope.data;
|
|
42650
|
-
if (!Array.isArray(data)) {
|
|
42651
|
-
throw new Error("Metrics server returned an unexpected payload (expected a datasource array)");
|
|
42652
|
-
}
|
|
42653
|
-
return data.filter((d) => {
|
|
42654
|
-
if (d === null || typeof d !== "object") return false;
|
|
42655
|
-
const id = d.id;
|
|
42656
|
-
return id !== void 0 && id !== null && id !== "";
|
|
42657
|
-
}).map((item) => ({
|
|
42658
|
-
id: String(item.id),
|
|
42659
|
-
name: item.name ?? String(item.id)
|
|
42660
|
-
}));
|
|
42661
|
-
} catch (err) {
|
|
42662
|
-
throw new Error(
|
|
42663
|
-
`Cannot discover datasources: ${err instanceof Error ? err.message : String(err)}`
|
|
42664
|
-
);
|
|
42665
|
-
}
|
|
42666
|
-
}
|
|
42667
|
-
},
|
|
42668
|
-
skills: {
|
|
42669
|
-
"semantic-metrics-modeling": SEMANTIC_METRICS_MODELING_SKILL
|
|
42670
|
-
},
|
|
42671
|
-
agents: {
|
|
42672
|
-
"semantic-metrics-builder": {
|
|
42673
|
-
key: "semantic-metrics-builder",
|
|
42674
|
-
name: "Semantic Metrics Builder",
|
|
42675
|
-
description: "Explore a granted datasource and build semantic tables and metrics interactively, tracking the work as persistent tasks with belief state and verifying each step.",
|
|
42676
|
-
type: import_protocols33.AgentType.DEEP_AGENT,
|
|
42677
|
-
prompt: SEMANTIC_METRICS_BUILDER_PROMPT,
|
|
42678
|
-
middleware: [
|
|
42679
|
-
{
|
|
42680
|
-
id: "semantic-metrics",
|
|
42681
|
-
type: "semantic-metrics",
|
|
42682
|
-
name: "Semantic Metrics",
|
|
42683
|
-
description: "Explore datasources, publish table/meta metrics, query runtime",
|
|
42684
|
-
enabled: true,
|
|
42685
|
-
config: { connections: [], connectAll: true }
|
|
42686
|
-
},
|
|
42687
|
-
{
|
|
42688
|
-
id: "skill",
|
|
42689
|
-
type: "skill",
|
|
42690
|
-
name: "Skill",
|
|
42691
|
-
description: "Load the semantic-metrics-modeling policy and task-definition reference",
|
|
42692
|
-
enabled: true,
|
|
42693
|
-
config: { readAll: false, skills: ["semantic-metrics-modeling", "task-definition"] }
|
|
42694
|
-
},
|
|
42695
|
-
{
|
|
42696
|
-
id: "task",
|
|
42697
|
-
type: "task",
|
|
42698
|
-
name: "Task",
|
|
42699
|
-
description: "Persistent TaskItems as the planning surface; update Belief State in task descriptions",
|
|
42700
|
-
enabled: true,
|
|
42701
|
-
config: {}
|
|
42702
|
-
},
|
|
42703
|
-
{
|
|
42704
|
-
id: "ask_user_to_clarify",
|
|
42705
|
-
type: "ask_user_to_clarify",
|
|
42706
|
-
name: "Ask User",
|
|
42707
|
-
description: "Wait for user input at modeling approval gates",
|
|
42708
|
-
enabled: true,
|
|
42709
|
-
config: {}
|
|
42710
|
-
},
|
|
42711
|
-
{
|
|
42712
|
-
id: "filesystem",
|
|
42713
|
-
type: "filesystem",
|
|
42714
|
-
name: "Filesystem",
|
|
42715
|
-
description: "Read user-provided schema docs, data dictionaries, or sample data files",
|
|
42716
|
-
enabled: true,
|
|
42717
|
-
config: {}
|
|
42718
|
-
}
|
|
42719
|
-
]
|
|
42720
|
-
}
|
|
42721
|
-
},
|
|
42722
|
-
middleware: (config) => createSemanticMetricsMiddleware(config)
|
|
42723
|
-
};
|
|
42724
|
-
|
|
42725
41246
|
// src/middlewares/collectionMiddleware.ts
|
|
42726
|
-
var
|
|
41247
|
+
var import_langchain77 = require("langchain");
|
|
42727
41248
|
|
|
42728
41249
|
// src/tool_lattice/collection/list_collections.ts
|
|
42729
|
-
var
|
|
42730
|
-
var
|
|
41250
|
+
var import_zod55 = __toESM(require("zod"));
|
|
41251
|
+
var import_langchain67 = require("langchain");
|
|
42731
41252
|
|
|
42732
41253
|
// src/tool_lattice/collection/utils.ts
|
|
42733
41254
|
function getEffectiveCollectionScope(exeConfig, staticScope) {
|
|
@@ -42750,7 +41271,7 @@ var createListCollectionsTool = ({
|
|
|
42750
41271
|
collectionKeys,
|
|
42751
41272
|
connectAll
|
|
42752
41273
|
}) => {
|
|
42753
|
-
return (0,
|
|
41274
|
+
return (0, import_langchain67.tool)(
|
|
42754
41275
|
async (_input, _exeConfig) => {
|
|
42755
41276
|
try {
|
|
42756
41277
|
const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
|
|
@@ -42785,23 +41306,23 @@ var createListCollectionsTool = ({
|
|
|
42785
41306
|
{
|
|
42786
41307
|
name: "list_collections",
|
|
42787
41308
|
description: LIST_COLLECTIONS_DESCRIPTION,
|
|
42788
|
-
schema:
|
|
41309
|
+
schema: import_zod55.default.object({})
|
|
42789
41310
|
}
|
|
42790
41311
|
);
|
|
42791
41312
|
};
|
|
42792
41313
|
|
|
42793
41314
|
// src/tool_lattice/collection/search_collection.ts
|
|
42794
|
-
var
|
|
42795
|
-
var
|
|
41315
|
+
var import_zod56 = __toESM(require("zod"));
|
|
41316
|
+
var import_langchain68 = require("langchain");
|
|
42796
41317
|
var SEARCH_COLLECTION_DESCRIPTION = `Search for content within a specific collection using semantic (vector) similarity. Use the 'filter' parameter to narrow results by metadata fields (e.g., {"category": "cardiovascular"}). Returns the most relevant content entries with similarity scores.`;
|
|
42797
|
-
var searchSchema =
|
|
42798
|
-
collection:
|
|
42799
|
-
query:
|
|
42800
|
-
filter:
|
|
42801
|
-
top_k:
|
|
41318
|
+
var searchSchema = import_zod56.default.object({
|
|
41319
|
+
collection: import_zod56.default.string().describe("The collection name to search in"),
|
|
41320
|
+
query: import_zod56.default.string().describe("The search query text"),
|
|
41321
|
+
filter: import_zod56.default.record(import_zod56.default.unknown()).optional().describe("Metadata filter conditions"),
|
|
41322
|
+
top_k: import_zod56.default.number().optional().default(5).describe("Number of results to return")
|
|
42802
41323
|
});
|
|
42803
41324
|
var createSearchCollectionTool = (scope = { collectionKeys: [], connectAll: true }) => {
|
|
42804
|
-
return (0,
|
|
41325
|
+
return (0, import_langchain68.tool)(
|
|
42805
41326
|
async (input, _exeConfig) => {
|
|
42806
41327
|
try {
|
|
42807
41328
|
const { collection, query, filter: filter2, top_k } = input;
|
|
@@ -42867,10 +41388,10 @@ var createSearchCollectionTool = (scope = { collectionKeys: [], connectAll: true
|
|
|
42867
41388
|
};
|
|
42868
41389
|
|
|
42869
41390
|
// src/tool_lattice/collection/get_collection.ts
|
|
42870
|
-
var
|
|
42871
|
-
var
|
|
41391
|
+
var import_zod57 = __toESM(require("zod"));
|
|
41392
|
+
var import_langchain69 = require("langchain");
|
|
42872
41393
|
var GET_COLLECTION_DESCRIPTION = `Get a collection's full definition including its custom fields schema. Use this to discover what metadata fields are available before adding entries.`;
|
|
42873
|
-
var createGetCollectionTool = (scope = { collectionKeys: [], connectAll: true }) => (0,
|
|
41394
|
+
var createGetCollectionTool = (scope = { collectionKeys: [], connectAll: true }) => (0, import_langchain69.tool)(
|
|
42874
41395
|
async (input, _exeConfig) => {
|
|
42875
41396
|
try {
|
|
42876
41397
|
const scopeError = validateCollectionScope(input.name, _exeConfig, scope);
|
|
@@ -42895,24 +41416,24 @@ Embedding: ${c.embeddingKey}${fieldsDesc}`;
|
|
|
42895
41416
|
return `Error: ${error.message}`;
|
|
42896
41417
|
}
|
|
42897
41418
|
},
|
|
42898
|
-
{ name: "get_collection", description: GET_COLLECTION_DESCRIPTION, schema:
|
|
41419
|
+
{ name: "get_collection", description: GET_COLLECTION_DESCRIPTION, schema: import_zod57.default.object({ name: import_zod57.default.string().describe("Collection name") }) }
|
|
42899
41420
|
);
|
|
42900
41421
|
|
|
42901
41422
|
// src/tool_lattice/collection/create_collection.ts
|
|
42902
|
-
var
|
|
42903
|
-
var
|
|
42904
|
-
var createSchema =
|
|
42905
|
-
name:
|
|
42906
|
-
label:
|
|
42907
|
-
embeddingKey:
|
|
42908
|
-
fields:
|
|
42909
|
-
key:
|
|
42910
|
-
type:
|
|
42911
|
-
enumValues:
|
|
42912
|
-
required:
|
|
41423
|
+
var import_zod58 = __toESM(require("zod"));
|
|
41424
|
+
var import_langchain70 = require("langchain");
|
|
41425
|
+
var createSchema = import_zod58.default.object({
|
|
41426
|
+
name: import_zod58.default.string().describe("Collection name (lowercase, underscores only)"),
|
|
41427
|
+
label: import_zod58.default.string().describe("Display name"),
|
|
41428
|
+
embeddingKey: import_zod58.default.string().describe("Embedding model key"),
|
|
41429
|
+
fields: import_zod58.default.array(import_zod58.default.object({
|
|
41430
|
+
key: import_zod58.default.string().describe("Field key name"),
|
|
41431
|
+
type: import_zod58.default.enum(["string", "number", "enum"]).describe("Field data type"),
|
|
41432
|
+
enumValues: import_zod58.default.array(import_zod58.default.string()).optional().describe("Valid values for enum type"),
|
|
41433
|
+
required: import_zod58.default.boolean().optional().default(false).describe("Whether field is required")
|
|
42913
41434
|
})).optional().describe("Custom field definitions for entries in this collection")
|
|
42914
41435
|
});
|
|
42915
|
-
var createCreateCollectionTool = (scope = {}) => (0,
|
|
41436
|
+
var createCreateCollectionTool = (scope = {}) => (0, import_langchain70.tool)(
|
|
42916
41437
|
async (input, _exeConfig) => {
|
|
42917
41438
|
try {
|
|
42918
41439
|
const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
|
|
@@ -42938,20 +41459,20 @@ var createCreateCollectionTool = (scope = {}) => (0, import_langchain74.tool)(
|
|
|
42938
41459
|
);
|
|
42939
41460
|
|
|
42940
41461
|
// src/tool_lattice/collection/update_collection.ts
|
|
42941
|
-
var
|
|
42942
|
-
var
|
|
42943
|
-
var schema =
|
|
42944
|
-
name:
|
|
42945
|
-
label:
|
|
42946
|
-
embeddingKey:
|
|
42947
|
-
fields:
|
|
42948
|
-
key:
|
|
42949
|
-
type:
|
|
42950
|
-
enumValues:
|
|
42951
|
-
required:
|
|
41462
|
+
var import_zod59 = __toESM(require("zod"));
|
|
41463
|
+
var import_langchain71 = require("langchain");
|
|
41464
|
+
var schema = import_zod59.default.object({
|
|
41465
|
+
name: import_zod59.default.string().describe("Collection name"),
|
|
41466
|
+
label: import_zod59.default.string().optional().describe("New display name"),
|
|
41467
|
+
embeddingKey: import_zod59.default.string().optional().describe("New embedding model key"),
|
|
41468
|
+
fields: import_zod59.default.array(import_zod59.default.object({
|
|
41469
|
+
key: import_zod59.default.string().describe("Field key name"),
|
|
41470
|
+
type: import_zod59.default.enum(["string", "number", "enum"]).describe("Field data type"),
|
|
41471
|
+
enumValues: import_zod59.default.array(import_zod59.default.string()).optional().describe("Valid values for enum type"),
|
|
41472
|
+
required: import_zod59.default.boolean().optional().default(false).describe("Whether field is required")
|
|
42952
41473
|
})).optional().describe("Custom field definitions for entries (replaces existing schema)")
|
|
42953
41474
|
});
|
|
42954
|
-
var createUpdateCollectionTool = (scope = { collectionKeys: [], connectAll: true }) => (0,
|
|
41475
|
+
var createUpdateCollectionTool = (scope = { collectionKeys: [], connectAll: true }) => (0, import_langchain71.tool)(
|
|
42955
41476
|
async (input, _exeConfig) => {
|
|
42956
41477
|
try {
|
|
42957
41478
|
const scopeError = validateCollectionScope(input.name, _exeConfig, scope);
|
|
@@ -42972,9 +41493,9 @@ var createUpdateCollectionTool = (scope = { collectionKeys: [], connectAll: true
|
|
|
42972
41493
|
);
|
|
42973
41494
|
|
|
42974
41495
|
// src/tool_lattice/collection/delete_collection.ts
|
|
42975
|
-
var
|
|
42976
|
-
var
|
|
42977
|
-
var createDeleteCollectionTool = (scope = { collectionKeys: [], connectAll: true }) => (0,
|
|
41496
|
+
var import_zod60 = __toESM(require("zod"));
|
|
41497
|
+
var import_langchain72 = require("langchain");
|
|
41498
|
+
var createDeleteCollectionTool = (scope = { collectionKeys: [], connectAll: true }) => (0, import_langchain72.tool)(
|
|
42978
41499
|
async (input, _exeConfig) => {
|
|
42979
41500
|
try {
|
|
42980
41501
|
const scopeError = validateCollectionScope(input.name, _exeConfig, scope);
|
|
@@ -42986,19 +41507,19 @@ var createDeleteCollectionTool = (scope = { collectionKeys: [], connectAll: true
|
|
|
42986
41507
|
return `Error: ${e.message}`;
|
|
42987
41508
|
}
|
|
42988
41509
|
},
|
|
42989
|
-
{ name: "delete_collection", description: `Delete a collection and all its entries. This cannot be undone.`, schema:
|
|
41510
|
+
{ name: "delete_collection", description: `Delete a collection and all its entries. This cannot be undone.`, schema: import_zod60.default.object({ name: import_zod60.default.string().describe("Collection name") }) }
|
|
42990
41511
|
);
|
|
42991
41512
|
|
|
42992
41513
|
// src/tool_lattice/collection/list_entries.ts
|
|
42993
|
-
var
|
|
42994
|
-
var
|
|
42995
|
-
var schema2 =
|
|
42996
|
-
collection:
|
|
41514
|
+
var import_zod61 = __toESM(require("zod"));
|
|
41515
|
+
var import_langchain73 = require("langchain");
|
|
41516
|
+
var schema2 = import_zod61.default.object({
|
|
41517
|
+
collection: import_zod61.default.string().describe("Collection name")
|
|
42997
41518
|
});
|
|
42998
41519
|
function buildKey2(tenantId2, name) {
|
|
42999
41520
|
return `${tenantId2}:${name}`;
|
|
43000
41521
|
}
|
|
43001
|
-
var createListEntriesTool = (scope = { collectionKeys: [], connectAll: true }) => (0,
|
|
41522
|
+
var createListEntriesTool = (scope = { collectionKeys: [], connectAll: true }) => (0, import_langchain73.tool)(
|
|
43002
41523
|
async (input, _exeConfig) => {
|
|
43003
41524
|
try {
|
|
43004
41525
|
const scopeError = validateCollectionScope(input.collection, _exeConfig, scope);
|
|
@@ -43027,19 +41548,19 @@ var createListEntriesTool = (scope = { collectionKeys: [], connectAll: true }) =
|
|
|
43027
41548
|
);
|
|
43028
41549
|
|
|
43029
41550
|
// src/tool_lattice/collection/add_entry.ts
|
|
43030
|
-
var
|
|
43031
|
-
var
|
|
41551
|
+
var import_zod62 = __toESM(require("zod"));
|
|
41552
|
+
var import_langchain74 = require("langchain");
|
|
43032
41553
|
var import_documents = require("@langchain/core/documents");
|
|
43033
41554
|
var import_uuid12 = require("uuid");
|
|
43034
|
-
var schema3 =
|
|
43035
|
-
collection:
|
|
43036
|
-
content:
|
|
43037
|
-
metadata:
|
|
41555
|
+
var schema3 = import_zod62.default.object({
|
|
41556
|
+
collection: import_zod62.default.string().describe("Collection name"),
|
|
41557
|
+
content: import_zod62.default.string().describe("Entry content text"),
|
|
41558
|
+
metadata: import_zod62.default.record(import_zod62.default.unknown()).optional().describe("Metadata fields matching the collection schema")
|
|
43038
41559
|
});
|
|
43039
41560
|
function key2(t, n) {
|
|
43040
41561
|
return `${t}:${n}`;
|
|
43041
41562
|
}
|
|
43042
|
-
var createAddEntryTool = (scope = { collectionKeys: [], connectAll: true }) => (0,
|
|
41563
|
+
var createAddEntryTool = (scope = { collectionKeys: [], connectAll: true }) => (0, import_langchain74.tool)(
|
|
43043
41564
|
async (input, _exeConfig) => {
|
|
43044
41565
|
try {
|
|
43045
41566
|
const scopeError = validateCollectionScope(input.collection, _exeConfig, scope);
|
|
@@ -43071,18 +41592,18 @@ var createAddEntryTool = (scope = { collectionKeys: [], connectAll: true }) => (
|
|
|
43071
41592
|
);
|
|
43072
41593
|
|
|
43073
41594
|
// src/tool_lattice/collection/update_entry.ts
|
|
43074
|
-
var
|
|
43075
|
-
var
|
|
43076
|
-
var schema4 =
|
|
43077
|
-
collection:
|
|
43078
|
-
entryId:
|
|
43079
|
-
content:
|
|
43080
|
-
metadata:
|
|
41595
|
+
var import_zod63 = __toESM(require("zod"));
|
|
41596
|
+
var import_langchain75 = require("langchain");
|
|
41597
|
+
var schema4 = import_zod63.default.object({
|
|
41598
|
+
collection: import_zod63.default.string().describe("Collection name"),
|
|
41599
|
+
entryId: import_zod63.default.string().describe("Entry ID to update"),
|
|
41600
|
+
content: import_zod63.default.string().optional().describe("New content"),
|
|
41601
|
+
metadata: import_zod63.default.record(import_zod63.default.unknown()).optional().describe("New metadata")
|
|
43081
41602
|
});
|
|
43082
41603
|
function key3(t, n) {
|
|
43083
41604
|
return `${t}:${n}`;
|
|
43084
41605
|
}
|
|
43085
|
-
var createUpdateEntryTool = (scope = { collectionKeys: [], connectAll: true }) => (0,
|
|
41606
|
+
var createUpdateEntryTool = (scope = { collectionKeys: [], connectAll: true }) => (0, import_langchain75.tool)(
|
|
43086
41607
|
async (input, _exeConfig) => {
|
|
43087
41608
|
try {
|
|
43088
41609
|
const scopeError = validateCollectionScope(input.collection, _exeConfig, scope);
|
|
@@ -43103,16 +41624,16 @@ var createUpdateEntryTool = (scope = { collectionKeys: [], connectAll: true }) =
|
|
|
43103
41624
|
);
|
|
43104
41625
|
|
|
43105
41626
|
// src/tool_lattice/collection/delete_entry.ts
|
|
43106
|
-
var
|
|
43107
|
-
var
|
|
43108
|
-
var schema5 =
|
|
43109
|
-
collection:
|
|
43110
|
-
entryId:
|
|
41627
|
+
var import_zod64 = __toESM(require("zod"));
|
|
41628
|
+
var import_langchain76 = require("langchain");
|
|
41629
|
+
var schema5 = import_zod64.default.object({
|
|
41630
|
+
collection: import_zod64.default.string().describe("Collection name"),
|
|
41631
|
+
entryId: import_zod64.default.string().describe("Entry ID to delete")
|
|
43111
41632
|
});
|
|
43112
41633
|
function key4(t, n) {
|
|
43113
41634
|
return `${t}:${n}`;
|
|
43114
41635
|
}
|
|
43115
|
-
var createDeleteEntryTool = (scope = { collectionKeys: [], connectAll: true }) => (0,
|
|
41636
|
+
var createDeleteEntryTool = (scope = { collectionKeys: [], connectAll: true }) => (0, import_langchain76.tool)(
|
|
43116
41637
|
async (input, _exeConfig) => {
|
|
43117
41638
|
try {
|
|
43118
41639
|
const scopeError = validateCollectionScope(input.collection, _exeConfig, scope);
|
|
@@ -43132,7 +41653,7 @@ var createDeleteEntryTool = (scope = { collectionKeys: [], connectAll: true }) =
|
|
|
43132
41653
|
function createCollectionMiddleware(params) {
|
|
43133
41654
|
const { collectionKeys, connectAll, compileStableCandidateTools = false } = params;
|
|
43134
41655
|
if (!compileStableCandidateTools && !connectAll && (!collectionKeys || collectionKeys.length === 0)) {
|
|
43135
|
-
return (0,
|
|
41656
|
+
return (0, import_langchain77.createMiddleware)({
|
|
43136
41657
|
name: "collectionMiddleware",
|
|
43137
41658
|
contextSchema,
|
|
43138
41659
|
tools: [
|
|
@@ -43142,7 +41663,7 @@ function createCollectionMiddleware(params) {
|
|
|
43142
41663
|
});
|
|
43143
41664
|
}
|
|
43144
41665
|
const toolParams = { collectionKeys, connectAll };
|
|
43145
|
-
return (0,
|
|
41666
|
+
return (0, import_langchain77.createMiddleware)({
|
|
43146
41667
|
name: "collectionMiddleware",
|
|
43147
41668
|
contextSchema,
|
|
43148
41669
|
tools: [
|
|
@@ -43205,24 +41726,24 @@ var collectionPlugin = {
|
|
|
43205
41726
|
};
|
|
43206
41727
|
|
|
43207
41728
|
// src/middlewares/askUserClarifyMiddleware.ts
|
|
43208
|
-
var
|
|
41729
|
+
var import_langchain79 = require("langchain");
|
|
43209
41730
|
var import_langgraph15 = require("@langchain/langgraph");
|
|
43210
41731
|
|
|
43211
41732
|
// src/tool_lattice/ask_user_to_clarify/index.ts
|
|
43212
|
-
var
|
|
43213
|
-
var
|
|
43214
|
-
var questionSchema =
|
|
43215
|
-
question:
|
|
43216
|
-
options:
|
|
43217
|
-
type:
|
|
43218
|
-
required:
|
|
43219
|
-
allowOther:
|
|
41733
|
+
var import_langchain78 = require("langchain");
|
|
41734
|
+
var import_zod65 = __toESM(require("zod"));
|
|
41735
|
+
var questionSchema = import_zod65.default.object({
|
|
41736
|
+
question: import_zod65.default.string().describe("The question text to ask the user. MUST include the specific context, options, or details being clarified \u2014 never use a bare generic label. Good: 'Confirm the plan: use Redis cache + PostgreSQL primary, split microservices as needed?' Bad: 'Confirm the plan?'"),
|
|
41737
|
+
options: import_zod65.default.array(import_zod65.default.string()).optional().default([]).describe("List of EXACT, selectable values. Maximum 3 options allowed. DO NOT include placeholder values like 'Other' or 'Enter manually'. For free-text with predefined choices, use allowOther=true (works with 'single' and 'multiple'). For pure free-text without choices, use type='input' instead. For file_upload and input, pass an empty array."),
|
|
41738
|
+
type: import_zod65.default.enum(["single", "multiple", "file_upload", "input"]).describe("The question format. 'single' = pick one from options (default, see tool description for guidance). 'multiple' = pick several from options. 'input' = free-text field (only when options cannot express the answer). 'file_upload' = file picker."),
|
|
41739
|
+
required: import_zod65.default.boolean().optional().default(false).describe("Whether this question must be answered"),
|
|
41740
|
+
allowOther: import_zod65.default.boolean().optional().default(true).describe("Set to true to append an 'Other' checkbox with a free-text input field. Works with 'single' and 'multiple' types. Use for open-ended answers or when the options cannot cover all possibilities. Not applicable for 'input' or 'file_upload' types.")
|
|
43220
41741
|
});
|
|
43221
|
-
var inputSchema =
|
|
43222
|
-
questions:
|
|
41742
|
+
var inputSchema = import_zod65.default.object({
|
|
41743
|
+
questions: import_zod65.default.array(questionSchema).min(1, "At least one question is required").describe("A structured sequence of clarification questions. Use these to gather missing parameters or disambiguate user intent before proceeding.")
|
|
43223
41744
|
});
|
|
43224
41745
|
function createAskUserToClarifyTool() {
|
|
43225
|
-
return (0,
|
|
41746
|
+
return (0, import_langchain78.tool)(
|
|
43226
41747
|
async (input) => {
|
|
43227
41748
|
return JSON.stringify(input);
|
|
43228
41749
|
},
|
|
@@ -43247,7 +41768,7 @@ function isProjectRoomRun(request) {
|
|
|
43247
41768
|
return isRecord9(runConfig?.projectRoom);
|
|
43248
41769
|
}
|
|
43249
41770
|
function createAskUserClarifyMiddleware() {
|
|
43250
|
-
return (0,
|
|
41771
|
+
return (0, import_langchain79.createMiddleware)({
|
|
43251
41772
|
name: "AskUserClarifyMiddleware",
|
|
43252
41773
|
tools: [createAskUserToClarifyTool()],
|
|
43253
41774
|
wrapToolCall: async (request, handler) => {
|
|
@@ -43257,7 +41778,7 @@ function createAskUserClarifyMiddleware() {
|
|
|
43257
41778
|
return handler(request);
|
|
43258
41779
|
}
|
|
43259
41780
|
if (isProjectRoomRun(request)) {
|
|
43260
|
-
return new
|
|
41781
|
+
return new import_langchain79.ToolMessage({
|
|
43261
41782
|
content: "You are replying inside a project room, which has no interactive clarification UI. Ask your clarifying questions directly in your reply text and stop; the user's next room message will continue the conversation.",
|
|
43262
41783
|
tool_call_id: toolCall?.id,
|
|
43263
41784
|
name: toolName2
|
|
@@ -43265,7 +41786,7 @@ function createAskUserClarifyMiddleware() {
|
|
|
43265
41786
|
}
|
|
43266
41787
|
const parsed = inputSchema.safeParse(toolCall?.args);
|
|
43267
41788
|
if (!parsed.success) {
|
|
43268
|
-
return new
|
|
41789
|
+
return new import_langchain79.ToolMessage({
|
|
43269
41790
|
content: `Invalid clarify tool arguments: ${parsed.error.message}`,
|
|
43270
41791
|
tool_call_id: toolCall?.id,
|
|
43271
41792
|
name: toolName2
|
|
@@ -43285,7 +41806,7 @@ function createAskUserClarifyMiddleware() {
|
|
|
43285
41806
|
const result = await (0, import_langgraph15.interrupt)(md);
|
|
43286
41807
|
const response = result.data;
|
|
43287
41808
|
if (!response?.answers || response.answers.length === 0) {
|
|
43288
|
-
return new
|
|
41809
|
+
return new import_langchain79.ToolMessage({
|
|
43289
41810
|
content: "No clarification questions were answered.",
|
|
43290
41811
|
tool_call_id: toolCall?.id,
|
|
43291
41812
|
name: toolName2
|
|
@@ -43295,7 +41816,7 @@ function createAskUserClarifyMiddleware() {
|
|
|
43295
41816
|
(answer) => (answer.selectedOptions?.length ?? 0) > 0 || answer.otherText && answer.otherText.trim() !== "" || answer.filePath && answer.filePath.trim() !== ""
|
|
43296
41817
|
);
|
|
43297
41818
|
if (answeredQuestions.length === 0) {
|
|
43298
|
-
return new
|
|
41819
|
+
return new import_langchain79.ToolMessage({
|
|
43299
41820
|
content: "No clarification questions were answered.",
|
|
43300
41821
|
tool_call_id: toolCall?.id,
|
|
43301
41822
|
name: toolName2
|
|
@@ -43325,7 +41846,7 @@ function createAskUserClarifyMiddleware() {
|
|
|
43325
41846
|
}
|
|
43326
41847
|
lines.push("");
|
|
43327
41848
|
}
|
|
43328
|
-
return new
|
|
41849
|
+
return new import_langchain79.ToolMessage({
|
|
43329
41850
|
content: lines.join("\n"),
|
|
43330
41851
|
tool_call_id: toolCall?.id,
|
|
43331
41852
|
name: toolName2
|
|
@@ -43351,11 +41872,11 @@ var askUserClarifyPlugin = {
|
|
|
43351
41872
|
};
|
|
43352
41873
|
|
|
43353
41874
|
// src/middlewares/widgetMiddleware.ts
|
|
43354
|
-
var
|
|
41875
|
+
var import_langchain82 = require("langchain");
|
|
43355
41876
|
|
|
43356
41877
|
// src/tool_lattice/widget/loadGuidelines.ts
|
|
43357
|
-
var
|
|
43358
|
-
var
|
|
41878
|
+
var import_langchain80 = require("langchain");
|
|
41879
|
+
var import_zod66 = require("zod");
|
|
43359
41880
|
|
|
43360
41881
|
// src/middlewares/guidelines/index.ts
|
|
43361
41882
|
var CORE = `# Imagine \u2014 Visual Creation Suite
|
|
@@ -44146,13 +42667,13 @@ function getGuidelines(modules) {
|
|
|
44146
42667
|
var AVAILABLE_MODULES = Object.keys(MODULE_SECTIONS);
|
|
44147
42668
|
|
|
44148
42669
|
// src/tool_lattice/widget/loadGuidelines.ts
|
|
44149
|
-
var LoadGuidelinesInputSchema =
|
|
44150
|
-
modules:
|
|
42670
|
+
var LoadGuidelinesInputSchema = import_zod66.z.object({
|
|
42671
|
+
modules: import_zod66.z.array(import_zod66.z.string()).describe(
|
|
44151
42672
|
"Which design modules to load. Choose all that apply. Available modules: [" + AVAILABLE_MODULES.join(",") + "]"
|
|
44152
42673
|
)
|
|
44153
42674
|
});
|
|
44154
42675
|
function createLoadGuidelinesTool() {
|
|
44155
|
-
return (0,
|
|
42676
|
+
return (0, import_langchain80.tool)(
|
|
44156
42677
|
async (input) => {
|
|
44157
42678
|
const result = getGuidelines(input.modules);
|
|
44158
42679
|
return result;
|
|
@@ -44166,8 +42687,8 @@ function createLoadGuidelinesTool() {
|
|
|
44166
42687
|
}
|
|
44167
42688
|
|
|
44168
42689
|
// src/tool_lattice/widget/showWidget.ts
|
|
44169
|
-
var
|
|
44170
|
-
var
|
|
42690
|
+
var import_langchain81 = require("langchain");
|
|
42691
|
+
var import_zod67 = require("zod");
|
|
44171
42692
|
function containsForbiddenTags(code) {
|
|
44172
42693
|
const forbiddenPatterns = [
|
|
44173
42694
|
/<!DOCTYPE/i,
|
|
@@ -44189,20 +42710,20 @@ function validateWidgetCode(code) {
|
|
|
44189
42710
|
}
|
|
44190
42711
|
return { valid: true };
|
|
44191
42712
|
}
|
|
44192
|
-
var ShowWidgetInputSchema =
|
|
44193
|
-
i_have_seen_guidelines:
|
|
42713
|
+
var ShowWidgetInputSchema = import_zod67.z.object({
|
|
42714
|
+
i_have_seen_guidelines: import_zod67.z.boolean().describe(
|
|
44194
42715
|
"Must be true. Confirm you have called load_guidelines first."
|
|
44195
42716
|
),
|
|
44196
|
-
title:
|
|
44197
|
-
loading_messages:
|
|
42717
|
+
title: import_zod67.z.string().describe("Title displayed above the widget"),
|
|
42718
|
+
loading_messages: import_zod67.z.array(import_zod67.z.string()).optional().describe(
|
|
44198
42719
|
"1-4 short strings shown while the widget renders"
|
|
44199
42720
|
),
|
|
44200
|
-
widget_code:
|
|
42721
|
+
widget_code: import_zod67.z.string().describe(
|
|
44201
42722
|
"HTML fragment to render. Rules: 1. No DOCTYPE, <html>, <head>, or <body> tags. 2. Order: <style> block first, then HTML content, then <script> last. 3. Use only CSS variables for colors (e.g. var(--color-accent)). 4. No gradients, shadows, or blur effects. For SVG: start directly with <svg> tag."
|
|
44202
42723
|
)
|
|
44203
42724
|
});
|
|
44204
42725
|
function createShowWidgetTool() {
|
|
44205
|
-
return (0,
|
|
42726
|
+
return (0, import_langchain81.tool)(
|
|
44206
42727
|
async (input) => {
|
|
44207
42728
|
if (!input.i_have_seen_guidelines) {
|
|
44208
42729
|
return "Error: You must call load_guidelines before using show_widget. Set i_have_seen_guidelines to true only after loading guidelines.";
|
|
@@ -44233,7 +42754,7 @@ function createWidgetMiddleware() {
|
|
|
44233
42754
|
createLoadGuidelinesTool(),
|
|
44234
42755
|
createShowWidgetTool()
|
|
44235
42756
|
];
|
|
44236
|
-
return (0,
|
|
42757
|
+
return (0, import_langchain82.createMiddleware)({
|
|
44237
42758
|
name: "widgetMiddleware",
|
|
44238
42759
|
contextSchema,
|
|
44239
42760
|
tools
|
|
@@ -44257,8 +42778,8 @@ var widgetPlugin = {
|
|
|
44257
42778
|
};
|
|
44258
42779
|
|
|
44259
42780
|
// src/middlewares/taskMiddleware.ts
|
|
44260
|
-
var
|
|
44261
|
-
var
|
|
42781
|
+
var import_langchain83 = require("langchain");
|
|
42782
|
+
var import_zod68 = require("zod");
|
|
44262
42783
|
var import_langgraph16 = require("@langchain/langgraph");
|
|
44263
42784
|
|
|
44264
42785
|
// src/util/truncateForJson.ts
|
|
@@ -44318,7 +42839,7 @@ function truncateForJson(value, options = {}) {
|
|
|
44318
42839
|
}
|
|
44319
42840
|
|
|
44320
42841
|
// src/middlewares/taskMiddleware.ts
|
|
44321
|
-
var
|
|
42842
|
+
var import_protocols33 = require("@axiom-lattice/protocols");
|
|
44322
42843
|
|
|
44323
42844
|
// src/middlewares/taskResponseSerialization.ts
|
|
44324
42845
|
var TASK_RESPONSE_SCALAR_MAX_BYTES = 4096;
|
|
@@ -44786,7 +43307,7 @@ function classifyTaskAuthority(runConfig) {
|
|
|
44786
43307
|
return delegatedTaskId ? { kind: "delegated", taskId: delegatedTaskId } : { kind: "ordinary" };
|
|
44787
43308
|
}
|
|
44788
43309
|
try {
|
|
44789
|
-
const trusted = (0,
|
|
43310
|
+
const trusted = (0, import_protocols33.parseTrustedRunContext)(hasProjectTask ? { projectTask: runConfig.projectTask } : { projectRoom: runConfig.projectRoom });
|
|
44790
43311
|
return { kind: hasProjectTask ? "projectTask" : "projectRoom", trusted };
|
|
44791
43312
|
} catch {
|
|
44792
43313
|
return { kind: "invalid" };
|
|
@@ -44816,6 +43337,9 @@ function trustedRosterScope(trusted) {
|
|
|
44816
43337
|
callerAssistantId: context.assistantId
|
|
44817
43338
|
};
|
|
44818
43339
|
}
|
|
43340
|
+
function trustedRosterExempt(trusted) {
|
|
43341
|
+
return trusted.projectTask?.rosterExempt === true;
|
|
43342
|
+
}
|
|
44819
43343
|
async function requireTrustedOwner(trusted, targetAssistantId) {
|
|
44820
43344
|
const context = trusted.projectTask ?? trusted.projectRoom;
|
|
44821
43345
|
const memberships = getStoreLattice("default", "projectBotMembership").store;
|
|
@@ -45080,6 +43604,7 @@ async function validateTrustedChildDependencyWait(store, tenantId2, parent, depe
|
|
|
45080
43604
|
if (dependency.status === "completed") continue;
|
|
45081
43605
|
if (!["pending", "in_progress", "interrupted"].includes(dependency.status) || dependency.parentId !== parent.id || dependency.ownerType !== "agent" || !hasExactContextSource(dependency, expectedSource)) return void 0;
|
|
45082
43606
|
incompleteChildren += 1;
|
|
43607
|
+
if (trustedRosterExempt(trusted)) continue;
|
|
45083
43608
|
try {
|
|
45084
43609
|
await requireTrustedOwner(trusted, dependency.ownerId);
|
|
45085
43610
|
} catch (error) {
|
|
@@ -45119,7 +43644,7 @@ function getTaskWorkItemStore() {
|
|
|
45119
43644
|
return getStoreLattice("default", "taskWorkItem").store;
|
|
45120
43645
|
}
|
|
45121
43646
|
function getProjectTaskWorkItemStore() {
|
|
45122
|
-
return (0,
|
|
43647
|
+
return (0, import_protocols33.requireProjectTaskWorkItemStore)(getTaskWorkItemStore());
|
|
45123
43648
|
}
|
|
45124
43649
|
function reviewInterruption(task) {
|
|
45125
43650
|
const value = task.context?.interruption;
|
|
@@ -45135,73 +43660,72 @@ function buildReviewMarkdown(task) {
|
|
|
45135
43660
|
result: task.result
|
|
45136
43661
|
});
|
|
45137
43662
|
}
|
|
45138
|
-
var manageTaskSchema =
|
|
45139
|
-
action:
|
|
45140
|
-
id:
|
|
45141
|
-
title:
|
|
45142
|
-
description:
|
|
45143
|
-
priority:
|
|
45144
|
-
status:
|
|
45145
|
-
dueDate:
|
|
45146
|
-
metadata:
|
|
45147
|
-
metadataFilter:
|
|
45148
|
-
|
|
43663
|
+
var manageTaskSchema = import_zod68.z.object({
|
|
43664
|
+
action: import_zod68.z.enum(["create", "get", "list", "update", "set_status", "add_activity", "delete"]).describe("Action to perform. Available: create, get, list, update, set_status, add_activity, delete. To change status, use set_status. To change content fields, use update."),
|
|
43665
|
+
id: import_zod68.z.string().optional().describe("Task ID (required for get, update, add_activity; required for delete unless ids is given)"),
|
|
43666
|
+
title: import_zod68.z.string().optional().describe("Task title (required for create)"),
|
|
43667
|
+
description: import_zod68.z.string().optional().describe("Task description in Markdown"),
|
|
43668
|
+
priority: import_zod68.z.enum(["low", "medium", "high"]).optional().describe("Priority level"),
|
|
43669
|
+
status: import_zod68.z.enum(["pending", "in_progress", "review", "failed", "interrupted", "completed", "cancelled"]).optional().describe("Task status. For status-only changes, prefer set_status action. Set 'in_progress' when you start processing a task you hold; 'completed'/'failed' require the task to be 'in_progress'. Agent summary-only interrupted updates default to missing_input"),
|
|
43670
|
+
dueDate: import_zod68.z.string().optional().describe("Due date (ISO 8601 format)"),
|
|
43671
|
+
metadata: import_zod68.z.record(import_zod68.z.unknown()).optional().describe("Structured metadata (e.g. projectId, module)"),
|
|
43672
|
+
metadataFilter: import_zod68.z.record(
|
|
43673
|
+
import_zod68.z.union([import_zod68.z.string(), import_zod68.z.number(), import_zod68.z.boolean()])
|
|
45149
43674
|
).optional().describe("List-only filter. Every key must equal the task metadata value, e.g. {projectId:'p1', retries:2}. Multiple keys AND together."),
|
|
45150
|
-
parentId:
|
|
45151
|
-
sourceId:
|
|
45152
|
-
context:
|
|
45153
|
-
ownerType:
|
|
45154
|
-
ownerId:
|
|
45155
|
-
requireReview:
|
|
45156
|
-
dependencies:
|
|
45157
|
-
|
|
45158
|
-
|
|
45159
|
-
|
|
45160
|
-
|
|
45161
|
-
|
|
45162
|
-
|
|
45163
|
-
addedBy: import_zod71.z.enum(["user", "agent"]).optional().describe("Who attached the file")
|
|
43675
|
+
parentId: import_zod68.z.string().optional().describe("Parent task ID for grouping subtasks"),
|
|
43676
|
+
sourceId: import_zod68.z.string().optional().describe("Source session/thread ID"),
|
|
43677
|
+
context: import_zod68.z.record(import_zod68.z.unknown()).optional().describe("Additional context data"),
|
|
43678
|
+
ownerType: import_zod68.z.enum(["user", "agent"]).optional().describe("Owner type. Defaults to 'user' if omitted"),
|
|
43679
|
+
ownerId: import_zod68.z.string().optional().describe("Owner ID. Auto-filled from current user/agent if omitted"),
|
|
43680
|
+
requireReview: import_zod68.z.boolean().optional().describe("If true, agent completion pauses as interrupted(review_required) for HITL approval"),
|
|
43681
|
+
dependencies: import_zod68.z.array(import_zod68.z.string()).optional().describe("List of task IDs that must be completed before this task can start"),
|
|
43682
|
+
result: import_zod68.z.string().optional().describe("Result summary. Used with set_status status='completed' or update status='completed'"),
|
|
43683
|
+
failureReason: import_zod68.z.string().optional().describe("Failure reason. Used with set_status status='failed' or update status='failed'"),
|
|
43684
|
+
files: import_zod68.z.array(import_zod68.z.object({
|
|
43685
|
+
uri: import_zod68.z.string().describe("Uniquely locates the resource: http(s):// URL, /s/:token share, or sandbox path"),
|
|
43686
|
+
name: import_zod68.z.string().optional().describe("Display name"),
|
|
43687
|
+
addedBy: import_zod68.z.enum(["user", "agent"]).optional().describe("Who attached the file")
|
|
45164
43688
|
})).optional().describe("File references attached to this task"),
|
|
45165
|
-
beliefImpact:
|
|
45166
|
-
key:
|
|
45167
|
-
after:
|
|
45168
|
-
basis:
|
|
45169
|
-
isNew:
|
|
43689
|
+
beliefImpact: import_zod68.z.array(import_zod68.z.object({
|
|
43690
|
+
key: import_zod68.z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
|
|
43691
|
+
after: import_zod68.z.number().int().min(0).max(100),
|
|
43692
|
+
basis: import_zod68.z.string().trim().min(1).max(1e3),
|
|
43693
|
+
isNew: import_zod68.z.boolean().optional().describe("Set true only to add a belief key that is absent from the belief owner's Belief State; omit for keys that already exist")
|
|
45170
43694
|
})).optional().describe("Structured belief reports required when an agent-owned task completes; existing keys update the belief owner's table, and a brand-new key must be declared with isNew: true"),
|
|
45171
|
-
content:
|
|
45172
|
-
summary:
|
|
45173
|
-
executionResultId:
|
|
43695
|
+
content: import_zod68.z.string().optional().describe("Markdown content required for add_activity"),
|
|
43696
|
+
summary: import_zod68.z.string().optional().describe("Brief summary of the operation"),
|
|
43697
|
+
executionResultId: import_zod68.z.string().refine(import_protocols33.isExecutionResultEventKey, {
|
|
45174
43698
|
message: "executionResultId must be the execution-result:<threadId> event key returned by task()"
|
|
45175
43699
|
}).optional().describe(
|
|
45176
43700
|
"Canonical ASCII `execution-result:<suffix>` event key returned by task(); the nonempty suffix allows only A-Z, a-z, 0-9, period, underscore, colon, and hyphen, and is not a database row ID"
|
|
45177
43701
|
),
|
|
45178
|
-
ids:
|
|
43702
|
+
ids: import_zod68.z.array(import_zod68.z.string().trim().min(1)).optional().describe("Task IDs to delete in one batch (delete action only). Use with or instead of id.")
|
|
45179
43703
|
}).superRefine((input, context) => {
|
|
45180
43704
|
if (input.executionResultId && input.action !== "update" && input.action !== "set_status" && input.action !== "add_activity") {
|
|
45181
43705
|
context.addIssue({
|
|
45182
|
-
code:
|
|
43706
|
+
code: import_zod68.z.ZodIssueCode.custom,
|
|
45183
43707
|
path: ["executionResultId"],
|
|
45184
43708
|
message: "executionResultId is valid only for update, set_status, or add_activity"
|
|
45185
43709
|
});
|
|
45186
43710
|
}
|
|
45187
43711
|
if (input.metadataFilter && input.action !== "list") {
|
|
45188
43712
|
context.addIssue({
|
|
45189
|
-
code:
|
|
43713
|
+
code: import_zod68.z.ZodIssueCode.custom,
|
|
45190
43714
|
path: ["metadataFilter"],
|
|
45191
43715
|
message: "metadataFilter is valid only for list"
|
|
45192
43716
|
});
|
|
45193
43717
|
}
|
|
45194
43718
|
if (input.ids && input.action !== "delete") {
|
|
45195
43719
|
context.addIssue({
|
|
45196
|
-
code:
|
|
43720
|
+
code: import_zod68.z.ZodIssueCode.custom,
|
|
45197
43721
|
path: ["ids"],
|
|
45198
43722
|
message: "ids is valid only for delete"
|
|
45199
43723
|
});
|
|
45200
43724
|
}
|
|
45201
43725
|
});
|
|
45202
|
-
var startTaskSchema =
|
|
45203
|
-
taskId:
|
|
45204
|
-
agentId:
|
|
43726
|
+
var startTaskSchema = import_zod68.z.object({
|
|
43727
|
+
taskId: import_zod68.z.string().trim().min(1).describe("ID of the persisted TaskItem to start"),
|
|
43728
|
+
agentId: import_zod68.z.string().trim().min(1).describe(
|
|
45205
43729
|
`ID of the Agent that should execute the task. Use "general-purpose" to run the caller's own capabilities as an isolated worker.`
|
|
45206
43730
|
)
|
|
45207
43731
|
});
|
|
@@ -45235,7 +43759,7 @@ async function getPendingExecutionResultIds(store, tenantId2, taskId) {
|
|
|
45235
43759
|
order: "desc",
|
|
45236
43760
|
limit: PENDING_EXECUTION_RESULT_LIMIT + 1
|
|
45237
43761
|
});
|
|
45238
|
-
const canonicalCandidates = candidates.slice(0, PENDING_EXECUTION_RESULT_LIMIT + 1).filter((item) => (0,
|
|
43762
|
+
const canonicalCandidates = candidates.slice(0, PENDING_EXECUTION_RESULT_LIMIT + 1).filter((item) => (0, import_protocols33.isExecutionResultEventKey)(item.eventKey));
|
|
45239
43763
|
const reconciliationRows = new Array(canonicalCandidates.length);
|
|
45240
43764
|
let nextCandidateIndex = 0;
|
|
45241
43765
|
let firstError;
|
|
@@ -45323,7 +43847,7 @@ function createTaskMiddleware(options = {}) {
|
|
|
45323
43847
|
const workspaceId = trustedScope?.workspaceId ?? rc.workspaceId;
|
|
45324
43848
|
const projectId = trustedScope?.projectId ?? rc.projectId;
|
|
45325
43849
|
const revalidateCaller = async () => {
|
|
45326
|
-
if (!trustedProject) return void 0;
|
|
43850
|
+
if (!trustedProject || trustedRosterExempt(trustedProject)) return void 0;
|
|
45327
43851
|
try {
|
|
45328
43852
|
await createProjectTaskOwnerPolicy().requireCaller(trustedRosterScope(trustedProject));
|
|
45329
43853
|
} catch (error) {
|
|
@@ -45331,7 +43855,7 @@ function createTaskMiddleware(options = {}) {
|
|
|
45331
43855
|
}
|
|
45332
43856
|
return void 0;
|
|
45333
43857
|
};
|
|
45334
|
-
if (trustedProject) {
|
|
43858
|
+
if (trustedProject && !trustedRosterExempt(trustedProject)) {
|
|
45335
43859
|
try {
|
|
45336
43860
|
await createProjectTaskOwnerPolicy().requireCaller(trustedRosterScope(trustedProject));
|
|
45337
43861
|
} catch (error) {
|
|
@@ -45364,10 +43888,12 @@ function createTaskMiddleware(options = {}) {
|
|
|
45364
43888
|
if (trustedProject) {
|
|
45365
43889
|
const snapshot = taskMutationSnapshot(existing);
|
|
45366
43890
|
if (!snapshot) return trustedContextError();
|
|
45367
|
-
|
|
45368
|
-
|
|
45369
|
-
|
|
45370
|
-
|
|
43891
|
+
if (!trustedRosterExempt(trustedProject)) {
|
|
43892
|
+
try {
|
|
43893
|
+
await createProjectTaskOwnerPolicy().requireCaller(trustedRosterScope(trustedProject));
|
|
43894
|
+
} catch (error) {
|
|
43895
|
+
return projectPolicyError(error);
|
|
43896
|
+
}
|
|
45371
43897
|
}
|
|
45372
43898
|
deleted = await store.deleteIfSnapshot(tenantId2, id, snapshot);
|
|
45373
43899
|
} else {
|
|
@@ -45420,13 +43946,15 @@ function createTaskMiddleware(options = {}) {
|
|
|
45420
43946
|
"Target Project task owner is not active in the exact roster."
|
|
45421
43947
|
));
|
|
45422
43948
|
}
|
|
45423
|
-
|
|
45424
|
-
|
|
45425
|
-
|
|
45426
|
-
|
|
45427
|
-
|
|
45428
|
-
|
|
45429
|
-
|
|
43949
|
+
if (!trustedRosterExempt(trustedProject)) {
|
|
43950
|
+
try {
|
|
43951
|
+
await requireTrustedOwner(trustedProject, ownerId);
|
|
43952
|
+
} catch (error) {
|
|
43953
|
+
return projectPolicyError(error instanceof ProjectTaskOwnerPolicyError ? error : new ProjectTaskOwnerPolicyError(
|
|
43954
|
+
"PROJECT_TASK_OWNER_INACTIVE",
|
|
43955
|
+
"Target Project task owner is not active in the exact roster."
|
|
43956
|
+
));
|
|
43957
|
+
}
|
|
45430
43958
|
}
|
|
45431
43959
|
}
|
|
45432
43960
|
if (effectiveOwnerType === "agent" && (input.result !== void 0 || input.failureReason !== void 0)) {
|
|
@@ -45474,10 +44002,12 @@ function createTaskMiddleware(options = {}) {
|
|
|
45474
44002
|
)) return trustedContextError("Parent or dependency task changed before creation.");
|
|
45475
44003
|
const callerError = await revalidateCaller();
|
|
45476
44004
|
if (callerError) return callerError;
|
|
45477
|
-
|
|
45478
|
-
|
|
45479
|
-
|
|
45480
|
-
|
|
44005
|
+
if (!trustedRosterExempt(trustedProject)) {
|
|
44006
|
+
try {
|
|
44007
|
+
await requireTrustedOwner(trustedProject, ownerId);
|
|
44008
|
+
} catch (error) {
|
|
44009
|
+
return projectPolicyError(error);
|
|
44010
|
+
}
|
|
45481
44011
|
}
|
|
45482
44012
|
}
|
|
45483
44013
|
return store.create({
|
|
@@ -45735,18 +44265,6 @@ function createTaskMiddleware(options = {}) {
|
|
|
45735
44265
|
return trustedFailure;
|
|
45736
44266
|
}
|
|
45737
44267
|
}
|
|
45738
|
-
if (trustedProject && input.dependencyTaskIds !== void 0) {
|
|
45739
|
-
const interruption = input.context?.interruption;
|
|
45740
|
-
const interruptionType2 = interruption && typeof interruption === "object" ? interruption.type : void 0;
|
|
45741
|
-
if (input.status !== "interrupted" || interruptionType2 !== "external_dependency") {
|
|
45742
|
-
taskUpdateBlocked(input.id, "INVALID_EXTERNAL_DEPENDENCY", {});
|
|
45743
|
-
return JSON.stringify({
|
|
45744
|
-
success: false,
|
|
45745
|
-
code: "INVALID_EXTERNAL_DEPENDENCY",
|
|
45746
|
-
error: "dependencyTaskIds are only valid for external dependency interruptions."
|
|
45747
|
-
});
|
|
45748
|
-
}
|
|
45749
|
-
}
|
|
45750
44268
|
if (trustedProject && (input.ownerType !== void 0 && input.ownerType !== existing.ownerType || input.ownerId !== void 0 && input.ownerId !== existing.ownerId)) {
|
|
45751
44269
|
taskUpdateBlocked(input.id, "TASK_OWNERSHIP_VIA_DISPATCH_REQUIRED", {
|
|
45752
44270
|
inputOwnerType: input.ownerType,
|
|
@@ -45877,8 +44395,8 @@ function createTaskMiddleware(options = {}) {
|
|
|
45877
44395
|
let reconciliationMetadata = {};
|
|
45878
44396
|
let descriptionMutated = false;
|
|
45879
44397
|
if (isAgentTask && input.description !== void 0 && !valuesEqual(input.description, existing.description)) {
|
|
45880
|
-
const oldBelief = (0,
|
|
45881
|
-
const newBelief = (0,
|
|
44398
|
+
const oldBelief = (0, import_protocols33.parseTaskBeliefState)(existing.description ?? "");
|
|
44399
|
+
const newBelief = (0, import_protocols33.parseTaskBeliefState)(input.description);
|
|
45882
44400
|
const hasBeliefState = oldBelief.success || newBelief.success;
|
|
45883
44401
|
if (hasBeliefState) {
|
|
45884
44402
|
await validateExecutionResult();
|
|
@@ -45938,7 +44456,7 @@ function createTaskMiddleware(options = {}) {
|
|
|
45938
44456
|
return trustedContextError("Parent or dependency task changed before update.");
|
|
45939
44457
|
}
|
|
45940
44458
|
}
|
|
45941
|
-
if (trustedProject) {
|
|
44459
|
+
if (trustedProject && !trustedRosterExempt(trustedProject)) {
|
|
45942
44460
|
try {
|
|
45943
44461
|
await createProjectTaskOwnerPolicy().requireCaller(trustedRosterScope(trustedProject));
|
|
45944
44462
|
} catch (error) {
|
|
@@ -45978,7 +44496,7 @@ function createTaskMiddleware(options = {}) {
|
|
|
45978
44496
|
const workItemSummary = input.summary;
|
|
45979
44497
|
let activityWarnings;
|
|
45980
44498
|
try {
|
|
45981
|
-
if (trustedProject) {
|
|
44499
|
+
if (trustedProject && !trustedRosterExempt(trustedProject)) {
|
|
45982
44500
|
try {
|
|
45983
44501
|
await createProjectTaskOwnerPolicy().requireCaller(trustedRosterScope(trustedProject));
|
|
45984
44502
|
} catch (error) {
|
|
@@ -46063,18 +44581,6 @@ function createTaskMiddleware(options = {}) {
|
|
|
46063
44581
|
return trustedFailure;
|
|
46064
44582
|
}
|
|
46065
44583
|
}
|
|
46066
|
-
if (trustedProject && input.dependencyTaskIds !== void 0) {
|
|
46067
|
-
const interruption = input.context?.interruption;
|
|
46068
|
-
const interruptionType2 = interruption && typeof interruption === "object" ? interruption.type : void 0;
|
|
46069
|
-
if (input.status !== "interrupted" || interruptionType2 !== "external_dependency") {
|
|
46070
|
-
taskUpdateBlocked(input.id, "INVALID_EXTERNAL_DEPENDENCY", {});
|
|
46071
|
-
return JSON.stringify({
|
|
46072
|
-
success: false,
|
|
46073
|
-
code: "INVALID_EXTERNAL_DEPENDENCY",
|
|
46074
|
-
error: "dependencyTaskIds are only valid for external dependency interruptions."
|
|
46075
|
-
});
|
|
46076
|
-
}
|
|
46077
|
-
}
|
|
46078
44584
|
if (trustedProject && (input.ownerType !== void 0 && input.ownerType !== existing.ownerType || input.ownerId !== void 0 && input.ownerId !== existing.ownerId)) {
|
|
46079
44585
|
taskUpdateBlocked(input.id, "TASK_OWNERSHIP_VIA_DISPATCH_REQUIRED", {});
|
|
46080
44586
|
return JSON.stringify({
|
|
@@ -46156,11 +44662,11 @@ function createTaskMiddleware(options = {}) {
|
|
|
46156
44662
|
const interruption = input.context?.interruption;
|
|
46157
44663
|
const explicitType = interruption && typeof interruption === "object" ? interruption.type : void 0;
|
|
46158
44664
|
const type = explicitType ?? "missing_input";
|
|
46159
|
-
if (type !== "missing_input" && type !== "
|
|
44665
|
+
if (type !== "missing_input" && type !== "user_decision") {
|
|
46160
44666
|
return JSON.stringify({
|
|
46161
44667
|
success: false,
|
|
46162
44668
|
code: "INVALID_INTERRUPTION_TYPE",
|
|
46163
|
-
error: "Agent interruption type must be missing_input
|
|
44669
|
+
error: "Agent interruption type must be missing_input or user_decision."
|
|
46164
44670
|
});
|
|
46165
44671
|
}
|
|
46166
44672
|
await validateExecutionResult();
|
|
@@ -46172,8 +44678,7 @@ function createTaskMiddleware(options = {}) {
|
|
|
46172
44678
|
type,
|
|
46173
44679
|
summary: input.summary ?? "",
|
|
46174
44680
|
actor,
|
|
46175
|
-
threadId: statusThreadId
|
|
46176
|
-
dependencyTaskIds: input.dependencyTaskIds
|
|
44681
|
+
threadId: statusThreadId
|
|
46177
44682
|
});
|
|
46178
44683
|
return lifecycleMutationResponse(interrupted);
|
|
46179
44684
|
}
|
|
@@ -46576,12 +45081,12 @@ function createTaskMiddleware(options = {}) {
|
|
|
46576
45081
|
...trustedCaller ? { callerMembershipId: trustedCaller.membershipId, callerAssistantId: trustedCaller.assistantId } : {}
|
|
46577
45082
|
}));
|
|
46578
45083
|
};
|
|
46579
|
-
return (0,
|
|
45084
|
+
return (0, import_langchain83.createMiddleware)({
|
|
46580
45085
|
name: "TaskMiddleware",
|
|
46581
45086
|
contextSchema,
|
|
46582
45087
|
// Persisted between invocations (ADRs: the run↔task binding survives turns).
|
|
46583
|
-
stateSchema:
|
|
46584
|
-
taskId:
|
|
45088
|
+
stateSchema: import_zod68.z.object({
|
|
45089
|
+
taskId: import_zod68.z.string().default("")
|
|
46585
45090
|
}),
|
|
46586
45091
|
// CLAIM: a run that holds a task moves it to in_progress (idempotent).
|
|
46587
45092
|
beforeAgent: async (state, runtime) => {
|
|
@@ -46691,7 +45196,7 @@ ${TASK_CONVERGENCE_GUIDANCE}
|
|
|
46691
45196
|
});
|
|
46692
45197
|
},
|
|
46693
45198
|
tools: [
|
|
46694
|
-
(0,
|
|
45199
|
+
(0, import_langchain83.tool)(
|
|
46695
45200
|
handleManageTask,
|
|
46696
45201
|
{
|
|
46697
45202
|
name: "manage_task",
|
|
@@ -46737,7 +45242,7 @@ to an expert \u2014 never re-dispatch the task you are processing.`,
|
|
|
46737
45242
|
schema: manageTaskSchema
|
|
46738
45243
|
}
|
|
46739
45244
|
),
|
|
46740
|
-
(0,
|
|
45245
|
+
(0, import_langchain83.tool)(handleStartTask, {
|
|
46741
45246
|
name: "task",
|
|
46742
45247
|
description: `Start a persisted TaskItem with any existing Agent in a fresh isolated thread. Use this to delegate work \u2014 dispatch a subtask you created to the agent that should execute it; never re-dispatch the task you are currently processing (give the expert a child task instead). Pass agentId "general-purpose" for the general-purpose worker \u2014 ${DEFAULT_GENERAL_PURPOSE_DESCRIPTION} It has access to all the caller's tools, model, and middleware, so use it for general-purpose subtasks, to isolate context and token usage, and whenever no specialized agent fits. The target does NOT need task-management tools: it runs and returns an observation plus an executionResultId, and the caller passes that executionResultId to the manage_task update or add_activity that interprets and records it. A project task instead returns a managed result (success:true, managed:true) because the project-lifecycle queue owns execution.`,
|
|
46743
45248
|
schema: startTaskSchema
|
|
@@ -46881,8 +45386,7 @@ canonical Belief State:
|
|
|
46881
45386
|
};
|
|
46882
45387
|
|
|
46883
45388
|
// src/middlewares/documentLearningMiddleware.ts
|
|
46884
|
-
var
|
|
46885
|
-
var import_langchain88 = require("langchain");
|
|
45389
|
+
var import_langchain84 = require("langchain");
|
|
46886
45390
|
|
|
46887
45391
|
// src/middlewares/documentLearningSkills.ts
|
|
46888
45392
|
var LEARN_CAPABILITY_SKILL = `---
|
|
@@ -47121,20 +45625,11 @@ patterns discovered, recommendations. Include validation coverage: user-sample N
|
|
|
47121
45625
|
`;
|
|
47122
45626
|
|
|
47123
45627
|
// src/middlewares/documentLearningMiddleware.ts
|
|
47124
|
-
var createDocumentLearningMiddleware = () => (0,
|
|
45628
|
+
var createDocumentLearningMiddleware = () => (0, import_langchain84.createMiddleware)({
|
|
47125
45629
|
name: "DocumentLearningMiddleware",
|
|
47126
45630
|
contextSchema,
|
|
47127
45631
|
tools: []
|
|
47128
45632
|
});
|
|
47129
|
-
var DOCUMENT_LEARNER_SYSTEM_PROMPT = `You are a capability learning specialist.
|
|
47130
|
-
|
|
47131
|
-
CRITICAL FIRST ACTION \u2014 before any response about the task:
|
|
47132
|
-
1. Call the \`skill\` tool with skill_name: "agent-architecture" to load the
|
|
47133
|
-
authoritative Charter.
|
|
47134
|
-
2. Call the \`skill\` tool with skill_name: "document-learning-learn-capability" to
|
|
47135
|
-
load the source-to-capability workflow.
|
|
47136
|
-
Never announce that you will follow a skill. Load both in this order and follow
|
|
47137
|
-
their content. If either load fails, retry it once, then report the failure.`;
|
|
47138
45633
|
var documentLearningPlugin = {
|
|
47139
45634
|
meta: {
|
|
47140
45635
|
type: "document-learning",
|
|
@@ -47143,92 +45638,6 @@ var documentLearningPlugin = {
|
|
|
47143
45638
|
description: "\u4ECE\u6587\u6863\u4E2D\u5B66\u4E60\u77E5\u8BC6\uFF0C\u81EA\u52A8\u6784\u5EFA\u6280\u80FD\u4F53\u7CFB\u548C\u8BC4\u6D4B\u3002 Learn knowledge from documents and build structured skill systems with evaluations.",
|
|
47144
45639
|
recommends: ["skill", "eval"]
|
|
47145
45640
|
},
|
|
47146
|
-
agents: {
|
|
47147
|
-
"document-learner": {
|
|
47148
|
-
key: "document-learner",
|
|
47149
|
-
name: "Document Learning Agent",
|
|
47150
|
-
description: "Read documents and build structured skill systems with evaluations. Use this agent when you need to extract knowledge from documents and turn it into reusable, testable agent skills.",
|
|
47151
|
-
type: import_protocols35.AgentType.DEEP_AGENT,
|
|
47152
|
-
prompt: DOCUMENT_LEARNER_SYSTEM_PROMPT,
|
|
47153
|
-
subAgents: ["document-parser-benchmark"],
|
|
47154
|
-
tools: [
|
|
47155
|
-
"invoke_agent",
|
|
47156
|
-
"list_agents",
|
|
47157
|
-
"create_agent",
|
|
47158
|
-
"update_agent",
|
|
47159
|
-
"delete_agent",
|
|
47160
|
-
"get_agent",
|
|
47161
|
-
"list_tools",
|
|
47162
|
-
"list_middleware_types"
|
|
47163
|
-
],
|
|
47164
|
-
middleware: [
|
|
47165
|
-
{
|
|
47166
|
-
id: "skill",
|
|
47167
|
-
type: "skill",
|
|
47168
|
-
name: "Skill",
|
|
47169
|
-
description: "Skill creation and loading",
|
|
47170
|
-
enabled: true,
|
|
47171
|
-
config: { readAll: true }
|
|
47172
|
-
},
|
|
47173
|
-
{
|
|
47174
|
-
id: "document-learning",
|
|
47175
|
-
type: "document-learning",
|
|
47176
|
-
name: "Document Learning",
|
|
47177
|
-
description: "Source-to-capability learning workflow",
|
|
47178
|
-
enabled: true,
|
|
47179
|
-
config: {}
|
|
47180
|
-
},
|
|
47181
|
-
{
|
|
47182
|
-
id: "eval",
|
|
47183
|
-
type: "eval",
|
|
47184
|
-
name: "Eval",
|
|
47185
|
-
description: "Evaluation design and execution",
|
|
47186
|
-
enabled: true,
|
|
47187
|
-
config: {}
|
|
47188
|
-
},
|
|
47189
|
-
{
|
|
47190
|
-
id: "task",
|
|
47191
|
-
type: "task",
|
|
47192
|
-
name: "Task",
|
|
47193
|
-
description: "Training process tracking with approval gates",
|
|
47194
|
-
enabled: true,
|
|
47195
|
-
config: {}
|
|
47196
|
-
},
|
|
47197
|
-
{
|
|
47198
|
-
id: "widget",
|
|
47199
|
-
type: "widget",
|
|
47200
|
-
name: "Widget",
|
|
47201
|
-
description: "Visualize benchmark results and eval dashboards",
|
|
47202
|
-
enabled: true,
|
|
47203
|
-
config: {}
|
|
47204
|
-
},
|
|
47205
|
-
{
|
|
47206
|
-
id: "ask_user_to_clarify",
|
|
47207
|
-
type: "ask_user_to_clarify",
|
|
47208
|
-
name: "Ask User",
|
|
47209
|
-
description: "Wait for user input at approval gates",
|
|
47210
|
-
enabled: true,
|
|
47211
|
-
config: {}
|
|
47212
|
-
},
|
|
47213
|
-
{
|
|
47214
|
-
id: "filesystem",
|
|
47215
|
-
type: "filesystem",
|
|
47216
|
-
name: "Filesystem",
|
|
47217
|
-
description: "Read documents, write skill files",
|
|
47218
|
-
enabled: true,
|
|
47219
|
-
config: {}
|
|
47220
|
-
},
|
|
47221
|
-
{
|
|
47222
|
-
id: "document-parser",
|
|
47223
|
-
type: "document-parser",
|
|
47224
|
-
name: "Document Parser",
|
|
47225
|
-
description: "Parse documents with the chosen engine",
|
|
47226
|
-
enabled: true,
|
|
47227
|
-
config: { connectAll: true }
|
|
47228
|
-
}
|
|
47229
|
-
]
|
|
47230
|
-
}
|
|
47231
|
-
},
|
|
47232
45641
|
skills: {
|
|
47233
45642
|
"document-learning-learn-capability": {
|
|
47234
45643
|
version: "1.0.0",
|
|
@@ -47239,12 +45648,12 @@ var documentLearningPlugin = {
|
|
|
47239
45648
|
};
|
|
47240
45649
|
|
|
47241
45650
|
// src/middlewares/documentParserMiddleware.ts
|
|
47242
|
-
var
|
|
45651
|
+
var import_langchain86 = require("langchain");
|
|
47243
45652
|
|
|
47244
45653
|
// src/tool_lattice/document_parser/index.ts
|
|
47245
45654
|
var path7 = __toESM(require("path"));
|
|
47246
|
-
var
|
|
47247
|
-
var
|
|
45655
|
+
var import_zod69 = __toESM(require("zod"));
|
|
45656
|
+
var import_langchain85 = require("langchain");
|
|
47248
45657
|
var PARSE_DOCUMENT_DESCRIPTION = `Parse a document file (docx, pdf) into structured Markdown using a remote document parsing service.
|
|
47249
45658
|
This tool handles the full pipeline internally: file upload \u2192 document parsing \u2192 polling until complete \u2192 download result \u2192 save to filesystem.
|
|
47250
45659
|
|
|
@@ -47367,7 +45776,7 @@ function createParseDocumentTool({
|
|
|
47367
45776
|
baseUrl = "",
|
|
47368
45777
|
apiKey = ""
|
|
47369
45778
|
}) {
|
|
47370
|
-
return (0,
|
|
45779
|
+
return (0, import_langchain85.tool)(
|
|
47371
45780
|
async (input, exe_config) => {
|
|
47372
45781
|
try {
|
|
47373
45782
|
const runConfig = exe_config?.configurable?.runConfig ?? { assistant_id: "", thread_id: "" };
|
|
@@ -47438,17 +45847,17 @@ function createParseDocumentTool({
|
|
|
47438
45847
|
{
|
|
47439
45848
|
name: "parse_document",
|
|
47440
45849
|
description: PARSE_DOCUMENT_DESCRIPTION,
|
|
47441
|
-
schema:
|
|
47442
|
-
file_path:
|
|
45850
|
+
schema: import_zod69.default.object({
|
|
45851
|
+
file_path: import_zod69.default.string().describe(
|
|
47443
45852
|
'Absolute path to the document file. Must point to an existing .docx or .pdf file. Example: "/project/reports/contract.docx". The file must be accessible from the current workspace.'
|
|
47444
45853
|
),
|
|
47445
|
-
engine:
|
|
45854
|
+
engine: import_zod69.default.string().describe(
|
|
47446
45855
|
'Parsing engine to use. Available options: "textin" (recommended, works with local files, supports docx/pdf), "datalab" (alternative engine for docx/pdf), "mineru" (requires public URL, use only if textin/datalab fail), "paddleocr_remote" (PaddleOCR, good for scanned documents), "qwen_ocr" (OCR-focused, best for image-heavy PDFs).'
|
|
47447
45856
|
),
|
|
47448
|
-
output_path:
|
|
45857
|
+
output_path: import_zod69.default.string().optional().describe(
|
|
47449
45858
|
'Path to save the parsed result. If not specified, the input extension is replaced with .md. Example: "/project/report.docx" becomes "/project/report.md". Parent directories are created automatically.'
|
|
47450
45859
|
),
|
|
47451
|
-
output_format:
|
|
45860
|
+
output_format: import_zod69.default.enum(["markdown", "json"]).optional().default("markdown").describe(
|
|
47452
45861
|
'Output format. "markdown": structured Markdown with tables, headers, formatting preserved (recommended). "json": raw JSON output from the parsing engine (for programmatic use).'
|
|
47453
45862
|
)
|
|
47454
45863
|
})
|
|
@@ -47457,7 +45866,7 @@ function createParseDocumentTool({
|
|
|
47457
45866
|
}
|
|
47458
45867
|
|
|
47459
45868
|
// src/middlewares/documentParserMiddleware.ts
|
|
47460
|
-
var
|
|
45869
|
+
var import_protocols34 = require("@axiom-lattice/protocols");
|
|
47461
45870
|
|
|
47462
45871
|
// src/middlewares/documentBenchmarkWorkflow.ts
|
|
47463
45872
|
var DOCUMENT_PARSER_BENCHMARK_YAML = `name: document-parser-benchmark
|
|
@@ -47866,7 +46275,7 @@ def main() -> None:
|
|
|
47866
46275
|
if __name__ == "__main__":
|
|
47867
46276
|
main()
|
|
47868
46277
|
`;
|
|
47869
|
-
var
|
|
46278
|
+
var resources = {
|
|
47870
46279
|
"references/api_reference.md": { mimeType: "text/markdown", content: `# API reference
|
|
47871
46280
|
|
|
47872
46281
|
The supported command-line form is 'markitdown input -o output.md'. The Python API uses 'MarkItDown().convert(path)' upstream, but this runtime prefers the installed CLI and does not provide direct Python SDK LLM calls. Use local conversion for local files and keep output as Markdown.` },
|
|
@@ -47895,7 +46304,7 @@ Single file: 'markitdown input -o output.md'. Ordinary directory: 'scripts/batch
|
|
|
47895
46304
|
var DOCUMENT_PARSER_MARKITDOWN_SKILL = {
|
|
47896
46305
|
version: "1.1.0",
|
|
47897
46306
|
content: MARKITDOWN_SKILL_CONTENT,
|
|
47898
|
-
resources
|
|
46307
|
+
resources
|
|
47899
46308
|
};
|
|
47900
46309
|
|
|
47901
46310
|
// src/middlewares/documentParserMiddleware.ts
|
|
@@ -47904,12 +46313,29 @@ function createDocumentParserMiddleware(config) {
|
|
|
47904
46313
|
const baseUrl = config.baseUrl || "";
|
|
47905
46314
|
const apiKey = config.apiKey || "";
|
|
47906
46315
|
const connections = Array.isArray(config.connections) ? config.connections.filter((key5) => typeof key5 === "string") : [];
|
|
47907
|
-
return (0,
|
|
46316
|
+
return (0, import_langchain86.createMiddleware)({
|
|
47908
46317
|
name: "DocumentParser",
|
|
47909
46318
|
contextSchema,
|
|
47910
46319
|
tools: [createParseDocumentTool({ connectAll, connections, baseUrl, apiKey })]
|
|
47911
46320
|
});
|
|
47912
46321
|
}
|
|
46322
|
+
var DOCUMENT_PARSER_SYSTEM_PROMPT = `You are the Document Parser. Turn documents (pdf, docx, images, spreadsheets, and similar) into clean Markdown.
|
|
46323
|
+
|
|
46324
|
+
CRITICAL FIRST ACTION: call the \`skill\` tool with skill_name: "document-parser-markitdown" and follow it. Never announce skill loads.
|
|
46325
|
+
|
|
46326
|
+
DEFAULT \u2014 local MarkItDown:
|
|
46327
|
+
- Single file: run \`markitdown <input> -o <output.md>\` via shell.
|
|
46328
|
+
- Batch or literature collections: use the scripts bundled in the skill.
|
|
46329
|
+
- After converting, verify the output is non-empty and its structure/tables are intact, then report the exact input -> output paths.
|
|
46330
|
+
|
|
46331
|
+
ESCALATION \u2014 remote parse_document:
|
|
46332
|
+
- Call parse_document only when local conversion fails, the format is unsupported, the output is empty or materially incomplete, the structure is badly damaged, OCR quality is inadequate, or the user explicitly asks for professional parsing.
|
|
46333
|
+
- When the user is unsatisfied with quality, use ask_user_to_clarify to ask whether to switch to a remote engine, and recommend one engine based on the observed file features and the user's feedback. If the user names an engine, use it.
|
|
46334
|
+
|
|
46335
|
+
BENCHMARK:
|
|
46336
|
+
- Only when the user explicitly asks to compare engines. Confirm with ask_user_to_clarify first, then delegate to the document-parser-benchmark subagent. Never benchmark by default.
|
|
46337
|
+
|
|
46338
|
+
Report only what you actually produced; never claim success without inspecting the output file.`;
|
|
47913
46339
|
var documentParserPlugin = {
|
|
47914
46340
|
meta: {
|
|
47915
46341
|
type: "document-parser",
|
|
@@ -47980,9 +46406,59 @@ var documentParserPlugin = {
|
|
|
47980
46406
|
},
|
|
47981
46407
|
middleware: (config) => createDocumentParserMiddleware(config),
|
|
47982
46408
|
agents: {
|
|
46409
|
+
"document-parser": {
|
|
46410
|
+
key: "document-parser",
|
|
46411
|
+
type: import_protocols34.AgentType.DEEP_AGENT,
|
|
46412
|
+
name: "Document Parser",
|
|
46413
|
+
description: "Parse documents (pdf, docx, images, spreadsheets) into clean Markdown. Defaults to local MarkItDown; escalates to remote engines only when quality or format needs it; runs engine benchmarking only on explicit request.",
|
|
46414
|
+
prompt: DOCUMENT_PARSER_SYSTEM_PROMPT,
|
|
46415
|
+
subAgents: ["document-parser-benchmark"],
|
|
46416
|
+
middleware: [
|
|
46417
|
+
{
|
|
46418
|
+
id: "skill",
|
|
46419
|
+
type: "skill",
|
|
46420
|
+
name: "Skill",
|
|
46421
|
+
description: "Load the local MarkItDown parsing procedure",
|
|
46422
|
+
enabled: true,
|
|
46423
|
+
config: { readAll: true }
|
|
46424
|
+
},
|
|
46425
|
+
{
|
|
46426
|
+
id: "filesystem",
|
|
46427
|
+
type: "filesystem",
|
|
46428
|
+
name: "Filesystem",
|
|
46429
|
+
description: "Read source documents and write Markdown output",
|
|
46430
|
+
enabled: true,
|
|
46431
|
+
config: { vmIsolation: "project" }
|
|
46432
|
+
},
|
|
46433
|
+
{
|
|
46434
|
+
id: "code_eval",
|
|
46435
|
+
type: "code_eval",
|
|
46436
|
+
name: "Code Runner",
|
|
46437
|
+
description: "Run the markitdown CLI and bundled conversion scripts",
|
|
46438
|
+
enabled: true,
|
|
46439
|
+
config: { vmIsolation: "project" }
|
|
46440
|
+
},
|
|
46441
|
+
{
|
|
46442
|
+
id: "document-parser",
|
|
46443
|
+
type: "document-parser",
|
|
46444
|
+
name: "Document Parser",
|
|
46445
|
+
description: "Remote parse_document fallback for hard documents",
|
|
46446
|
+
enabled: true,
|
|
46447
|
+
config: { connectAll: true }
|
|
46448
|
+
},
|
|
46449
|
+
{
|
|
46450
|
+
id: "ask_user_to_clarify",
|
|
46451
|
+
type: "ask_user_to_clarify",
|
|
46452
|
+
name: "Ask User",
|
|
46453
|
+
description: "Confirm engine switches and benchmark runs",
|
|
46454
|
+
enabled: true,
|
|
46455
|
+
config: {}
|
|
46456
|
+
}
|
|
46457
|
+
]
|
|
46458
|
+
},
|
|
47983
46459
|
"document-parser-benchmark": {
|
|
47984
46460
|
key: "document-parser-benchmark",
|
|
47985
|
-
type:
|
|
46461
|
+
type: import_protocols34.AgentType.WORKFLOW,
|
|
47986
46462
|
name: "Document Parser Benchmark",
|
|
47987
46463
|
description: "Benchmark document parsing engines. Parses a document with 5 engines in parallel, scores results, and produces a ranking report. Use this when you need to evaluate which parsing engine works best for a given document.",
|
|
47988
46464
|
prompt: "Benchmark document parsing engines: parse with 5 engines, score, and rank results.",
|
|
@@ -48019,9 +46495,9 @@ var documentParserPlugin = {
|
|
|
48019
46495
|
|
|
48020
46496
|
// src/middlewares/projectRoomMiddleware.ts
|
|
48021
46497
|
var import_crypto10 = require("crypto");
|
|
48022
|
-
var
|
|
48023
|
-
var
|
|
48024
|
-
var
|
|
46498
|
+
var import_protocols35 = require("@axiom-lattice/protocols");
|
|
46499
|
+
var import_langchain87 = require("langchain");
|
|
46500
|
+
var import_zod70 = require("zod");
|
|
48025
46501
|
var PROJECT_ROOM_CONTEXT_REQUIRED = "PROJECT_ROOM_CONTEXT_REQUIRED";
|
|
48026
46502
|
var PROJECT_ROOM_POST_FAILED = "PROJECT_ROOM_POST_FAILED";
|
|
48027
46503
|
var PROJECT_ROOM_ROSTER_FAILED = "PROJECT_ROOM_ROSTER_FAILED";
|
|
@@ -48041,15 +46517,15 @@ var ROSTER_FAILED = JSON.stringify({
|
|
|
48041
46517
|
error: PROJECT_ROOM_ROSTER_FAILED,
|
|
48042
46518
|
message: PROJECT_ROOM_ROSTER_FAILED_MESSAGE
|
|
48043
46519
|
});
|
|
48044
|
-
var postSchema =
|
|
48045
|
-
text:
|
|
46520
|
+
var postSchema = import_zod70.z.object({
|
|
46521
|
+
text: import_zod70.z.string().trim().min(1).max(2e4)
|
|
48046
46522
|
}).strict();
|
|
48047
|
-
var listSchema =
|
|
46523
|
+
var listSchema = import_zod70.z.object({}).strict();
|
|
48048
46524
|
function ownDataValue2(record, key5) {
|
|
48049
46525
|
if (typeof record !== "object" || record === null || Array.isArray(record)) return void 0;
|
|
48050
46526
|
try {
|
|
48051
46527
|
const descriptor = Object.getOwnPropertyDescriptor(record, key5);
|
|
48052
|
-
return (0,
|
|
46528
|
+
return (0, import_protocols35.descriptorDataValue)(descriptor)?.value;
|
|
48053
46529
|
} catch {
|
|
48054
46530
|
return void 0;
|
|
48055
46531
|
}
|
|
@@ -48059,14 +46535,14 @@ function readTrustedRoomScope(config) {
|
|
|
48059
46535
|
const runConfig = ownDataValue2(configurable, "runConfig");
|
|
48060
46536
|
const projectRoom = ownDataValue2(runConfig, "projectRoom");
|
|
48061
46537
|
try {
|
|
48062
|
-
return (0,
|
|
46538
|
+
return (0, import_protocols35.parseTrustedRunContext)({ projectRoom }).projectRoom;
|
|
48063
46539
|
} catch {
|
|
48064
46540
|
return void 0;
|
|
48065
46541
|
}
|
|
48066
46542
|
}
|
|
48067
46543
|
function exactValues2(value, required, optional = []) {
|
|
48068
46544
|
try {
|
|
48069
|
-
return (0,
|
|
46545
|
+
return (0, import_protocols35.snapshotExactRecord)(value, required, optional);
|
|
48070
46546
|
} catch {
|
|
48071
46547
|
return void 0;
|
|
48072
46548
|
}
|
|
@@ -48102,7 +46578,7 @@ function snapshotMembership3(value) {
|
|
|
48102
46578
|
return { ...values, joinedAt, updatedAt };
|
|
48103
46579
|
}
|
|
48104
46580
|
function snapshotRows(value) {
|
|
48105
|
-
return (0,
|
|
46581
|
+
return (0, import_protocols35.snapshotExactArray)(value) ?? [];
|
|
48106
46582
|
}
|
|
48107
46583
|
async function hasActiveCurrentMembership(scope) {
|
|
48108
46584
|
const memberships = getStoreLattice("default", "projectBotMembership").store;
|
|
@@ -48111,10 +46587,10 @@ async function hasActiveCurrentMembership(scope) {
|
|
|
48111
46587
|
return true;
|
|
48112
46588
|
}
|
|
48113
46589
|
function createProjectRoomMiddleware() {
|
|
48114
|
-
return (0,
|
|
46590
|
+
return (0, import_langchain87.createMiddleware)({
|
|
48115
46591
|
name: "ProjectRoomMiddleware",
|
|
48116
46592
|
tools: [
|
|
48117
|
-
(0,
|
|
46593
|
+
(0, import_langchain87.tool)(async (input, config) => {
|
|
48118
46594
|
const { text } = input;
|
|
48119
46595
|
const scope = readTrustedRoomScope(config);
|
|
48120
46596
|
if (!scope) return CONTEXT_REQUIRED;
|
|
@@ -48145,7 +46621,7 @@ function createProjectRoomMiddleware() {
|
|
|
48145
46621
|
description: "Post a text reply to the current trusted Project Room message",
|
|
48146
46622
|
schema: postSchema
|
|
48147
46623
|
}),
|
|
48148
|
-
(0,
|
|
46624
|
+
(0, import_langchain87.tool)(async (_input, config) => {
|
|
48149
46625
|
const scope = readTrustedRoomScope(config);
|
|
48150
46626
|
if (!scope) return CONTEXT_REQUIRED;
|
|
48151
46627
|
try {
|
|
@@ -48187,9 +46663,9 @@ var projectRoomPlugin = {
|
|
|
48187
46663
|
};
|
|
48188
46664
|
|
|
48189
46665
|
// src/middlewares/sandboxPluginsMiddleware.ts
|
|
48190
|
-
var
|
|
48191
|
-
var
|
|
48192
|
-
var
|
|
46666
|
+
var import_langchain88 = require("langchain");
|
|
46667
|
+
var import_zod71 = require("zod");
|
|
46668
|
+
var import_protocols36 = require("@axiom-lattice/protocols");
|
|
48193
46669
|
|
|
48194
46670
|
// src/middlewares/sandboxPluginsSkills.ts
|
|
48195
46671
|
var PLUGIN_JSON_TEMPLATE = `{
|
|
@@ -48910,16 +47386,16 @@ function tenantIdFrom(exeConfig) {
|
|
|
48910
47386
|
const c = exeConfig;
|
|
48911
47387
|
return c?.configurable?.runConfig?.tenantId ?? "default";
|
|
48912
47388
|
}
|
|
48913
|
-
var managePluginSchema =
|
|
48914
|
-
action:
|
|
48915
|
-
type:
|
|
48916
|
-
manifest:
|
|
48917
|
-
handlers:
|
|
48918
|
-
target:
|
|
48919
|
-
kind:
|
|
48920
|
-
name:
|
|
48921
|
-
input:
|
|
48922
|
-
connectionKey:
|
|
47389
|
+
var managePluginSchema = import_zod71.z.object({
|
|
47390
|
+
action: import_zod71.z.enum(["list", "get", "validate", "create", "update", "delete", "reload", "test"]),
|
|
47391
|
+
type: import_zod71.z.string().optional(),
|
|
47392
|
+
manifest: import_zod71.z.record(import_zod71.z.unknown()).optional(),
|
|
47393
|
+
handlers: import_zod71.z.record(import_zod71.z.string()).optional(),
|
|
47394
|
+
target: import_zod71.z.object({
|
|
47395
|
+
kind: import_zod71.z.enum(["tool", "connection-test", "connection-discover"]),
|
|
47396
|
+
name: import_zod71.z.string().optional(),
|
|
47397
|
+
input: import_zod71.z.unknown().optional(),
|
|
47398
|
+
connectionKey: import_zod71.z.string().optional()
|
|
48923
47399
|
}).optional()
|
|
48924
47400
|
});
|
|
48925
47401
|
var sandboxPluginsPlugin = {
|
|
@@ -48939,7 +47415,7 @@ var sandboxPluginsPlugin = {
|
|
|
48939
47415
|
key: "plugin-builder",
|
|
48940
47416
|
name: "Plugin Builder",
|
|
48941
47417
|
description: "Author and manage tenant plugins in the shared sandbox: clarify goal, inputs/outputs, credentials, and whether a UI is needed; then write the manifest and JS handlers, add an optional HTML MCP App UI, and validate/test with the manage_plugin tool.",
|
|
48942
|
-
type:
|
|
47418
|
+
type: import_protocols36.AgentType.DEEP_AGENT,
|
|
48943
47419
|
prompt: PLUGIN_BUILDER_PROMPT,
|
|
48944
47420
|
middleware: [
|
|
48945
47421
|
{
|
|
@@ -48993,10 +47469,10 @@ var sandboxPluginsPlugin = {
|
|
|
48993
47469
|
]
|
|
48994
47470
|
}
|
|
48995
47471
|
},
|
|
48996
|
-
middleware: () => (0,
|
|
47472
|
+
middleware: () => (0, import_langchain88.createMiddleware)({
|
|
48997
47473
|
name: "SandboxPluginsMiddleware",
|
|
48998
47474
|
tools: [
|
|
48999
|
-
(0,
|
|
47475
|
+
(0, import_langchain88.tool)(
|
|
49000
47476
|
async (input, exeConfig) => {
|
|
49001
47477
|
const tenantId2 = tenantIdFrom(exeConfig);
|
|
49002
47478
|
const catalog2 = getSandboxPluginCatalog();
|
|
@@ -49137,7 +47613,6 @@ var BUILTIN_PLUGINS = [
|
|
|
49137
47613
|
sqlPlugin,
|
|
49138
47614
|
skillPlugin,
|
|
49139
47615
|
metricsPlugin,
|
|
49140
|
-
semanticMetricsPlugin,
|
|
49141
47616
|
askUserClarifyPlugin,
|
|
49142
47617
|
widgetPlugin,
|
|
49143
47618
|
clawPlugin,
|
|
@@ -49777,7 +48252,6 @@ registerBuiltinPlugins();
|
|
|
49777
48252
|
createSandboxProvider,
|
|
49778
48253
|
createSandboxResolver,
|
|
49779
48254
|
createSchedulerMiddleware,
|
|
49780
|
-
createSemanticMetricsMiddleware,
|
|
49781
48255
|
createSharePayload,
|
|
49782
48256
|
createTaskExecutionService,
|
|
49783
48257
|
createTaskLifecycleService,
|
|
@@ -49861,6 +48335,7 @@ registerBuiltinPlugins();
|
|
|
49861
48335
|
invokeWithRetry,
|
|
49862
48336
|
isBuiltInSkill,
|
|
49863
48337
|
isDirectRoom,
|
|
48338
|
+
isMcpConnectionError,
|
|
49864
48339
|
isPluginSkillAuthorizedInSandbox,
|
|
49865
48340
|
isPluginSkillManagedInSandbox,
|
|
49866
48341
|
isUsingDefaultKey,
|
|
@@ -49883,7 +48358,6 @@ registerBuiltinPlugins();
|
|
|
49883
48358
|
parallelLimit,
|
|
49884
48359
|
parseCronExpression,
|
|
49885
48360
|
parseDirectRoomType,
|
|
49886
|
-
parseExternalDependency,
|
|
49887
48361
|
parseJudgeVerdict,
|
|
49888
48362
|
parsePackSize,
|
|
49889
48363
|
parseQueuedExecutionMode,
|
|
@@ -49936,7 +48410,6 @@ registerBuiltinPlugins();
|
|
|
49936
48410
|
sandboxLatticeManager,
|
|
49937
48411
|
sanitizeToolCallId,
|
|
49938
48412
|
scheduleLatticeManager,
|
|
49939
|
-
semanticMetricsPlugin,
|
|
49940
48413
|
serializePluginMeta,
|
|
49941
48414
|
serializeTaskMutationSuccess,
|
|
49942
48415
|
serializeTaskNormalizationFallback,
|