linkque-cli-v2 1.0.7 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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 }) => schemaType ? (0, codegen_1.str)`"${keyword}" keyword must be ${schemaType} ($data)` : (0, codegen_1.str)`"${keyword}" keyword is invalid ($data)`
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, schemaType, allowUndefined = false) {
2048
- return !schemaType.length || schemaType.some((st) => st === "array" ? Array.isArray(schema) : st === "object" ? schema && typeof schema == "object" && !Array.isArray(schema) : typeof schema == st || allowUndefined && typeof schema == "undefined");
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 (schemaType.length || def.validateSchema) {
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 (schemaType.length) {
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(schemaType) ? schemaType : [schemaType];
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;
@@ -17027,6 +17030,7 @@ function analyzeA2UIBindings(protocol) {
17027
17030
  }
17028
17031
  }
17029
17032
  return {
17033
+ surfaceIds: [...surfaces],
17030
17034
  surfaceId: surfaces.size === 1 ? [...surfaces][0] : void 0,
17031
17035
  occurrences,
17032
17036
  issues
@@ -17978,7 +17982,7 @@ function optionalString(value, path2, issues) {
17978
17982
 
17979
17983
  // ../agent-a2ui-card-contract/dist/esm/resolver.js
17980
17984
  var A2UICardResolverError = class extends Error {
17981
- constructor(code, message, fieldId) {
17985
+ constructor(code, message, fieldId, expectedType, actualType) {
17982
17986
  super(message);
17983
17987
  Object.defineProperty(this, "code", {
17984
17988
  enumerable: true,
@@ -17992,9 +17996,23 @@ var A2UICardResolverError = class extends Error {
17992
17996
  writable: true,
17993
17997
  value: void 0
17994
17998
  });
17999
+ Object.defineProperty(this, "expectedType", {
18000
+ enumerable: true,
18001
+ configurable: true,
18002
+ writable: true,
18003
+ value: void 0
18004
+ });
18005
+ Object.defineProperty(this, "actualType", {
18006
+ enumerable: true,
18007
+ configurable: true,
18008
+ writable: true,
18009
+ value: void 0
18010
+ });
17995
18011
  this.name = "A2UICardResolverError";
17996
18012
  this.code = code;
17997
18013
  this.fieldId = fieldId;
18014
+ this.expectedType = expectedType;
18015
+ this.actualType = actualType;
17998
18016
  }
17999
18017
  };
18000
18018
  async function executeA2UICardResolver(input) {
@@ -18014,8 +18032,8 @@ async function executeA2UICardResolver(input) {
18014
18032
  if (!tool) {
18015
18033
  throw new A2UICardResolverError("MCP_TOOL_UNAVAILABLE", `MCP tool ${call.mcpResourceId}/${call.toolName} is unavailable`, fieldId);
18016
18034
  }
18017
- if (!tool.readOnly || !tool.outputSchema) {
18018
- throw new A2UICardResolverError("MCP_SCHEMA_UNSUPPORTED", `MCP tool ${call.mcpResourceId}/${call.toolName} is not a read-only structured tool`, fieldId);
18035
+ if (!tool.outputSchema) {
18036
+ throw new A2UICardResolverError("MCP_SCHEMA_UNSUPPORTED", `MCP tool ${call.mcpResourceId}/${call.toolName} has no output schema`, fieldId);
18019
18037
  }
18020
18038
  const args = {};
18021
18039
  for (const binding of call.inputBindings) {
@@ -18042,7 +18060,7 @@ async function executeA2UICardResolver(input) {
18042
18060
  for (const binding of input.resolver.outputBindings) {
18043
18061
  const field = fieldById.get(binding.fieldId);
18044
18062
  const result = results.get(binding.callId);
18045
- if (!field || !result) {
18063
+ if (!field || result === void 0) {
18046
18064
  throw new A2UICardResolverError("CARD_BINDING_INVALID", `Output binding ${binding.fieldId} is invalid`, binding.fieldId);
18047
18065
  }
18048
18066
  let value;
@@ -18078,7 +18096,7 @@ async function executeA2UICardResolver(input) {
18078
18096
  }
18079
18097
  const value = readJsonPointer(viewModel, field.path);
18080
18098
  if (field.required && value === void 0) {
18081
- throw new A2UICardResolverError("CARD_REQUIRED_FIELD_MISSING", `Required card field ${field.fieldId} is missing`, field.fieldId);
18099
+ throw new A2UICardResolverError("CARD_REQUIRED_FIELD_MISSING", `Required card field ${field.fieldId} is missing`, field.fieldId, field.type, "missing");
18082
18100
  }
18083
18101
  if (value !== void 0) {
18084
18102
  assertSchemaValue(field.valueSchema, value, "CARD_MAPPING_SCHEMA_MISMATCH", `card field ${field.fieldId}`, field.fieldId);
@@ -18118,8 +18136,8 @@ function normalizeOptionalNulls(value, schema, required) {
18118
18136
  }
18119
18137
  async function executeTool(tool, args, signal, fieldId) {
18120
18138
  const response = await tool.call(args, signal);
18121
- const structured = cloneJsonObject(response.structuredContent);
18122
- if (!structured) {
18139
+ const structured = cloneJsonValue(response.structuredContent);
18140
+ if (structured === void 0) {
18123
18141
  throw new A2UICardResolverError("MCP_STRUCTURED_CONTENT_REQUIRED", `MCP tool ${tool.resourceId}/${tool.toolName} did not return structuredContent`, fieldId);
18124
18142
  }
18125
18143
  return structured;
@@ -18133,9 +18151,19 @@ function toolKey(resourceId, toolName) {
18133
18151
  function assertSchemaValue(schema, value, code, label, fieldId) {
18134
18152
  const issues = validateJsonSchemaValue2(schema, value);
18135
18153
  if (issues.length > 0) {
18136
- throw new A2UICardResolverError(code, `${label} does not match schema at ${issues[0].path}: ${issues[0].message}`, fieldId);
18154
+ throw new A2UICardResolverError(code, `${label} does not match schema at ${issues[0].path}: ${issues[0].message}`, fieldId, schemaType(schema), valueType2(value));
18137
18155
  }
18138
18156
  }
18157
+ function schemaType(schema) {
18158
+ return typeof schema.type === "string" ? schema.type : "unknown";
18159
+ }
18160
+ function valueType2(value) {
18161
+ if (value === null)
18162
+ return "null";
18163
+ if (Array.isArray(value))
18164
+ return "array";
18165
+ return typeof value === "object" ? "object" : typeof value;
18166
+ }
18139
18167
 
18140
18168
  // ../linkque-agent-runtime/dist/esm/core/mcpNaming.js
18141
18169
  import { createHash } from "node:crypto";
@@ -18172,7 +18200,7 @@ async function executeCardPresentation(resource, registry, runtimeContext, args,
18172
18200
  if (!handle) {
18173
18201
  throw new Error(`MCP tool ${call.mcpResourceId}/${call.toolName} is unavailable`);
18174
18202
  }
18175
- const inputSchema = isJsonObject(handle.inputSchema) ? handle.inputSchema : FALLBACK_OBJECT_SCHEMA;
18203
+ const inputSchema = normalizeMcpInputSchema(handle.inputSchema);
18176
18204
  return {
18177
18205
  resourceId: call.mcpResourceId,
18178
18206
  toolName: call.toolName,
@@ -18182,9 +18210,6 @@ async function executeCardPresentation(resource, registry, runtimeContext, args,
18182
18210
  // ViewModel Schema 校验。
18183
18211
  inputSchema,
18184
18212
  outputSchema: isJsonObject(handle.outputSchema) ? handle.outputSchema : FALLBACK_OBJECT_SCHEMA,
18185
- // 未声明 readOnlyHint 是旧 MCP 的常见情况;只拒绝明确声明
18186
- // readOnlyHint=false 的工具。
18187
- readOnly: handle.readOnly !== false,
18188
18213
  call: async (input, callSignal) => {
18189
18214
  const result = await handle.execute(supplementMcpInput(input, invocation, config.presentationInputSchema, inputSchema), callSignal);
18190
18215
  return { structuredContent: readStructuredContent(result) };
@@ -18233,29 +18258,46 @@ async function executeCardPresentationFromSources(resource, runtimeContext, sour
18233
18258
  transform: binding.transform
18234
18259
  }))
18235
18260
  };
18236
- const viewModel = await executeA2UICardResolver({
18237
- resolver,
18238
- fields: config.fields,
18239
- presentationInputSchema: {
18240
- type: "object",
18241
- properties: {},
18242
- additionalProperties: false
18243
- },
18244
- argsSchema: config.a2uiTemplate.argsSchema,
18245
- invocation: {},
18246
- runtimeContext,
18247
- tools: config.dataSources.filter((source) => sourceResults.has(source.sourceId)).map((source) => ({
18248
- resourceId: source.mcpResourceId,
18249
- toolName: source.toolName,
18250
- inputSchema: FALLBACK_OBJECT_SCHEMA,
18251
- outputSchema: source.outputSchema ?? FALLBACK_OBJECT_SCHEMA,
18252
- readOnly: true,
18253
- call: async () => ({
18254
- structuredContent: sourceResults.get(source.sourceId)
18255
- })
18256
- })),
18257
- signal
18258
- });
18261
+ let viewModel;
18262
+ try {
18263
+ viewModel = await executeA2UICardResolver({
18264
+ resolver,
18265
+ fields: config.fields,
18266
+ presentationInputSchema: {
18267
+ type: "object",
18268
+ properties: {},
18269
+ additionalProperties: false
18270
+ },
18271
+ argsSchema: config.a2uiTemplate.argsSchema,
18272
+ invocation: {},
18273
+ runtimeContext,
18274
+ tools: config.dataSources.filter((source) => sourceResults.has(source.sourceId)).map((source) => ({
18275
+ resourceId: source.mcpResourceId,
18276
+ toolName: source.toolName,
18277
+ inputSchema: FALLBACK_OBJECT_SCHEMA,
18278
+ outputSchema: source.outputSchema ?? FALLBACK_OBJECT_SCHEMA,
18279
+ call: async () => ({
18280
+ structuredContent: sourceResults.get(source.sourceId)
18281
+ })
18282
+ })),
18283
+ signal
18284
+ });
18285
+ } catch (error) {
18286
+ if (error instanceof A2UICardResolverError) {
18287
+ const binding = config.bindings.find((candidate) => candidate.fieldId === error.fieldId);
18288
+ const field = config.fields.find((candidate) => candidate.fieldId === error.fieldId);
18289
+ throw new CardMappingError({
18290
+ code: error.code,
18291
+ cardId: resource.resourceId,
18292
+ fieldId: error.fieldId ?? "unknown",
18293
+ sourceId: binding?.sourceId ?? "unknown",
18294
+ expectedType: error.expectedType ?? field?.type ?? "unknown",
18295
+ actualType: error.actualType ?? "unknown",
18296
+ retryable: false
18297
+ });
18298
+ }
18299
+ throw error;
18300
+ }
18259
18301
  return createPresentationResult(resource, config, viewModel);
18260
18302
  }
18261
18303
  function createPresentationResult(resource, config, viewModel) {
@@ -18290,25 +18332,46 @@ function isAgentPresentationToolResult(value) {
18290
18332
  }
18291
18333
  function injectResolvedViewModel(protocol, viewModel) {
18292
18334
  const analysis = analyzeA2UIBindings(protocol);
18293
- if (analysis.issues.length || !analysis.surfaceId) {
18294
- throw new Error("CARD template does not contain one valid A2UI surface");
18335
+ const declaredSurfaceIds = analysis.surfaceIds;
18336
+ const surfaceIds = Array.isArray(declaredSurfaceIds) && declaredSurfaceIds.every((surfaceId) => typeof surfaceId === "string") ? declaredSurfaceIds : collectA2UISurfaceIdsForLegacyContract(protocol);
18337
+ if (analysis.issues.length || surfaceIds.length === 0) {
18338
+ throw new Error("CARD template does not contain a valid A2UI surface");
18295
18339
  }
18296
18340
  return [
18297
18341
  ...protocol,
18298
18342
  {
18299
18343
  version: "0.9",
18300
- datas: [
18301
- {
18302
- updateDataModel: {
18303
- surfaceId: analysis.surfaceId,
18304
- path: "/",
18305
- value: viewModel
18306
- }
18344
+ datas: surfaceIds.map((surfaceId) => ({
18345
+ updateDataModel: {
18346
+ surfaceId,
18347
+ path: "/",
18348
+ value: viewModel
18307
18349
  }
18308
- ]
18350
+ }))
18309
18351
  }
18310
18352
  ];
18311
18353
  }
18354
+ function collectA2UISurfaceIdsForLegacyContract(protocol) {
18355
+ const surfaceIds = /* @__PURE__ */ new Set();
18356
+ for (const message of protocol) {
18357
+ if (!isJsonObject(message) || !Array.isArray(message.datas))
18358
+ continue;
18359
+ for (const instruction of message.datas) {
18360
+ if (!isJsonObject(instruction))
18361
+ continue;
18362
+ const operations = [
18363
+ "createSurface" in instruction ? instruction.createSurface : void 0,
18364
+ "updateComponents" in instruction ? instruction.updateComponents : void 0
18365
+ ];
18366
+ for (const operation of operations) {
18367
+ if (isJsonObject(operation) && typeof operation.surfaceId === "string") {
18368
+ surfaceIds.add(operation.surfaceId);
18369
+ }
18370
+ }
18371
+ }
18372
+ }
18373
+ return [...surfaceIds];
18374
+ }
18312
18375
  function createPresentationDescription(config) {
18313
18376
  return [
18314
18377
  config.description,
@@ -18349,23 +18412,44 @@ function compatibleSchemaTypes(source, target) {
18349
18412
  function readStructuredContent(result) {
18350
18413
  if (!isJsonObject(result))
18351
18414
  return void 0;
18352
- if (isJsonObject(result.structuredContent)) {
18353
- return JSON.parse(JSON.stringify(result.structuredContent));
18415
+ if (Object.hasOwn(result, "structuredContent") && isJsonValue(result.structuredContent)) {
18416
+ return cloneJsonValue(result.structuredContent);
18354
18417
  }
18355
- if (!Array.isArray(result.content) || result.content.length !== 1) {
18418
+ if (!Array.isArray(result.content) || result.content.length === 0) {
18356
18419
  return void 0;
18357
18420
  }
18358
- const [content] = result.content;
18359
- if (!isJsonObject(content) || content.type !== "text" || typeof content.text !== "string") {
18360
- return void 0;
18421
+ const texts = [];
18422
+ for (const content of result.content) {
18423
+ if (!isJsonObject(content) || content.type !== "text" || typeof content.text !== "string")
18424
+ return void 0;
18425
+ texts.push(content.text);
18361
18426
  }
18427
+ if (texts.length > 1)
18428
+ return texts.join("\n");
18362
18429
  try {
18363
- const parsed = JSON.parse(content.text);
18364
- return isJsonObject(parsed) ? JSON.parse(JSON.stringify(parsed)) : void 0;
18430
+ const parsed = JSON.parse(texts[0]);
18431
+ return isJsonValue(parsed) ? cloneJsonValue(parsed) : texts[0];
18365
18432
  } catch {
18366
- return void 0;
18433
+ return texts[0];
18434
+ }
18435
+ }
18436
+ function normalizeMcpInputSchema(value) {
18437
+ if (!isJsonObject(value) || getJsonSchemaIssues2(value).length > 0) {
18438
+ return { ...FALLBACK_OBJECT_SCHEMA };
18367
18439
  }
18440
+ if (value.type === "object" && (!isJsonObject(value.properties) || Object.keys(value.properties).length === 0))
18441
+ return { ...FALLBACK_OBJECT_SCHEMA };
18442
+ return JSON.parse(JSON.stringify(value));
18368
18443
  }
18444
+ var CardMappingError = class extends Error {
18445
+ details;
18446
+ retryable = false;
18447
+ constructor(details) {
18448
+ super(JSON.stringify(details));
18449
+ this.name = "CardMappingError";
18450
+ this.details = details;
18451
+ }
18452
+ };
18369
18453
  function isJsonObject(value) {
18370
18454
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
18371
18455
  }
@@ -18473,11 +18557,9 @@ var McpProxyTool = class {
18473
18557
  const tool = entry.tools.find((t) => t.name === toolName);
18474
18558
  if (!tool)
18475
18559
  return void 0;
18476
- const annotations = tool.annotations;
18477
18560
  return {
18478
18561
  inputSchema: tool.inputSchema,
18479
18562
  outputSchema: tool.outputSchema,
18480
- readOnly: annotations?.readOnlyHint,
18481
18563
  execute: (args, sig) => entry.server.callTool(tool.name, args, sig)
18482
18564
  };
18483
18565
  }
@@ -19690,6 +19772,7 @@ function wrapToolWithHooks(tool, dispatcher, commonParams, now = Date.now) {
19690
19772
 
19691
19773
  // ../linkque-agent-runtime/dist/esm/core/hook/noopHookExecutor.js
19692
19774
  var NoopHookExecutor = class {
19775
+ name = "NoopHookExecutor";
19693
19776
  execute(_resource, _context, _options) {
19694
19777
  return Promise.resolve({
19695
19778
  ok: true,
@@ -19808,6 +19891,7 @@ function buildLinkquegwEventBody(context) {
19808
19891
  };
19809
19892
  }
19810
19893
  var LinkquegwEventHookExecutor = class {
19894
+ name = EHookExecutorName.LinkquegwEventHookExecutor;
19811
19895
  baseUrl;
19812
19896
  getAuthHeaders;
19813
19897
  fetchImpl;
@@ -30194,10 +30278,10 @@ function coerceWithJsonSchema(value, schema) {
30194
30278
  nextValue = coerceWithUnionSchema(nextValue, schema.oneOf);
30195
30279
  }
30196
30280
  const schemaTypes = getSchemaTypes(schema);
30197
- const matchesUnionMember = schemaTypes.length > 1 && schemaTypes.some((schemaType) => matchesJsonType(nextValue, schemaType));
30281
+ const matchesUnionMember = schemaTypes.length > 1 && schemaTypes.some((schemaType2) => matchesJsonType(nextValue, schemaType2));
30198
30282
  if (schemaTypes.length > 0 && !matchesUnionMember) {
30199
- for (const schemaType of schemaTypes) {
30200
- const candidate = coercePrimitiveByType(nextValue, schemaType);
30283
+ for (const schemaType2 of schemaTypes) {
30284
+ const candidate = coercePrimitiveByType(nextValue, schemaType2);
30201
30285
  if (candidate !== nextValue) {
30202
30286
  nextValue = candidate;
30203
30287
  break;
@@ -52217,10 +52301,6 @@ ${currentTurn}`;
52217
52301
  }
52218
52302
 
52219
52303
  // ../linkque-agent-runtime/dist/esm/core/cardRenderMcpServer.js
52220
- var FALLBACK_SOURCE_INPUT_SCHEMA = {
52221
- type: "object",
52222
- additionalProperties: true
52223
- };
52224
52304
  var CardRenderMcpServer = class {
52225
52305
  resources;
52226
52306
  registry;
@@ -52322,7 +52402,7 @@ Select this card first, then call its card_source tools and card_finish tool.`,
52322
52402
  resourceId: resource.resourceId,
52323
52403
  label: source.purpose,
52324
52404
  description: `Use after selecting ${name}. ${source.purpose}. Choose all MCP arguments from the conversation and prior source results.`,
52325
- inputSchema: discoveredHandle?.inputSchema ?? FALLBACK_SOURCE_INPUT_SCHEMA,
52405
+ inputSchema: normalizeMcpInputSchema(discoveredHandle?.inputSchema),
52326
52406
  outputSchema: discoveredHandle?.outputSchema ?? source.outputSchema,
52327
52407
  execute: async (args, signal) => {
52328
52408
  if (!state2.selected || this.activeCardId !== resource.resourceId)
@@ -52333,12 +52413,21 @@ Select this card first, then call its card_source tools and card_finish tool.`,
52333
52413
  const handle = discoveredHandle ?? await this.registry.resolve(source.mcpResourceId, source.toolName, signal);
52334
52414
  if (!handle)
52335
52415
  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
52416
  const result = await handle.execute(args, signal);
52339
52417
  const structured = readStructuredContent(result);
52340
- if (!structured)
52341
- throw new Error(`MCP tool ${source.mcpResourceId}/${source.toolName} did not return structured content`);
52418
+ if (structured === void 0) {
52419
+ const binding = config.bindings.find((candidate) => candidate.sourceId === source.sourceId);
52420
+ const field = config.fields.find((candidate) => candidate.fieldId === binding?.fieldId);
52421
+ throw new CardMappingError({
52422
+ code: "MCP_RESULT_UNSUPPORTED",
52423
+ cardId: resource.resourceId,
52424
+ fieldId: binding?.fieldId ?? "unknown",
52425
+ sourceId: source.sourceId,
52426
+ expectedType: field?.type ?? "json",
52427
+ actualType: "mixed-or-empty-content",
52428
+ retryable: false
52429
+ });
52430
+ }
52342
52431
  state2.results.set(source.sourceId, structured);
52343
52432
  return structured;
52344
52433
  }
@@ -52563,6 +52652,92 @@ var NoopKnowledgeSearchPort = class {
52563
52652
  }
52564
52653
  };
52565
52654
 
52655
+ // ../linkque-agent-runtime/dist/esm/core/agentRuntimePlugin.js
52656
+ var validatePlugins = (plugins) => {
52657
+ const names = /* @__PURE__ */ new Set();
52658
+ for (const plugin of plugins) {
52659
+ const name = plugin.name.trim();
52660
+ if (!name) {
52661
+ throw new Error("Agent runtime \u63D2\u4EF6 name \u4E0D\u80FD\u4E3A\u7A7A");
52662
+ }
52663
+ if (names.has(name)) {
52664
+ throw new Error(`Agent runtime \u63D2\u4EF6 name \u91CD\u590D: ${name}`);
52665
+ }
52666
+ names.add(name);
52667
+ }
52668
+ return plugins;
52669
+ };
52670
+ function assertAgentConfigRoot(value, pluginName) {
52671
+ if (typeof value !== "object" || value === null || !("agent" in value)) {
52672
+ throw new Error(`Agent runtime \u63D2\u4EF6 ${pluginName} \u7684 modifyAgentConfig \u8FD4\u56DE\u4E86\u65E0\u6548\u914D\u7F6E`);
52673
+ }
52674
+ }
52675
+ var applyAgentRuntimePluginConfig = (agentConfig, plugins = []) => {
52676
+ const validatedPlugins = validatePlugins(plugins);
52677
+ const modifiers = validatedPlugins.filter((plugin) => plugin.modifyAgentConfig !== void 0);
52678
+ if (modifiers.length === 0)
52679
+ return agentConfig;
52680
+ let current = structuredClone(agentConfig);
52681
+ for (const plugin of modifiers) {
52682
+ try {
52683
+ const modified = plugin.modifyAgentConfig?.(current);
52684
+ if (modified !== void 0) {
52685
+ assertAgentConfigRoot(modified, plugin.name);
52686
+ current = modified;
52687
+ }
52688
+ current = structuredClone(current);
52689
+ } catch (error) {
52690
+ throw new Error(`Agent runtime \u63D2\u4EF6 ${plugin.name} \u4FEE\u6539 Agent Config \u5931\u8D25`, { cause: error });
52691
+ }
52692
+ }
52693
+ return current;
52694
+ };
52695
+ var MergedHookExecutorHandler = class {
52696
+ executorByName;
52697
+ constructor(executorByName) {
52698
+ this.executorByName = executorByName;
52699
+ }
52700
+ async execute(resource, context, options) {
52701
+ const executor = this.executorByName.get(resource.config.executorName);
52702
+ if (executor)
52703
+ return executor.execute(resource, context, options);
52704
+ return {
52705
+ ok: true,
52706
+ skipped: true,
52707
+ code: "PLUGIN_EXECUTOR_NOT_FOUND",
52708
+ message: `\u672A\u627E\u5230 name=${resource.config.executorName} \u7684 hook executor`
52709
+ };
52710
+ }
52711
+ };
52712
+ var resolveAgentRuntimeHookExecutor = (plugins = [], portHookExecutorList = [], debugLog) => {
52713
+ const entries = validatePlugins(plugins).flatMap((plugin) => (plugin.hookExecutorList ?? []).map((executor, index2) => ({
52714
+ executor,
52715
+ source: `plugin:${plugin.name}[${index2}]`
52716
+ })));
52717
+ entries.push(...portHookExecutorList.map((executor, index2) => ({
52718
+ executor,
52719
+ source: `ports.hookExecutorList[${index2}]`
52720
+ })));
52721
+ if (entries.length === 0)
52722
+ return void 0;
52723
+ const merged = /* @__PURE__ */ new Map();
52724
+ for (const entry of entries) {
52725
+ const name = entry.executor.name;
52726
+ if (!name.trim())
52727
+ throw new Error(`Hook executor name \u4E0D\u80FD\u4E3A\u7A7A: ${entry.source}`);
52728
+ const previous = merged.get(name);
52729
+ if (previous) {
52730
+ try {
52731
+ debugLog?.(`[hook-executor-merge] name=${name} \u51B2\u7A81: ${previous.source} \u88AB ${entry.source} \u8986\u76D6`, EDebugLogScope.HOOK);
52732
+ } catch {
52733
+ }
52734
+ }
52735
+ merged.set(name, entry);
52736
+ }
52737
+ const executorByName = new Map([...merged].map(([name, entry]) => [name, entry.executor]));
52738
+ return new MergedHookExecutorHandler(executorByName);
52739
+ };
52740
+
52566
52741
  // ../linkque-agent-runtime/dist/esm/core/agentRuntime.js
52567
52742
  var DEFAULT_HARNESS_PROMPT = `# Harness \u8FD0\u884C\u89C4\u7EA6
52568
52743
 
@@ -52625,13 +52800,14 @@ var AgentRuntime = class _AgentRuntime {
52625
52800
  * 本 constructor 供单测/noop 调试或需要完全自定义默认的场景。
52626
52801
  */
52627
52802
  constructor(ports = {}) {
52803
+ const mergedHookExecutor = resolveAgentRuntimeHookExecutor(ports.plugins, ports.hookExecutorList, ports.debugLog);
52628
52804
  this.agentLoop = ports.agentLoop ?? new PiAgentLoop(void 0, ports.linkqueBaseUrl);
52629
52805
  this.followUpQuestionGenerator = ports.followUpQuestionGenerator ?? new PiFollowUpQuestionGenerator(ports.linkqueBaseUrl);
52630
52806
  this.sessionManager = ports.sessionManager ?? new InMemorySessionManager();
52631
52807
  this.skillLoader = ports.skillLoader ?? new NoopSkillLoader();
52632
52808
  this.mcpServerProvider = ports.mcpServerProvider ?? new NoopMcpServerProvider();
52633
52809
  this.knowledgeSearchPort = ports.knowledgeSearchPort ?? new NoopKnowledgeSearchPort();
52634
- this.hookExecutor = ports.hookExecutor ?? new NoopHookExecutor();
52810
+ this.hookExecutor = mergedHookExecutor ?? new NoopHookExecutor();
52635
52811
  this.hookMetricsSink = ports.hookMetricsSink;
52636
52812
  this.portsDebugLog = ports.debugLog;
52637
52813
  }
@@ -52647,31 +52823,32 @@ var AgentRuntime = class _AgentRuntime {
52647
52823
  * @param ports 可选端口覆盖(任一缺省走默认适配器)
52648
52824
  */
52649
52825
  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
52826
  const portsArg = ports ?? {};
52827
+ const agentConfig = applyAgentRuntimePluginConfig(protocol, portsArg.plugins);
52828
+ const model = agentConfig.agent.model;
52829
+ const skillResources = agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.SKILL);
52830
+ const mcpResources = agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.MCP);
52831
+ const mcpToolResources = agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.MCP_TOOL);
52832
+ const cardResources = agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.CARD);
52833
+ const knowledgeResources = agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.KNOWLEDGE);
52834
+ const followUpQuestionGenerationEnabled = agentConfig.agent.resources.filter((resource) => resource.resourceType === EResourceType.FOLLOW_UP_QUESTIONS).some((resource) => resource.config.enable === true);
52835
+ const mcpServerSpecs = aggregateMcpServers([...mcpResources, ...mcpToolResources], agentConfig.agentId);
52659
52836
  const innerProvider = portsArg.mcpServerProvider ?? new NoopMcpServerProvider();
52660
52837
  const rt = new _AgentRuntime({
52661
52838
  ...portsArg,
52662
52839
  mcpServerProvider: new CardRenderMcpServerProvider(innerProvider)
52663
52840
  });
52664
- rt.defaultSystemPrompt = protocol.agent.systemPrompt.content;
52665
- rt.defaultHarnessPrompt = protocol.agent.harness ? protocol.agent.harness.systemPrompt : DEFAULT_HARNESS_PROMPT;
52841
+ rt.defaultSystemPrompt = agentConfig.agent.systemPrompt.content;
52842
+ rt.defaultHarnessPrompt = agentConfig.agent.harness ? agentConfig.agent.harness.systemPrompt : DEFAULT_HARNESS_PROMPT;
52666
52843
  rt.defaultModel = model.defaultModel || void 0;
52667
52844
  rt.defaultThinkingLevel = model.callParams?.thinkingLevel;
52668
52845
  rt.skillResources = skillResources;
52669
52846
  rt.mcpServerSpecs = mcpServerSpecs;
52670
52847
  rt.cardResources = cardResources;
52671
52848
  rt.knowledgeResources = knowledgeResources;
52672
- rt.agentId = protocol.agentId;
52849
+ rt.agentId = agentConfig.agentId;
52673
52850
  rt.followUpQuestionGenerationEnabled = followUpQuestionGenerationEnabled;
52674
- rt.hookResources = normalizeHookResources(protocol.agent.resources.filter((r) => r.resourceType === EResourceType.HOOK));
52851
+ rt.hookResources = normalizeHookResources(agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.HOOK));
52675
52852
  return rt;
52676
52853
  }
52677
52854
  async prepareFollowUpQuestionContext(sessionId, history = []) {
@@ -60279,6 +60456,9 @@ function setBakedProtocol(protocol) {
60279
60456
 
60280
60457
  export {
60281
60458
  EResourceType,
60459
+ EResourceProviderType,
60460
+ EHookStage,
60461
+ EHookExecutorName,
60282
60462
  executeHomeData,
60283
60463
  FOLLOW_UP_CONTEXT_MAX_HISTORY_RUNS,
60284
60464
  LinkquegwEventHookExecutor,