linkque-cli-v2 1.0.7 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/linkquejs.js +42 -11
- package/package.json +1 -1
- package/vendor/linkque-agent-appwrite-integrate/dist/esm/{chunk-FJ2BZPIM.js → chunk-MN4S5EF5.js} +237 -79
- package/vendor/linkque-agent-appwrite-integrate/dist/esm/runtime/handler/chat.js +77 -10
- package/vendor/linkque-agent-appwrite-integrate/dist/esm/runtime/protocol.js +1 -1
- package/worker.js +406 -117
package/linkquejs.js
CHANGED
|
@@ -25449,6 +25449,20 @@ function getJsonSchemaIssues(value, path22 = "schema", options = {}) {
|
|
|
25449
25449
|
validateSchemaNode(value, path22, issues, options);
|
|
25450
25450
|
return issues;
|
|
25451
25451
|
}
|
|
25452
|
+
var OPAQUE_OBJECT_SCHEMA = {
|
|
25453
|
+
type: "object",
|
|
25454
|
+
additionalProperties: true
|
|
25455
|
+
};
|
|
25456
|
+
function normalizeMcpOutputSchema(value) {
|
|
25457
|
+
if (!isPlainRecord(value) || getJsonSchemaIssues(value).length > 0) {
|
|
25458
|
+
return { schema: { ...OPAQUE_OBJECT_SCHEMA }, mode: "opaque" };
|
|
25459
|
+
}
|
|
25460
|
+
const schema = cloneJsonValue(value);
|
|
25461
|
+
if (schema.type === "object" && (!isPlainRecord(schema.properties) || Object.keys(schema.properties).length === 0) && !isPlainRecord(schema.additionalProperties)) {
|
|
25462
|
+
return { schema: { ...OPAQUE_OBJECT_SCHEMA }, mode: "opaque" };
|
|
25463
|
+
}
|
|
25464
|
+
return { schema, mode: "declared" };
|
|
25465
|
+
}
|
|
25452
25466
|
function normalizeTargetJsonSchema(schema) {
|
|
25453
25467
|
const cloned = JSON.parse(JSON.stringify(schema));
|
|
25454
25468
|
normalizeObjectDefaults(cloned);
|
|
@@ -25901,7 +25915,7 @@ function parseA2UICardBindingContext(value) {
|
|
|
25901
25915
|
const issues = getA2UICardBindingContextIssues(value);
|
|
25902
25916
|
return issues.length > 0 ? { success: false, issues } : {
|
|
25903
25917
|
success: true,
|
|
25904
|
-
data:
|
|
25918
|
+
data: normalizeBindingContext(value),
|
|
25905
25919
|
issues: []
|
|
25906
25920
|
};
|
|
25907
25921
|
}
|
|
@@ -26048,11 +26062,7 @@ function validateA2UICardBindings(input, options = {}) {
|
|
|
26048
26062
|
issues.push(issue2(`fields.${field.fieldId}`, "MCP_TOOL_UNAVAILABLE", `MCP tool ${binding.toolName} is absent from binding context`));
|
|
26049
26063
|
continue;
|
|
26050
26064
|
}
|
|
26051
|
-
const transform = validateA2UICardTransform(binding.transform
|
|
26052
|
-
fieldId: field.fieldId,
|
|
26053
|
-
sourceSchema: tool.outputSchema,
|
|
26054
|
-
targetSchema: field.valueSchema
|
|
26055
|
-
});
|
|
26065
|
+
const transform = validateA2UICardTransform(binding.transform);
|
|
26056
26066
|
issues.push(...transform.issues.map((entry) => ({
|
|
26057
26067
|
...entry,
|
|
26058
26068
|
path: `fields.${field.fieldId}.${entry.path}`
|
|
@@ -26123,6 +26133,7 @@ function validateTool(value, path22, resourceId, issues) {
|
|
|
26123
26133
|
"description",
|
|
26124
26134
|
"inputSchema",
|
|
26125
26135
|
"outputSchema",
|
|
26136
|
+
"outputSchemaMode",
|
|
26126
26137
|
"annotations"
|
|
26127
26138
|
], path22, issues);
|
|
26128
26139
|
if (value.resourceId !== resourceId) {
|
|
@@ -26132,11 +26143,28 @@ function validateTool(value, path22, resourceId, issues) {
|
|
|
26132
26143
|
issues.push(issue2(`${path22}.toolName`, "CARD_BINDING_CONTEXT_INVALID", "toolName is required"));
|
|
26133
26144
|
}
|
|
26134
26145
|
issues.push(...getJsonSchemaIssues(value.inputSchema, `${path22}.inputSchema`));
|
|
26135
|
-
|
|
26136
|
-
|
|
26137
|
-
issues.push(issue2(`${path22}.annotations`, "CARD_BINDING_CONTEXT_INVALID", "tool explicitly declares readOnlyHint=false"));
|
|
26146
|
+
if (value.outputSchemaMode !== void 0 && value.outputSchemaMode !== "declared" && value.outputSchemaMode !== "opaque") {
|
|
26147
|
+
issues.push(issue2(`${path22}.outputSchemaMode`, "CARD_BINDING_CONTEXT_INVALID", "outputSchemaMode must be declared or opaque"));
|
|
26138
26148
|
}
|
|
26139
26149
|
}
|
|
26150
|
+
function normalizeBindingContext(context) {
|
|
26151
|
+
const cloned = JSON.parse(JSON.stringify(context));
|
|
26152
|
+
cloned.candidates = cloned.candidates.map((candidate) => {
|
|
26153
|
+
if (candidate.status !== "ready")
|
|
26154
|
+
return candidate;
|
|
26155
|
+
const normalized = normalizeMcpOutputSchema(candidate.tool.outputSchema);
|
|
26156
|
+
const mode2 = normalized.mode === "opaque" || candidate.tool.outputSchemaMode === "opaque" ? "opaque" : "declared";
|
|
26157
|
+
return {
|
|
26158
|
+
...candidate,
|
|
26159
|
+
tool: {
|
|
26160
|
+
...candidate.tool,
|
|
26161
|
+
outputSchema: normalized.schema,
|
|
26162
|
+
outputSchemaMode: mode2
|
|
26163
|
+
}
|
|
26164
|
+
};
|
|
26165
|
+
});
|
|
26166
|
+
return cloned;
|
|
26167
|
+
}
|
|
26140
26168
|
function validatePreferences(value, path22, issues) {
|
|
26141
26169
|
if (value === void 0)
|
|
26142
26170
|
return;
|
|
@@ -27150,7 +27178,7 @@ function compileV3Resource(draft, revision, bindings, tools) {
|
|
|
27150
27178
|
purpose: binding.purpose,
|
|
27151
27179
|
required: binding.required,
|
|
27152
27180
|
...binding.dependsOn?.length ? { dependsOn: [...binding.dependsOn] } : {},
|
|
27153
|
-
outputSchema: tool?.outputSchema
|
|
27181
|
+
outputSchema: normalizeMcpOutputSchema(tool?.outputSchema).schema
|
|
27154
27182
|
};
|
|
27155
27183
|
const previous = sourceById.get(source.sourceId);
|
|
27156
27184
|
if (previous && stableJsonStringify(previous) !== stableJsonStringify(source)) {
|
|
@@ -27600,7 +27628,10 @@ async function validateCardBindingsFromDisk(cwd, draftId, expectedContextChecksu
|
|
|
27600
27628
|
}
|
|
27601
27629
|
const context = contextResult.data;
|
|
27602
27630
|
const actualContextChecksum = createA2UICardBindingContextChecksum(context);
|
|
27603
|
-
|
|
27631
|
+
const legacyContextChecksum = createA2UICardBindingContextChecksum(
|
|
27632
|
+
contextValue
|
|
27633
|
+
);
|
|
27634
|
+
if (actualContextChecksum !== expectedContextChecksum && legacyContextChecksum !== expectedContextChecksum) {
|
|
27604
27635
|
throw new LinkqueCliError(
|
|
27605
27636
|
"CARD_BINDING_CONTEXT_STALE",
|
|
27606
27637
|
"\u7ED1\u5B9A\u4E0A\u4E0B\u6587\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u53D1\u8D77 AI \u8F85\u52A9\u7ED1\u5B9A"
|
package/package.json
CHANGED
package/vendor/linkque-agent-appwrite-integrate/dist/esm/{chunk-FJ2BZPIM.js → chunk-MN4S5EF5.js}
RENAMED
|
@@ -1385,7 +1385,7 @@ var require_errors = __commonJS({
|
|
|
1385
1385
|
message: ({ keyword }) => (0, codegen_1.str)`must pass "${keyword}" keyword validation`
|
|
1386
1386
|
};
|
|
1387
1387
|
exports.keyword$DataError = {
|
|
1388
|
-
message: ({ keyword, schemaType }) =>
|
|
1388
|
+
message: ({ keyword, schemaType: schemaType2 }) => schemaType2 ? (0, codegen_1.str)`"${keyword}" keyword must be ${schemaType2} ($data)` : (0, codegen_1.str)`"${keyword}" keyword is invalid ($data)`
|
|
1389
1389
|
};
|
|
1390
1390
|
function reportError(cxt, error = exports.keywordError, errorPaths, overrideAllErrors) {
|
|
1391
1391
|
const { it } = cxt;
|
|
@@ -2044,8 +2044,8 @@ var require_keyword = __commonJS({
|
|
|
2044
2044
|
throw new Error(`keyword "${keyword}" failed to compile`);
|
|
2045
2045
|
return gen.scopeValue("keyword", typeof result == "function" ? { ref: result } : { ref: result, code: (0, codegen_1.stringify)(result) });
|
|
2046
2046
|
}
|
|
2047
|
-
function validSchemaType(schema,
|
|
2048
|
-
return !
|
|
2047
|
+
function validSchemaType(schema, schemaType2, allowUndefined = false) {
|
|
2048
|
+
return !schemaType2.length || schemaType2.some((st) => st === "array" ? Array.isArray(schema) : st === "object" ? schema && typeof schema == "object" && !Array.isArray(schema) : typeof schema == st || allowUndefined && typeof schema == "undefined");
|
|
2049
2049
|
}
|
|
2050
2050
|
exports.validSchemaType = validSchemaType;
|
|
2051
2051
|
function validateKeywordUsage({ schema, opts, self, errSchemaPath }, def, keyword) {
|
|
@@ -2823,11 +2823,11 @@ var require_validate = __commonJS({
|
|
|
2823
2823
|
check$data(valid = codegen_1.nil, $dataValid = codegen_1.nil) {
|
|
2824
2824
|
if (!this.$data)
|
|
2825
2825
|
return;
|
|
2826
|
-
const { gen, schemaCode, schemaType, def } = this;
|
|
2826
|
+
const { gen, schemaCode, schemaType: schemaType2, def } = this;
|
|
2827
2827
|
gen.if((0, codegen_1.or)((0, codegen_1._)`${schemaCode} === undefined`, $dataValid));
|
|
2828
2828
|
if (valid !== codegen_1.nil)
|
|
2829
2829
|
gen.assign(valid, true);
|
|
2830
|
-
if (
|
|
2830
|
+
if (schemaType2.length || def.validateSchema) {
|
|
2831
2831
|
gen.elseIf(this.invalid$data());
|
|
2832
2832
|
this.$dataError();
|
|
2833
2833
|
if (valid !== codegen_1.nil)
|
|
@@ -2836,13 +2836,13 @@ var require_validate = __commonJS({
|
|
|
2836
2836
|
gen.else();
|
|
2837
2837
|
}
|
|
2838
2838
|
invalid$data() {
|
|
2839
|
-
const { gen, schemaCode, schemaType, def, it } = this;
|
|
2839
|
+
const { gen, schemaCode, schemaType: schemaType2, def, it } = this;
|
|
2840
2840
|
return (0, codegen_1.or)(wrong$DataType(), invalid$DataSchema());
|
|
2841
2841
|
function wrong$DataType() {
|
|
2842
|
-
if (
|
|
2842
|
+
if (schemaType2.length) {
|
|
2843
2843
|
if (!(schemaCode instanceof codegen_1.Name))
|
|
2844
2844
|
throw new Error("ajv implementation error");
|
|
2845
|
-
const st = Array.isArray(
|
|
2845
|
+
const st = Array.isArray(schemaType2) ? schemaType2 : [schemaType2];
|
|
2846
2846
|
return (0, codegen_1._)`${(0, dataType_2.checkDataTypes)(st, schemaCode, it.opts.strictNumbers, dataType_2.DataType.Wrong)}`;
|
|
2847
2847
|
}
|
|
2848
2848
|
return codegen_1.nil;
|
|
@@ -16666,6 +16666,9 @@ function isJsonValue(value) {
|
|
|
16666
16666
|
return value.every(isJsonValue);
|
|
16667
16667
|
return isPlainRecord(value) && Object.values(value).every(isJsonValue);
|
|
16668
16668
|
}
|
|
16669
|
+
function cloneJsonValue(value) {
|
|
16670
|
+
return isJsonValue(value) ? JSON.parse(JSON.stringify(value)) : void 0;
|
|
16671
|
+
}
|
|
16669
16672
|
function cloneJsonObject(value) {
|
|
16670
16673
|
if (!isPlainRecord(value) || !isJsonValue(value))
|
|
16671
16674
|
return void 0;
|
|
@@ -17978,7 +17981,7 @@ function optionalString(value, path2, issues) {
|
|
|
17978
17981
|
|
|
17979
17982
|
// ../agent-a2ui-card-contract/dist/esm/resolver.js
|
|
17980
17983
|
var A2UICardResolverError = class extends Error {
|
|
17981
|
-
constructor(code, message, fieldId) {
|
|
17984
|
+
constructor(code, message, fieldId, expectedType, actualType) {
|
|
17982
17985
|
super(message);
|
|
17983
17986
|
Object.defineProperty(this, "code", {
|
|
17984
17987
|
enumerable: true,
|
|
@@ -17992,9 +17995,23 @@ var A2UICardResolverError = class extends Error {
|
|
|
17992
17995
|
writable: true,
|
|
17993
17996
|
value: void 0
|
|
17994
17997
|
});
|
|
17998
|
+
Object.defineProperty(this, "expectedType", {
|
|
17999
|
+
enumerable: true,
|
|
18000
|
+
configurable: true,
|
|
18001
|
+
writable: true,
|
|
18002
|
+
value: void 0
|
|
18003
|
+
});
|
|
18004
|
+
Object.defineProperty(this, "actualType", {
|
|
18005
|
+
enumerable: true,
|
|
18006
|
+
configurable: true,
|
|
18007
|
+
writable: true,
|
|
18008
|
+
value: void 0
|
|
18009
|
+
});
|
|
17995
18010
|
this.name = "A2UICardResolverError";
|
|
17996
18011
|
this.code = code;
|
|
17997
18012
|
this.fieldId = fieldId;
|
|
18013
|
+
this.expectedType = expectedType;
|
|
18014
|
+
this.actualType = actualType;
|
|
17998
18015
|
}
|
|
17999
18016
|
};
|
|
18000
18017
|
async function executeA2UICardResolver(input) {
|
|
@@ -18014,8 +18031,8 @@ async function executeA2UICardResolver(input) {
|
|
|
18014
18031
|
if (!tool) {
|
|
18015
18032
|
throw new A2UICardResolverError("MCP_TOOL_UNAVAILABLE", `MCP tool ${call.mcpResourceId}/${call.toolName} is unavailable`, fieldId);
|
|
18016
18033
|
}
|
|
18017
|
-
if (!tool.
|
|
18018
|
-
throw new A2UICardResolverError("MCP_SCHEMA_UNSUPPORTED", `MCP tool ${call.mcpResourceId}/${call.toolName}
|
|
18034
|
+
if (!tool.outputSchema) {
|
|
18035
|
+
throw new A2UICardResolverError("MCP_SCHEMA_UNSUPPORTED", `MCP tool ${call.mcpResourceId}/${call.toolName} has no output schema`, fieldId);
|
|
18019
18036
|
}
|
|
18020
18037
|
const args = {};
|
|
18021
18038
|
for (const binding of call.inputBindings) {
|
|
@@ -18042,7 +18059,7 @@ async function executeA2UICardResolver(input) {
|
|
|
18042
18059
|
for (const binding of input.resolver.outputBindings) {
|
|
18043
18060
|
const field = fieldById.get(binding.fieldId);
|
|
18044
18061
|
const result = results.get(binding.callId);
|
|
18045
|
-
if (!field ||
|
|
18062
|
+
if (!field || result === void 0) {
|
|
18046
18063
|
throw new A2UICardResolverError("CARD_BINDING_INVALID", `Output binding ${binding.fieldId} is invalid`, binding.fieldId);
|
|
18047
18064
|
}
|
|
18048
18065
|
let value;
|
|
@@ -18078,7 +18095,7 @@ async function executeA2UICardResolver(input) {
|
|
|
18078
18095
|
}
|
|
18079
18096
|
const value = readJsonPointer(viewModel, field.path);
|
|
18080
18097
|
if (field.required && value === void 0) {
|
|
18081
|
-
throw new A2UICardResolverError("CARD_REQUIRED_FIELD_MISSING", `Required card field ${field.fieldId} is missing`, field.fieldId);
|
|
18098
|
+
throw new A2UICardResolverError("CARD_REQUIRED_FIELD_MISSING", `Required card field ${field.fieldId} is missing`, field.fieldId, field.type, "missing");
|
|
18082
18099
|
}
|
|
18083
18100
|
if (value !== void 0) {
|
|
18084
18101
|
assertSchemaValue(field.valueSchema, value, "CARD_MAPPING_SCHEMA_MISMATCH", `card field ${field.fieldId}`, field.fieldId);
|
|
@@ -18118,8 +18135,8 @@ function normalizeOptionalNulls(value, schema, required) {
|
|
|
18118
18135
|
}
|
|
18119
18136
|
async function executeTool(tool, args, signal, fieldId) {
|
|
18120
18137
|
const response = await tool.call(args, signal);
|
|
18121
|
-
const structured =
|
|
18122
|
-
if (
|
|
18138
|
+
const structured = cloneJsonValue(response.structuredContent);
|
|
18139
|
+
if (structured === void 0) {
|
|
18123
18140
|
throw new A2UICardResolverError("MCP_STRUCTURED_CONTENT_REQUIRED", `MCP tool ${tool.resourceId}/${tool.toolName} did not return structuredContent`, fieldId);
|
|
18124
18141
|
}
|
|
18125
18142
|
return structured;
|
|
@@ -18133,9 +18150,19 @@ function toolKey(resourceId, toolName) {
|
|
|
18133
18150
|
function assertSchemaValue(schema, value, code, label, fieldId) {
|
|
18134
18151
|
const issues = validateJsonSchemaValue2(schema, value);
|
|
18135
18152
|
if (issues.length > 0) {
|
|
18136
|
-
throw new A2UICardResolverError(code, `${label} does not match schema at ${issues[0].path}: ${issues[0].message}`, fieldId);
|
|
18153
|
+
throw new A2UICardResolverError(code, `${label} does not match schema at ${issues[0].path}: ${issues[0].message}`, fieldId, schemaType(schema), valueType2(value));
|
|
18137
18154
|
}
|
|
18138
18155
|
}
|
|
18156
|
+
function schemaType(schema) {
|
|
18157
|
+
return typeof schema.type === "string" ? schema.type : "unknown";
|
|
18158
|
+
}
|
|
18159
|
+
function valueType2(value) {
|
|
18160
|
+
if (value === null)
|
|
18161
|
+
return "null";
|
|
18162
|
+
if (Array.isArray(value))
|
|
18163
|
+
return "array";
|
|
18164
|
+
return typeof value === "object" ? "object" : typeof value;
|
|
18165
|
+
}
|
|
18139
18166
|
|
|
18140
18167
|
// ../linkque-agent-runtime/dist/esm/core/mcpNaming.js
|
|
18141
18168
|
import { createHash } from "node:crypto";
|
|
@@ -18172,7 +18199,7 @@ async function executeCardPresentation(resource, registry, runtimeContext, args,
|
|
|
18172
18199
|
if (!handle) {
|
|
18173
18200
|
throw new Error(`MCP tool ${call.mcpResourceId}/${call.toolName} is unavailable`);
|
|
18174
18201
|
}
|
|
18175
|
-
const inputSchema =
|
|
18202
|
+
const inputSchema = normalizeMcpInputSchema(handle.inputSchema);
|
|
18176
18203
|
return {
|
|
18177
18204
|
resourceId: call.mcpResourceId,
|
|
18178
18205
|
toolName: call.toolName,
|
|
@@ -18182,9 +18209,6 @@ async function executeCardPresentation(resource, registry, runtimeContext, args,
|
|
|
18182
18209
|
// ViewModel Schema 校验。
|
|
18183
18210
|
inputSchema,
|
|
18184
18211
|
outputSchema: isJsonObject(handle.outputSchema) ? handle.outputSchema : FALLBACK_OBJECT_SCHEMA,
|
|
18185
|
-
// 未声明 readOnlyHint 是旧 MCP 的常见情况;只拒绝明确声明
|
|
18186
|
-
// readOnlyHint=false 的工具。
|
|
18187
|
-
readOnly: handle.readOnly !== false,
|
|
18188
18212
|
call: async (input, callSignal) => {
|
|
18189
18213
|
const result = await handle.execute(supplementMcpInput(input, invocation, config.presentationInputSchema, inputSchema), callSignal);
|
|
18190
18214
|
return { structuredContent: readStructuredContent(result) };
|
|
@@ -18233,29 +18257,46 @@ async function executeCardPresentationFromSources(resource, runtimeContext, sour
|
|
|
18233
18257
|
transform: binding.transform
|
|
18234
18258
|
}))
|
|
18235
18259
|
};
|
|
18236
|
-
|
|
18237
|
-
|
|
18238
|
-
|
|
18239
|
-
|
|
18240
|
-
|
|
18241
|
-
|
|
18242
|
-
|
|
18243
|
-
|
|
18244
|
-
|
|
18245
|
-
|
|
18246
|
-
|
|
18247
|
-
|
|
18248
|
-
|
|
18249
|
-
|
|
18250
|
-
|
|
18251
|
-
|
|
18252
|
-
|
|
18253
|
-
|
|
18254
|
-
|
|
18255
|
-
|
|
18256
|
-
|
|
18257
|
-
|
|
18258
|
-
|
|
18260
|
+
let viewModel;
|
|
18261
|
+
try {
|
|
18262
|
+
viewModel = await executeA2UICardResolver({
|
|
18263
|
+
resolver,
|
|
18264
|
+
fields: config.fields,
|
|
18265
|
+
presentationInputSchema: {
|
|
18266
|
+
type: "object",
|
|
18267
|
+
properties: {},
|
|
18268
|
+
additionalProperties: false
|
|
18269
|
+
},
|
|
18270
|
+
argsSchema: config.a2uiTemplate.argsSchema,
|
|
18271
|
+
invocation: {},
|
|
18272
|
+
runtimeContext,
|
|
18273
|
+
tools: config.dataSources.filter((source) => sourceResults.has(source.sourceId)).map((source) => ({
|
|
18274
|
+
resourceId: source.mcpResourceId,
|
|
18275
|
+
toolName: source.toolName,
|
|
18276
|
+
inputSchema: FALLBACK_OBJECT_SCHEMA,
|
|
18277
|
+
outputSchema: source.outputSchema ?? FALLBACK_OBJECT_SCHEMA,
|
|
18278
|
+
call: async () => ({
|
|
18279
|
+
structuredContent: sourceResults.get(source.sourceId)
|
|
18280
|
+
})
|
|
18281
|
+
})),
|
|
18282
|
+
signal
|
|
18283
|
+
});
|
|
18284
|
+
} catch (error) {
|
|
18285
|
+
if (error instanceof A2UICardResolverError) {
|
|
18286
|
+
const binding = config.bindings.find((candidate) => candidate.fieldId === error.fieldId);
|
|
18287
|
+
const field = config.fields.find((candidate) => candidate.fieldId === error.fieldId);
|
|
18288
|
+
throw new CardMappingError({
|
|
18289
|
+
code: error.code,
|
|
18290
|
+
cardId: resource.resourceId,
|
|
18291
|
+
fieldId: error.fieldId ?? "unknown",
|
|
18292
|
+
sourceId: binding?.sourceId ?? "unknown",
|
|
18293
|
+
expectedType: error.expectedType ?? field?.type ?? "unknown",
|
|
18294
|
+
actualType: error.actualType ?? "unknown",
|
|
18295
|
+
retryable: false
|
|
18296
|
+
});
|
|
18297
|
+
}
|
|
18298
|
+
throw error;
|
|
18299
|
+
}
|
|
18259
18300
|
return createPresentationResult(resource, config, viewModel);
|
|
18260
18301
|
}
|
|
18261
18302
|
function createPresentationResult(resource, config, viewModel) {
|
|
@@ -18349,23 +18390,44 @@ function compatibleSchemaTypes(source, target) {
|
|
|
18349
18390
|
function readStructuredContent(result) {
|
|
18350
18391
|
if (!isJsonObject(result))
|
|
18351
18392
|
return void 0;
|
|
18352
|
-
if (
|
|
18353
|
-
return
|
|
18393
|
+
if (Object.hasOwn(result, "structuredContent") && isJsonValue(result.structuredContent)) {
|
|
18394
|
+
return cloneJsonValue(result.structuredContent);
|
|
18354
18395
|
}
|
|
18355
|
-
if (!Array.isArray(result.content) || result.content.length
|
|
18396
|
+
if (!Array.isArray(result.content) || result.content.length === 0) {
|
|
18356
18397
|
return void 0;
|
|
18357
18398
|
}
|
|
18358
|
-
const
|
|
18359
|
-
|
|
18360
|
-
|
|
18399
|
+
const texts = [];
|
|
18400
|
+
for (const content of result.content) {
|
|
18401
|
+
if (!isJsonObject(content) || content.type !== "text" || typeof content.text !== "string")
|
|
18402
|
+
return void 0;
|
|
18403
|
+
texts.push(content.text);
|
|
18361
18404
|
}
|
|
18405
|
+
if (texts.length > 1)
|
|
18406
|
+
return texts.join("\n");
|
|
18362
18407
|
try {
|
|
18363
|
-
const parsed = JSON.parse(
|
|
18364
|
-
return
|
|
18408
|
+
const parsed = JSON.parse(texts[0]);
|
|
18409
|
+
return isJsonValue(parsed) ? cloneJsonValue(parsed) : texts[0];
|
|
18365
18410
|
} catch {
|
|
18366
|
-
return
|
|
18411
|
+
return texts[0];
|
|
18367
18412
|
}
|
|
18368
18413
|
}
|
|
18414
|
+
function normalizeMcpInputSchema(value) {
|
|
18415
|
+
if (!isJsonObject(value) || getJsonSchemaIssues2(value).length > 0) {
|
|
18416
|
+
return { ...FALLBACK_OBJECT_SCHEMA };
|
|
18417
|
+
}
|
|
18418
|
+
if (value.type === "object" && (!isJsonObject(value.properties) || Object.keys(value.properties).length === 0))
|
|
18419
|
+
return { ...FALLBACK_OBJECT_SCHEMA };
|
|
18420
|
+
return JSON.parse(JSON.stringify(value));
|
|
18421
|
+
}
|
|
18422
|
+
var CardMappingError = class extends Error {
|
|
18423
|
+
details;
|
|
18424
|
+
retryable = false;
|
|
18425
|
+
constructor(details) {
|
|
18426
|
+
super(JSON.stringify(details));
|
|
18427
|
+
this.name = "CardMappingError";
|
|
18428
|
+
this.details = details;
|
|
18429
|
+
}
|
|
18430
|
+
};
|
|
18369
18431
|
function isJsonObject(value) {
|
|
18370
18432
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
18371
18433
|
}
|
|
@@ -18473,11 +18535,9 @@ var McpProxyTool = class {
|
|
|
18473
18535
|
const tool = entry.tools.find((t) => t.name === toolName);
|
|
18474
18536
|
if (!tool)
|
|
18475
18537
|
return void 0;
|
|
18476
|
-
const annotations = tool.annotations;
|
|
18477
18538
|
return {
|
|
18478
18539
|
inputSchema: tool.inputSchema,
|
|
18479
18540
|
outputSchema: tool.outputSchema,
|
|
18480
|
-
readOnly: annotations?.readOnlyHint,
|
|
18481
18541
|
execute: (args, sig) => entry.server.callTool(tool.name, args, sig)
|
|
18482
18542
|
};
|
|
18483
18543
|
}
|
|
@@ -19690,6 +19750,7 @@ function wrapToolWithHooks(tool, dispatcher, commonParams, now = Date.now) {
|
|
|
19690
19750
|
|
|
19691
19751
|
// ../linkque-agent-runtime/dist/esm/core/hook/noopHookExecutor.js
|
|
19692
19752
|
var NoopHookExecutor = class {
|
|
19753
|
+
name = "NoopHookExecutor";
|
|
19693
19754
|
execute(_resource, _context, _options) {
|
|
19694
19755
|
return Promise.resolve({
|
|
19695
19756
|
ok: true,
|
|
@@ -19808,6 +19869,7 @@ function buildLinkquegwEventBody(context) {
|
|
|
19808
19869
|
};
|
|
19809
19870
|
}
|
|
19810
19871
|
var LinkquegwEventHookExecutor = class {
|
|
19872
|
+
name = EHookExecutorName.LinkquegwEventHookExecutor;
|
|
19811
19873
|
baseUrl;
|
|
19812
19874
|
getAuthHeaders;
|
|
19813
19875
|
fetchImpl;
|
|
@@ -30194,10 +30256,10 @@ function coerceWithJsonSchema(value, schema) {
|
|
|
30194
30256
|
nextValue = coerceWithUnionSchema(nextValue, schema.oneOf);
|
|
30195
30257
|
}
|
|
30196
30258
|
const schemaTypes = getSchemaTypes(schema);
|
|
30197
|
-
const matchesUnionMember = schemaTypes.length > 1 && schemaTypes.some((
|
|
30259
|
+
const matchesUnionMember = schemaTypes.length > 1 && schemaTypes.some((schemaType2) => matchesJsonType(nextValue, schemaType2));
|
|
30198
30260
|
if (schemaTypes.length > 0 && !matchesUnionMember) {
|
|
30199
|
-
for (const
|
|
30200
|
-
const candidate = coercePrimitiveByType(nextValue,
|
|
30261
|
+
for (const schemaType2 of schemaTypes) {
|
|
30262
|
+
const candidate = coercePrimitiveByType(nextValue, schemaType2);
|
|
30201
30263
|
if (candidate !== nextValue) {
|
|
30202
30264
|
nextValue = candidate;
|
|
30203
30265
|
break;
|
|
@@ -52217,10 +52279,6 @@ ${currentTurn}`;
|
|
|
52217
52279
|
}
|
|
52218
52280
|
|
|
52219
52281
|
// ../linkque-agent-runtime/dist/esm/core/cardRenderMcpServer.js
|
|
52220
|
-
var FALLBACK_SOURCE_INPUT_SCHEMA = {
|
|
52221
|
-
type: "object",
|
|
52222
|
-
additionalProperties: true
|
|
52223
|
-
};
|
|
52224
52282
|
var CardRenderMcpServer = class {
|
|
52225
52283
|
resources;
|
|
52226
52284
|
registry;
|
|
@@ -52322,7 +52380,7 @@ Select this card first, then call its card_source tools and card_finish tool.`,
|
|
|
52322
52380
|
resourceId: resource.resourceId,
|
|
52323
52381
|
label: source.purpose,
|
|
52324
52382
|
description: `Use after selecting ${name}. ${source.purpose}. Choose all MCP arguments from the conversation and prior source results.`,
|
|
52325
|
-
inputSchema: discoveredHandle?.inputSchema
|
|
52383
|
+
inputSchema: normalizeMcpInputSchema(discoveredHandle?.inputSchema),
|
|
52326
52384
|
outputSchema: discoveredHandle?.outputSchema ?? source.outputSchema,
|
|
52327
52385
|
execute: async (args, signal) => {
|
|
52328
52386
|
if (!state2.selected || this.activeCardId !== resource.resourceId)
|
|
@@ -52333,12 +52391,21 @@ Select this card first, then call its card_source tools and card_finish tool.`,
|
|
|
52333
52391
|
const handle = discoveredHandle ?? await this.registry.resolve(source.mcpResourceId, source.toolName, signal);
|
|
52334
52392
|
if (!handle)
|
|
52335
52393
|
throw new Error(`MCP tool ${source.mcpResourceId}/${source.toolName} is unavailable`);
|
|
52336
|
-
if (handle.readOnly === false)
|
|
52337
|
-
throw new Error(`Card data source ${source.mcpResourceId}/${source.toolName} must be read-only`);
|
|
52338
52394
|
const result = await handle.execute(args, signal);
|
|
52339
52395
|
const structured = readStructuredContent(result);
|
|
52340
|
-
if (
|
|
52341
|
-
|
|
52396
|
+
if (structured === void 0) {
|
|
52397
|
+
const binding = config.bindings.find((candidate) => candidate.sourceId === source.sourceId);
|
|
52398
|
+
const field = config.fields.find((candidate) => candidate.fieldId === binding?.fieldId);
|
|
52399
|
+
throw new CardMappingError({
|
|
52400
|
+
code: "MCP_RESULT_UNSUPPORTED",
|
|
52401
|
+
cardId: resource.resourceId,
|
|
52402
|
+
fieldId: binding?.fieldId ?? "unknown",
|
|
52403
|
+
sourceId: source.sourceId,
|
|
52404
|
+
expectedType: field?.type ?? "json",
|
|
52405
|
+
actualType: "mixed-or-empty-content",
|
|
52406
|
+
retryable: false
|
|
52407
|
+
});
|
|
52408
|
+
}
|
|
52342
52409
|
state2.results.set(source.sourceId, structured);
|
|
52343
52410
|
return structured;
|
|
52344
52411
|
}
|
|
@@ -52563,6 +52630,92 @@ var NoopKnowledgeSearchPort = class {
|
|
|
52563
52630
|
}
|
|
52564
52631
|
};
|
|
52565
52632
|
|
|
52633
|
+
// ../linkque-agent-runtime/dist/esm/core/agentRuntimePlugin.js
|
|
52634
|
+
var validatePlugins = (plugins) => {
|
|
52635
|
+
const names = /* @__PURE__ */ new Set();
|
|
52636
|
+
for (const plugin of plugins) {
|
|
52637
|
+
const name = plugin.name.trim();
|
|
52638
|
+
if (!name) {
|
|
52639
|
+
throw new Error("Agent runtime \u63D2\u4EF6 name \u4E0D\u80FD\u4E3A\u7A7A");
|
|
52640
|
+
}
|
|
52641
|
+
if (names.has(name)) {
|
|
52642
|
+
throw new Error(`Agent runtime \u63D2\u4EF6 name \u91CD\u590D: ${name}`);
|
|
52643
|
+
}
|
|
52644
|
+
names.add(name);
|
|
52645
|
+
}
|
|
52646
|
+
return plugins;
|
|
52647
|
+
};
|
|
52648
|
+
function assertAgentConfigRoot(value, pluginName) {
|
|
52649
|
+
if (typeof value !== "object" || value === null || !("agent" in value)) {
|
|
52650
|
+
throw new Error(`Agent runtime \u63D2\u4EF6 ${pluginName} \u7684 modifyAgentConfig \u8FD4\u56DE\u4E86\u65E0\u6548\u914D\u7F6E`);
|
|
52651
|
+
}
|
|
52652
|
+
}
|
|
52653
|
+
var applyAgentRuntimePluginConfig = (agentConfig, plugins = []) => {
|
|
52654
|
+
const validatedPlugins = validatePlugins(plugins);
|
|
52655
|
+
const modifiers = validatedPlugins.filter((plugin) => plugin.modifyAgentConfig !== void 0);
|
|
52656
|
+
if (modifiers.length === 0)
|
|
52657
|
+
return agentConfig;
|
|
52658
|
+
let current = structuredClone(agentConfig);
|
|
52659
|
+
for (const plugin of modifiers) {
|
|
52660
|
+
try {
|
|
52661
|
+
const modified = plugin.modifyAgentConfig?.(current);
|
|
52662
|
+
if (modified !== void 0) {
|
|
52663
|
+
assertAgentConfigRoot(modified, plugin.name);
|
|
52664
|
+
current = modified;
|
|
52665
|
+
}
|
|
52666
|
+
current = structuredClone(current);
|
|
52667
|
+
} catch (error) {
|
|
52668
|
+
throw new Error(`Agent runtime \u63D2\u4EF6 ${plugin.name} \u4FEE\u6539 Agent Config \u5931\u8D25`, { cause: error });
|
|
52669
|
+
}
|
|
52670
|
+
}
|
|
52671
|
+
return current;
|
|
52672
|
+
};
|
|
52673
|
+
var MergedHookExecutorHandler = class {
|
|
52674
|
+
executorByName;
|
|
52675
|
+
constructor(executorByName) {
|
|
52676
|
+
this.executorByName = executorByName;
|
|
52677
|
+
}
|
|
52678
|
+
async execute(resource, context, options) {
|
|
52679
|
+
const executor = this.executorByName.get(resource.config.executorName);
|
|
52680
|
+
if (executor)
|
|
52681
|
+
return executor.execute(resource, context, options);
|
|
52682
|
+
return {
|
|
52683
|
+
ok: true,
|
|
52684
|
+
skipped: true,
|
|
52685
|
+
code: "PLUGIN_EXECUTOR_NOT_FOUND",
|
|
52686
|
+
message: `\u672A\u627E\u5230 name=${resource.config.executorName} \u7684 hook executor`
|
|
52687
|
+
};
|
|
52688
|
+
}
|
|
52689
|
+
};
|
|
52690
|
+
var resolveAgentRuntimeHookExecutor = (plugins = [], portHookExecutorList = [], debugLog) => {
|
|
52691
|
+
const entries = validatePlugins(plugins).flatMap((plugin) => (plugin.hookExecutorList ?? []).map((executor, index2) => ({
|
|
52692
|
+
executor,
|
|
52693
|
+
source: `plugin:${plugin.name}[${index2}]`
|
|
52694
|
+
})));
|
|
52695
|
+
entries.push(...portHookExecutorList.map((executor, index2) => ({
|
|
52696
|
+
executor,
|
|
52697
|
+
source: `ports.hookExecutorList[${index2}]`
|
|
52698
|
+
})));
|
|
52699
|
+
if (entries.length === 0)
|
|
52700
|
+
return void 0;
|
|
52701
|
+
const merged = /* @__PURE__ */ new Map();
|
|
52702
|
+
for (const entry of entries) {
|
|
52703
|
+
const name = entry.executor.name;
|
|
52704
|
+
if (!name.trim())
|
|
52705
|
+
throw new Error(`Hook executor name \u4E0D\u80FD\u4E3A\u7A7A: ${entry.source}`);
|
|
52706
|
+
const previous = merged.get(name);
|
|
52707
|
+
if (previous) {
|
|
52708
|
+
try {
|
|
52709
|
+
debugLog?.(`[hook-executor-merge] name=${name} \u51B2\u7A81: ${previous.source} \u88AB ${entry.source} \u8986\u76D6`, EDebugLogScope.HOOK);
|
|
52710
|
+
} catch {
|
|
52711
|
+
}
|
|
52712
|
+
}
|
|
52713
|
+
merged.set(name, entry);
|
|
52714
|
+
}
|
|
52715
|
+
const executorByName = new Map([...merged].map(([name, entry]) => [name, entry.executor]));
|
|
52716
|
+
return new MergedHookExecutorHandler(executorByName);
|
|
52717
|
+
};
|
|
52718
|
+
|
|
52566
52719
|
// ../linkque-agent-runtime/dist/esm/core/agentRuntime.js
|
|
52567
52720
|
var DEFAULT_HARNESS_PROMPT = `# Harness \u8FD0\u884C\u89C4\u7EA6
|
|
52568
52721
|
|
|
@@ -52625,13 +52778,14 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
52625
52778
|
* 本 constructor 供单测/noop 调试或需要完全自定义默认的场景。
|
|
52626
52779
|
*/
|
|
52627
52780
|
constructor(ports = {}) {
|
|
52781
|
+
const mergedHookExecutor = resolveAgentRuntimeHookExecutor(ports.plugins, ports.hookExecutorList, ports.debugLog);
|
|
52628
52782
|
this.agentLoop = ports.agentLoop ?? new PiAgentLoop(void 0, ports.linkqueBaseUrl);
|
|
52629
52783
|
this.followUpQuestionGenerator = ports.followUpQuestionGenerator ?? new PiFollowUpQuestionGenerator(ports.linkqueBaseUrl);
|
|
52630
52784
|
this.sessionManager = ports.sessionManager ?? new InMemorySessionManager();
|
|
52631
52785
|
this.skillLoader = ports.skillLoader ?? new NoopSkillLoader();
|
|
52632
52786
|
this.mcpServerProvider = ports.mcpServerProvider ?? new NoopMcpServerProvider();
|
|
52633
52787
|
this.knowledgeSearchPort = ports.knowledgeSearchPort ?? new NoopKnowledgeSearchPort();
|
|
52634
|
-
this.hookExecutor =
|
|
52788
|
+
this.hookExecutor = mergedHookExecutor ?? new NoopHookExecutor();
|
|
52635
52789
|
this.hookMetricsSink = ports.hookMetricsSink;
|
|
52636
52790
|
this.portsDebugLog = ports.debugLog;
|
|
52637
52791
|
}
|
|
@@ -52647,31 +52801,32 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
52647
52801
|
* @param ports 可选端口覆盖(任一缺省走默认适配器)
|
|
52648
52802
|
*/
|
|
52649
52803
|
static create(protocol, ports) {
|
|
52650
|
-
const model = protocol.agent.model;
|
|
52651
|
-
const skillResources = protocol.agent.resources.filter((r) => r.resourceType === EResourceType.SKILL);
|
|
52652
|
-
const mcpResources = protocol.agent.resources.filter((r) => r.resourceType === EResourceType.MCP);
|
|
52653
|
-
const mcpToolResources = protocol.agent.resources.filter((r) => r.resourceType === EResourceType.MCP_TOOL);
|
|
52654
|
-
const cardResources = protocol.agent.resources.filter((r) => r.resourceType === EResourceType.CARD);
|
|
52655
|
-
const knowledgeResources = protocol.agent.resources.filter((r) => r.resourceType === EResourceType.KNOWLEDGE);
|
|
52656
|
-
const followUpQuestionGenerationEnabled = protocol.agent.resources.filter((resource) => resource.resourceType === EResourceType.FOLLOW_UP_QUESTIONS).some((resource) => resource.config.enable === true);
|
|
52657
|
-
const mcpServerSpecs = aggregateMcpServers([...mcpResources, ...mcpToolResources], protocol.agentId);
|
|
52658
52804
|
const portsArg = ports ?? {};
|
|
52805
|
+
const agentConfig = applyAgentRuntimePluginConfig(protocol, portsArg.plugins);
|
|
52806
|
+
const model = agentConfig.agent.model;
|
|
52807
|
+
const skillResources = agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.SKILL);
|
|
52808
|
+
const mcpResources = agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.MCP);
|
|
52809
|
+
const mcpToolResources = agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.MCP_TOOL);
|
|
52810
|
+
const cardResources = agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.CARD);
|
|
52811
|
+
const knowledgeResources = agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.KNOWLEDGE);
|
|
52812
|
+
const followUpQuestionGenerationEnabled = agentConfig.agent.resources.filter((resource) => resource.resourceType === EResourceType.FOLLOW_UP_QUESTIONS).some((resource) => resource.config.enable === true);
|
|
52813
|
+
const mcpServerSpecs = aggregateMcpServers([...mcpResources, ...mcpToolResources], agentConfig.agentId);
|
|
52659
52814
|
const innerProvider = portsArg.mcpServerProvider ?? new NoopMcpServerProvider();
|
|
52660
52815
|
const rt = new _AgentRuntime({
|
|
52661
52816
|
...portsArg,
|
|
52662
52817
|
mcpServerProvider: new CardRenderMcpServerProvider(innerProvider)
|
|
52663
52818
|
});
|
|
52664
|
-
rt.defaultSystemPrompt =
|
|
52665
|
-
rt.defaultHarnessPrompt =
|
|
52819
|
+
rt.defaultSystemPrompt = agentConfig.agent.systemPrompt.content;
|
|
52820
|
+
rt.defaultHarnessPrompt = agentConfig.agent.harness ? agentConfig.agent.harness.systemPrompt : DEFAULT_HARNESS_PROMPT;
|
|
52666
52821
|
rt.defaultModel = model.defaultModel || void 0;
|
|
52667
52822
|
rt.defaultThinkingLevel = model.callParams?.thinkingLevel;
|
|
52668
52823
|
rt.skillResources = skillResources;
|
|
52669
52824
|
rt.mcpServerSpecs = mcpServerSpecs;
|
|
52670
52825
|
rt.cardResources = cardResources;
|
|
52671
52826
|
rt.knowledgeResources = knowledgeResources;
|
|
52672
|
-
rt.agentId =
|
|
52827
|
+
rt.agentId = agentConfig.agentId;
|
|
52673
52828
|
rt.followUpQuestionGenerationEnabled = followUpQuestionGenerationEnabled;
|
|
52674
|
-
rt.hookResources = normalizeHookResources(
|
|
52829
|
+
rt.hookResources = normalizeHookResources(agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.HOOK));
|
|
52675
52830
|
return rt;
|
|
52676
52831
|
}
|
|
52677
52832
|
async prepareFollowUpQuestionContext(sessionId, history = []) {
|
|
@@ -60279,6 +60434,9 @@ function setBakedProtocol(protocol) {
|
|
|
60279
60434
|
|
|
60280
60435
|
export {
|
|
60281
60436
|
EResourceType,
|
|
60437
|
+
EResourceProviderType,
|
|
60438
|
+
EHookStage,
|
|
60439
|
+
EHookExecutorName,
|
|
60282
60440
|
executeHomeData,
|
|
60283
60441
|
FOLLOW_UP_CONTEXT_MAX_HISTORY_RUNS,
|
|
60284
60442
|
LinkquegwEventHookExecutor,
|