linkque-cli-v2 1.0.6 → 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.
@@ -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;
@@ -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.readOnly || !tool.outputSchema) {
18018
- throw new A2UICardResolverError("MCP_SCHEMA_UNSUPPORTED", `MCP tool ${call.mcpResourceId}/${call.toolName} is not a read-only structured tool`, fieldId);
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 || !result) {
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 = cloneJsonObject(response.structuredContent);
18122
- if (!structured) {
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 = isJsonObject(handle.inputSchema) ? handle.inputSchema : FALLBACK_OBJECT_SCHEMA;
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
- 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
- });
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 (isJsonObject(result.structuredContent)) {
18353
- return JSON.parse(JSON.stringify(result.structuredContent));
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 !== 1) {
18396
+ if (!Array.isArray(result.content) || result.content.length === 0) {
18356
18397
  return void 0;
18357
18398
  }
18358
- const [content] = result.content;
18359
- if (!isJsonObject(content) || content.type !== "text" || typeof content.text !== "string") {
18360
- return void 0;
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(content.text);
18364
- return isJsonObject(parsed) ? JSON.parse(JSON.stringify(parsed)) : void 0;
18408
+ const parsed = JSON.parse(texts[0]);
18409
+ return isJsonValue(parsed) ? cloneJsonValue(parsed) : texts[0];
18365
18410
  } catch {
18366
- return void 0;
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,
@@ -19798,7 +19859,6 @@ function buildLinkquegwEventBody(context) {
19798
19859
  eventType,
19799
19860
  eventId: context.eventId,
19800
19861
  eventTime: context.timestamp,
19801
- ...commonParams.userId !== void 0 && { userId: commonParams.userId },
19802
19862
  conversationId: commonParams.conversationId,
19803
19863
  ...commonParams.sessionId !== void 0 && {
19804
19864
  sessionId: commonParams.sessionId
@@ -19809,6 +19869,7 @@ function buildLinkquegwEventBody(context) {
19809
19869
  };
19810
19870
  }
19811
19871
  var LinkquegwEventHookExecutor = class {
19872
+ name = EHookExecutorName.LinkquegwEventHookExecutor;
19812
19873
  baseUrl;
19813
19874
  getAuthHeaders;
19814
19875
  fetchImpl;
@@ -30195,10 +30256,10 @@ function coerceWithJsonSchema(value, schema) {
30195
30256
  nextValue = coerceWithUnionSchema(nextValue, schema.oneOf);
30196
30257
  }
30197
30258
  const schemaTypes = getSchemaTypes(schema);
30198
- const matchesUnionMember = schemaTypes.length > 1 && schemaTypes.some((schemaType) => matchesJsonType(nextValue, schemaType));
30259
+ const matchesUnionMember = schemaTypes.length > 1 && schemaTypes.some((schemaType2) => matchesJsonType(nextValue, schemaType2));
30199
30260
  if (schemaTypes.length > 0 && !matchesUnionMember) {
30200
- for (const schemaType of schemaTypes) {
30201
- const candidate = coercePrimitiveByType(nextValue, schemaType);
30261
+ for (const schemaType2 of schemaTypes) {
30262
+ const candidate = coercePrimitiveByType(nextValue, schemaType2);
30202
30263
  if (candidate !== nextValue) {
30203
30264
  nextValue = candidate;
30204
30265
  break;
@@ -52218,10 +52279,6 @@ ${currentTurn}`;
52218
52279
  }
52219
52280
 
52220
52281
  // ../linkque-agent-runtime/dist/esm/core/cardRenderMcpServer.js
52221
- var FALLBACK_SOURCE_INPUT_SCHEMA = {
52222
- type: "object",
52223
- additionalProperties: true
52224
- };
52225
52282
  var CardRenderMcpServer = class {
52226
52283
  resources;
52227
52284
  registry;
@@ -52323,7 +52380,7 @@ Select this card first, then call its card_source tools and card_finish tool.`,
52323
52380
  resourceId: resource.resourceId,
52324
52381
  label: source.purpose,
52325
52382
  description: `Use after selecting ${name}. ${source.purpose}. Choose all MCP arguments from the conversation and prior source results.`,
52326
- inputSchema: discoveredHandle?.inputSchema ?? FALLBACK_SOURCE_INPUT_SCHEMA,
52383
+ inputSchema: normalizeMcpInputSchema(discoveredHandle?.inputSchema),
52327
52384
  outputSchema: discoveredHandle?.outputSchema ?? source.outputSchema,
52328
52385
  execute: async (args, signal) => {
52329
52386
  if (!state2.selected || this.activeCardId !== resource.resourceId)
@@ -52334,12 +52391,21 @@ Select this card first, then call its card_source tools and card_finish tool.`,
52334
52391
  const handle = discoveredHandle ?? await this.registry.resolve(source.mcpResourceId, source.toolName, signal);
52335
52392
  if (!handle)
52336
52393
  throw new Error(`MCP tool ${source.mcpResourceId}/${source.toolName} is unavailable`);
52337
- if (handle.readOnly === false)
52338
- throw new Error(`Card data source ${source.mcpResourceId}/${source.toolName} must be read-only`);
52339
52394
  const result = await handle.execute(args, signal);
52340
52395
  const structured = readStructuredContent(result);
52341
- if (!structured)
52342
- throw new Error(`MCP tool ${source.mcpResourceId}/${source.toolName} did not return structured content`);
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
+ }
52343
52409
  state2.results.set(source.sourceId, structured);
52344
52410
  return structured;
52345
52411
  }
@@ -52564,6 +52630,92 @@ var NoopKnowledgeSearchPort = class {
52564
52630
  }
52565
52631
  };
52566
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
+
52567
52719
  // ../linkque-agent-runtime/dist/esm/core/agentRuntime.js
52568
52720
  var DEFAULT_HARNESS_PROMPT = `# Harness \u8FD0\u884C\u89C4\u7EA6
52569
52721
 
@@ -52626,13 +52778,14 @@ var AgentRuntime = class _AgentRuntime {
52626
52778
  * 本 constructor 供单测/noop 调试或需要完全自定义默认的场景。
52627
52779
  */
52628
52780
  constructor(ports = {}) {
52781
+ const mergedHookExecutor = resolveAgentRuntimeHookExecutor(ports.plugins, ports.hookExecutorList, ports.debugLog);
52629
52782
  this.agentLoop = ports.agentLoop ?? new PiAgentLoop(void 0, ports.linkqueBaseUrl);
52630
52783
  this.followUpQuestionGenerator = ports.followUpQuestionGenerator ?? new PiFollowUpQuestionGenerator(ports.linkqueBaseUrl);
52631
52784
  this.sessionManager = ports.sessionManager ?? new InMemorySessionManager();
52632
52785
  this.skillLoader = ports.skillLoader ?? new NoopSkillLoader();
52633
52786
  this.mcpServerProvider = ports.mcpServerProvider ?? new NoopMcpServerProvider();
52634
52787
  this.knowledgeSearchPort = ports.knowledgeSearchPort ?? new NoopKnowledgeSearchPort();
52635
- this.hookExecutor = ports.hookExecutor ?? new NoopHookExecutor();
52788
+ this.hookExecutor = mergedHookExecutor ?? new NoopHookExecutor();
52636
52789
  this.hookMetricsSink = ports.hookMetricsSink;
52637
52790
  this.portsDebugLog = ports.debugLog;
52638
52791
  }
@@ -52648,31 +52801,32 @@ var AgentRuntime = class _AgentRuntime {
52648
52801
  * @param ports 可选端口覆盖(任一缺省走默认适配器)
52649
52802
  */
52650
52803
  static create(protocol, ports) {
52651
- const model = protocol.agent.model;
52652
- const skillResources = protocol.agent.resources.filter((r) => r.resourceType === EResourceType.SKILL);
52653
- const mcpResources = protocol.agent.resources.filter((r) => r.resourceType === EResourceType.MCP);
52654
- const mcpToolResources = protocol.agent.resources.filter((r) => r.resourceType === EResourceType.MCP_TOOL);
52655
- const cardResources = protocol.agent.resources.filter((r) => r.resourceType === EResourceType.CARD);
52656
- const knowledgeResources = protocol.agent.resources.filter((r) => r.resourceType === EResourceType.KNOWLEDGE);
52657
- const followUpQuestionGenerationEnabled = protocol.agent.resources.filter((resource) => resource.resourceType === EResourceType.FOLLOW_UP_QUESTIONS).some((resource) => resource.config.enable === true);
52658
- const mcpServerSpecs = aggregateMcpServers([...mcpResources, ...mcpToolResources], protocol.agentId);
52659
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);
52660
52814
  const innerProvider = portsArg.mcpServerProvider ?? new NoopMcpServerProvider();
52661
52815
  const rt = new _AgentRuntime({
52662
52816
  ...portsArg,
52663
52817
  mcpServerProvider: new CardRenderMcpServerProvider(innerProvider)
52664
52818
  });
52665
- rt.defaultSystemPrompt = protocol.agent.systemPrompt.content;
52666
- rt.defaultHarnessPrompt = protocol.agent.harness ? protocol.agent.harness.systemPrompt : DEFAULT_HARNESS_PROMPT;
52819
+ rt.defaultSystemPrompt = agentConfig.agent.systemPrompt.content;
52820
+ rt.defaultHarnessPrompt = agentConfig.agent.harness ? agentConfig.agent.harness.systemPrompt : DEFAULT_HARNESS_PROMPT;
52667
52821
  rt.defaultModel = model.defaultModel || void 0;
52668
52822
  rt.defaultThinkingLevel = model.callParams?.thinkingLevel;
52669
52823
  rt.skillResources = skillResources;
52670
52824
  rt.mcpServerSpecs = mcpServerSpecs;
52671
52825
  rt.cardResources = cardResources;
52672
52826
  rt.knowledgeResources = knowledgeResources;
52673
- rt.agentId = protocol.agentId;
52827
+ rt.agentId = agentConfig.agentId;
52674
52828
  rt.followUpQuestionGenerationEnabled = followUpQuestionGenerationEnabled;
52675
- rt.hookResources = normalizeHookResources(protocol.agent.resources.filter((r) => r.resourceType === EResourceType.HOOK));
52829
+ rt.hookResources = normalizeHookResources(agentConfig.agent.resources.filter((r) => r.resourceType === EResourceType.HOOK));
52676
52830
  return rt;
52677
52831
  }
52678
52832
  async prepareFollowUpQuestionContext(sessionId, history = []) {
@@ -56373,7 +56527,7 @@ var RemoteSignatureSigner = class {
56373
56527
  * 对一次出站请求取签名。
56374
56528
  *
56375
56529
  * @param req 见 {@link ISignRequest}(method/url/body)
56376
- * @returns `{authorization, signatureContent}`
56530
+ * @returns `{authorization, signatureContent, userId?}`
56377
56531
  * @throws 签名服务非 2xx / 鉴权头获取失败 / 响应缺字段时抛错(由 signingFetch 转 transport-error)。
56378
56532
  */
56379
56533
  async sign(req) {
@@ -56409,7 +56563,8 @@ var RemoteSignatureSigner = class {
56409
56563
  }
56410
56564
  return {
56411
56565
  authorization: payload.authorization,
56412
- signatureContent: payload.signatureContent
56566
+ signatureContent: payload.signatureContent,
56567
+ ...optionalUserId(payload.userId)
56413
56568
  };
56414
56569
  }
56415
56570
  };
@@ -56431,9 +56586,13 @@ function extractFromWrapped(wrapped) {
56431
56586
  }
56432
56587
  return {
56433
56588
  authorization: data.authorization,
56434
- signatureContent: data.signatureContent
56589
+ signatureContent: data.signatureContent,
56590
+ ...optionalUserId(data.userId)
56435
56591
  };
56436
56592
  }
56593
+ function optionalUserId(value) {
56594
+ return typeof value === "string" && value.trim() ? { userId: value.trim() } : {};
56595
+ }
56437
56596
  async function safeText(resp) {
56438
56597
  try {
56439
56598
  return await resp.text();
@@ -57978,6 +58137,7 @@ var SSEClientTransport = class {
57978
58137
 
57979
58138
  // ../linkque-agent-runtime/dist/esm/impl/mcp/alipay/signingFetch.js
57980
58139
  var ALIPAY_SDK_VERSION = "@alipay/open-mcp-server-2.0.4";
58140
+ var OAGW_ALIPAY_UID_HEADER = "x-oagw-alipay-uid";
57981
58141
  function createSigningFetch(signer, baseFetch = globalThis.fetch, onTraceId, debugLog) {
57982
58142
  const loggedFetch = debugLog ? createHttpLoggingFetch(debugLog, "mcp-call", baseFetch) : baseFetch;
57983
58143
  return async (url2, init) => {
@@ -57987,11 +58147,16 @@ function createSigningFetch(signer, baseFetch = globalThis.fetch, onTraceId, deb
57987
58147
  httpRequestUrl: targetUrl.pathname + targetUrl.search,
57988
58148
  httpRequestBody: typeof init?.body === "string" ? init.body : ""
57989
58149
  };
57990
- const { authorization, signatureContent } = await signer.sign(req);
58150
+ const { authorization, signatureContent, userId } = await signer.sign(req);
57991
58151
  const headers = new Headers(init?.headers);
57992
58152
  headers.set("Authorization", authorization);
57993
58153
  headers.set("X-Signature-Content", Buffer.from(signatureContent).toString("base64"));
57994
58154
  headers.set("X-Alipay-SDK-Version", ALIPAY_SDK_VERSION);
58155
+ if (userId) {
58156
+ headers.set(OAGW_ALIPAY_UID_HEADER, userId);
58157
+ } else {
58158
+ headers.delete(OAGW_ALIPAY_UID_HEADER);
58159
+ }
57995
58160
  const resp = await loggedFetch(url2, { ...init, headers });
57996
58161
  if (onTraceId) {
57997
58162
  try {
@@ -60268,8 +60433,10 @@ function setBakedProtocol(protocol) {
60268
60433
  }
60269
60434
 
60270
60435
  export {
60271
- EModelProvider,
60272
60436
  EResourceType,
60437
+ EResourceProviderType,
60438
+ EHookStage,
60439
+ EHookExecutorName,
60273
60440
  executeHomeData,
60274
60441
  FOLLOW_UP_CONTEXT_MAX_HISTORY_RUNS,
60275
60442
  LinkquegwEventHookExecutor,