linkque-cli-v2 1.1.3 → 1.1.4-beta.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.
Files changed (16) hide show
  1. package/linkquejs.js +37 -15
  2. package/package.json +1 -1
  3. package/vendor/linkque-agent-appwrite-integrate/dist/esm/{anthropic-messages-B5T6TFD2.js → anthropic-messages-YOPI234A.js} +1 -1
  4. package/vendor/linkque-agent-appwrite-integrate/dist/esm/{azure-openai-responses-S7HNQOSE.js → azure-openai-responses-67YPFLZQ.js} +2 -2
  5. package/vendor/linkque-agent-appwrite-integrate/dist/esm/{chunk-MR5QT2A5.js → chunk-IMZDZMKV.js} +149 -40
  6. package/vendor/linkque-agent-appwrite-integrate/dist/esm/{chunk-IKZ25GJD.js → chunk-LSBJJGJC.js} +1 -1
  7. package/vendor/linkque-agent-appwrite-integrate/dist/esm/{chunk-3S3TOEBZ.js → chunk-Y3G4J3TB.js} +1 -0
  8. package/vendor/linkque-agent-appwrite-integrate/dist/esm/{google-generative-ai-IOXNKFEV.js → google-generative-ai-R5DASQKW.js} +1 -1
  9. package/vendor/linkque-agent-appwrite-integrate/dist/esm/{google-vertex-U4ZV5IXZ.js → google-vertex-OLX2NFGJ.js} +1 -1
  10. package/vendor/linkque-agent-appwrite-integrate/dist/esm/{mistral-conversations-G3K7SSWR.js → mistral-conversations-L6T7EWC2.js} +1 -1
  11. package/vendor/linkque-agent-appwrite-integrate/dist/esm/{openai-codex-responses-4JJLPTCS.js → openai-codex-responses-7QJMWGY5.js} +2 -2
  12. package/vendor/linkque-agent-appwrite-integrate/dist/esm/{openai-completions-PH4WW6E7.js → openai-completions-75YD6VJJ.js} +1 -1
  13. package/vendor/linkque-agent-appwrite-integrate/dist/esm/{openai-responses-KGWAX6HR.js → openai-responses-G6MVJCGC.js} +2 -2
  14. package/vendor/linkque-agent-appwrite-integrate/dist/esm/runtime/handler/chat.js +2 -2
  15. package/vendor/linkque-agent-appwrite-integrate/dist/esm/runtime/protocol.js +2 -2
  16. package/worker.js +170 -31
package/linkquejs.js CHANGED
@@ -25304,6 +25304,7 @@ function analyzeA2UIBindings(protocol) {
25304
25304
  const listRoots = inferListRoots(components, issues);
25305
25305
  for (const component of components) {
25306
25306
  const context = {
25307
+ surfaceId,
25307
25308
  component,
25308
25309
  listRoot: listRoots.get(component.id),
25309
25310
  occurrences,
@@ -25317,6 +25318,7 @@ function analyzeA2UIBindings(protocol) {
25317
25318
  issues.push(issue2(`card.surfaces.${surfaceId}.components.${component.id}.children.path`, "INVALID_BINDING_PATH", `Invalid list path ${children.path}`));
25318
25319
  } else {
25319
25320
  occurrences.push({
25321
+ surfaceId,
25320
25322
  componentId: component.id,
25321
25323
  componentName: component.component,
25322
25324
  propertyPath: "children.path",
@@ -25335,6 +25337,16 @@ function analyzeA2UIBindings(protocol) {
25335
25337
  issues
25336
25338
  };
25337
25339
  }
25340
+ function collectReferencedA2UICardBusinessFieldIds(protocol, fields) {
25341
+ const businessFields = fields.filter((field) => field.source === "business").slice().sort((left, right) => right.path.length - left.path.length);
25342
+ const result = /* @__PURE__ */ new Set();
25343
+ for (const occurrence of analyzeA2UIBindings(protocol).occurrences) {
25344
+ const field = businessFields.find((candidate) => occurrence.canonicalPath === candidate.path || occurrence.canonicalPath.startsWith(`${candidate.path}/*/`) || occurrence.canonicalPath.startsWith(`${candidate.path}/`));
25345
+ if (field)
25346
+ result.add(field.fieldId);
25347
+ }
25348
+ return result;
25349
+ }
25338
25350
  function visitValue(value, propertyPath, context) {
25339
25351
  if (propertyPath === "action.local.path" && typeof value === "string") {
25340
25352
  addOccurrence(value, propertyPath, "local", context);
@@ -25366,6 +25378,7 @@ function addOccurrence(rawPath, propertyPath, usage, context) {
25366
25378
  return;
25367
25379
  }
25368
25380
  context.occurrences.push({
25381
+ surfaceId: context.surfaceId,
25369
25382
  componentId: context.component.id,
25370
25383
  componentName: context.component.component,
25371
25384
  propertyPath,
@@ -26051,12 +26064,15 @@ function validateA2UICardBindings(input, options = {}) {
26051
26064
  readyCandidates.set(candidateKey(candidate.resourceId, candidate.tool.toolName), candidate.tool);
26052
26065
  }
26053
26066
  const bindingByField = new Map(bindings.map((binding) => [binding.fieldId, binding]));
26067
+ const requiredFields = collectReferencedA2UICardBusinessFieldIds(input.draft.card, input.draft.manifest.fields.filter((field) => field.required));
26054
26068
  for (const field of input.draft.manifest.fields) {
26055
26069
  if (field.source !== "business")
26056
26070
  continue;
26057
26071
  if (selectedFields && !selectedFields.has(field.fieldId))
26058
26072
  continue;
26059
26073
  const binding = bindingByField.get(field.fieldId);
26074
+ if (!selectedFields && !requiredFields.has(field.fieldId) && !binding)
26075
+ continue;
26060
26076
  if (!binding) {
26061
26077
  issues.push(issue2(`fields.${field.fieldId}`, "CARD_BINDING_INCOMPLETE", `business field ${field.fieldId} has not been bound`));
26062
26078
  continue;
@@ -26394,9 +26410,9 @@ function getA2UICardResourceConfigIssues(value) {
26394
26410
  validateLooseJsonSchema(value.presentationInputSchema, "config.presentationInputSchema", issues);
26395
26411
  const fields = validateFields(value.fields, "config.fields", issues);
26396
26412
  const resolver = validateResolver(value.resolver, "config.resolver", issues);
26397
- validateTemplate(value.a2uiTemplate, fields, issues);
26413
+ const card = validateTemplate(value.a2uiTemplate, fields, issues);
26398
26414
  if (fields && resolver)
26399
- validateResolverCoverage(fields, resolver, issues);
26415
+ validateResolverCoverage(fields, resolver, issues, card);
26400
26416
  return issues;
26401
26417
  }
26402
26418
  function getA2UICardResourceConfigV3Issues(value) {
@@ -26429,9 +26445,9 @@ function getA2UICardResourceConfigV3Issues(value) {
26429
26445
  }
26430
26446
  const dataSources = validateDataSources(value.dataSources, "config.dataSources", issues);
26431
26447
  const bindings = validateV3OutputBindings(value.bindings, "config.bindings", issues);
26432
- validateTemplate(value.a2uiTemplate, fields, issues);
26448
+ const card = validateTemplate(value.a2uiTemplate, fields, issues);
26433
26449
  if (fields && dataSources && bindings) {
26434
- validateV3Coverage(fields, dataSources, bindings, issues);
26450
+ validateV3Coverage(fields, dataSources, bindings, issues, { card });
26435
26451
  }
26436
26452
  return issues;
26437
26453
  }
@@ -26545,7 +26561,8 @@ function validateV3Coverage(fields, dataSources, bindings, issues, options = {})
26545
26561
  bound.add(binding.fieldId);
26546
26562
  });
26547
26563
  if (options.requireComplete !== false) {
26548
- for (const fieldId of businessFields) {
26564
+ const requiredFields = options.card ? collectReferencedA2UICardBusinessFieldIds(options.card, fields.filter((field) => field.required)) : new Set(fields.filter((field) => field.source === "business" && field.required).map((field) => field.fieldId));
26565
+ for (const fieldId of requiredFields) {
26549
26566
  if (bound.has(fieldId))
26550
26567
  continue;
26551
26568
  issues.push(issue2("config.bindings", "CARD_BINDING_INCOMPLETE", `business field ${fieldId} is not bound`));
@@ -26983,13 +27000,13 @@ function validateInstructionShape(instruction, path22, issues) {
26983
27000
  function validateTemplate(value, fields, issues) {
26984
27001
  if (!isPlainRecord(value)) {
26985
27002
  issues.push(issue2("config.a2uiTemplate", "INVALID_A2UI_TEMPLATE", "a2uiTemplate must be an object"));
26986
- return;
27003
+ return void 0;
26987
27004
  }
26988
27005
  exactKeys(value, ["argsSchema", "content"], "config.a2uiTemplate", issues);
26989
27006
  validateLooseJsonSchema(value.argsSchema, "config.a2uiTemplate.argsSchema", issues);
26990
27007
  if (typeof value.content !== "string") {
26991
27008
  issues.push(issue2("config.a2uiTemplate.content", "INVALID_A2UI_CONTENT", "a2uiTemplate.content must be serialized A2UI JSON"));
26992
- return;
27009
+ return void 0;
26993
27010
  }
26994
27011
  try {
26995
27012
  const card = validateProtocol(JSON.parse(value.content), "config.a2uiTemplate.content", issues);
@@ -26997,9 +27014,11 @@ function validateTemplate(value, fields, issues) {
26997
27014
  const analysis = analyzeA2UIBindings(card);
26998
27015
  issues.push(...analysis.issues);
26999
27016
  }
27017
+ return card;
27000
27018
  } catch {
27001
27019
  issues.push(issue2("config.a2uiTemplate.content", "INVALID_A2UI_CONTENT", "a2uiTemplate.content must contain valid JSON"));
27002
27020
  }
27021
+ return void 0;
27003
27022
  }
27004
27023
  function validateLooseJsonSchema(value, path22, issues) {
27005
27024
  const schemaIssues = getJsonSchemaIssues(value, path22, {
@@ -27008,7 +27027,7 @@ function validateLooseJsonSchema(value, path22, issues) {
27008
27027
  issues.push(...schemaIssues);
27009
27028
  return schemaIssues.length === 0;
27010
27029
  }
27011
- function validateResolverCoverage(fields, resolver, issues) {
27030
+ function validateResolverCoverage(fields, resolver, issues, card) {
27012
27031
  const businessFields = new Set(fields.filter((field) => field.source === "business").map((field) => field.fieldId));
27013
27032
  const bound = /* @__PURE__ */ new Set();
27014
27033
  resolver.outputBindings.forEach((binding, index) => {
@@ -27017,7 +27036,8 @@ function validateResolverCoverage(fields, resolver, issues) {
27017
27036
  }
27018
27037
  bound.add(binding.fieldId);
27019
27038
  });
27020
- for (const fieldId of businessFields) {
27039
+ const requiredFields = card ? collectReferencedA2UICardBusinessFieldIds(card, fields.filter((field) => field.required)) : new Set(fields.filter((field) => field.source === "business" && field.required).map((field) => field.fieldId));
27040
+ for (const fieldId of requiredFields) {
27021
27041
  if (!bound.has(fieldId)) {
27022
27042
  issues.push(issue2("config.resolver.outputBindings", "CARD_BINDING_INCOMPLETE", `business field ${fieldId} is not bound`));
27023
27043
  }
@@ -27065,6 +27085,7 @@ function compileA2UICardResource(input) {
27065
27085
  }
27066
27086
  const fieldById = new Map(draft.manifest.fields.map((field) => [field.fieldId, field]));
27067
27087
  const selectionByField = /* @__PURE__ */ new Map();
27088
+ const requiredFields = collectReferencedA2UICardBusinessFieldIds(draft.card, draft.manifest.fields.filter((field) => field.required));
27068
27089
  for (const selection of input.bindings) {
27069
27090
  const field = fieldById.get(selection.fieldId);
27070
27091
  if (!field || field.source !== "business") {
@@ -27078,9 +27099,9 @@ function compileA2UICardResource(input) {
27078
27099
  }
27079
27100
  selectionByField.set(selection.fieldId, cloneSelection(selection));
27080
27101
  }
27081
- for (const field of draft.manifest.fields) {
27082
- if (field.source === "business" && !selectionByField.has(field.fieldId)) {
27083
- throw new A2UICardCompileError("CARD_BINDING_INCOMPLETE", `Business field ${field.fieldId} has not been bound`);
27102
+ for (const fieldId of requiredFields) {
27103
+ if (!selectionByField.has(fieldId)) {
27104
+ throw new A2UICardCompileError("CARD_BINDING_INCOMPLETE", `Required referenced business field ${fieldId} has not been bound`);
27084
27105
  }
27085
27106
  }
27086
27107
  const resolver = compileResolver([...selectionByField.values()]);
@@ -27172,6 +27193,7 @@ function compileV3Resource(draft, revision, bindings, tools) {
27172
27193
  const sourceById = /* @__PURE__ */ new Map();
27173
27194
  const outputBindings = [];
27174
27195
  const boundFields = /* @__PURE__ */ new Set();
27196
+ const requiredFields = collectReferencedA2UICardBusinessFieldIds(draft.card, draft.manifest.fields.filter((field) => field.required));
27175
27197
  for (const binding of bindings) {
27176
27198
  const field = fieldById.get(binding.fieldId);
27177
27199
  if (!field || field.source !== "business" || boundFields.has(binding.fieldId)) {
@@ -27199,9 +27221,9 @@ function compileV3Resource(draft, revision, bindings, tools) {
27199
27221
  transform: binding.transform
27200
27222
  });
27201
27223
  }
27202
- for (const field of draft.manifest.fields) {
27203
- if (field.source === "business" && !boundFields.has(field.fieldId)) {
27204
- throw new A2UICardCompileError("CARD_BINDING_INCOMPLETE", `Business field ${field.fieldId} has not been bound`);
27224
+ for (const fieldId of requiredFields) {
27225
+ if (!boundFields.has(fieldId)) {
27226
+ throw new A2UICardCompileError("CARD_BINDING_INCOMPLETE", `Required referenced business field ${fieldId} has not been bound`);
27205
27227
  }
27206
27228
  }
27207
27229
  const resource = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linkque-cli-v2",
3
- "version": "1.1.3",
3
+ "version": "1.1.4-beta.1",
4
4
  "description": "Public Linkque CLI bundle for sandbox debugging",
5
5
  "bin": {
6
6
  "linkquejs": "linkquejs.js"
@@ -19,7 +19,7 @@ import {
19
19
  } from "./chunk-Y6UTJIT4.js";
20
20
  import {
21
21
  calculateCost
22
- } from "./chunk-3S3TOEBZ.js";
22
+ } from "./chunk-Y3G4J3TB.js";
23
23
  import {
24
24
  getProviderEnvValue
25
25
  } from "./chunk-OXGCUIKV.js";
@@ -2,7 +2,7 @@ import {
2
2
  convertResponsesMessages,
3
3
  convertResponsesTools,
4
4
  processResponsesStream
5
- } from "./chunk-IKZ25GJD.js";
5
+ } from "./chunk-LSBJJGJC.js";
6
6
  import "./chunk-UFVAKOTZ.js";
7
7
  import {
8
8
  AzureOpenAI
@@ -23,7 +23,7 @@ import {
23
23
  } from "./chunk-Y6UTJIT4.js";
24
24
  import {
25
25
  clampThinkingLevel
26
- } from "./chunk-3S3TOEBZ.js";
26
+ } from "./chunk-Y3G4J3TB.js";
27
27
  import {
28
28
  getProviderEnvValue
29
29
  } from "./chunk-OXGCUIKV.js";
@@ -132,8 +132,9 @@ import {
132
132
  import {
133
133
  createModels,
134
134
  createProvider,
135
- lazyApi
136
- } from "./chunk-3S3TOEBZ.js";
135
+ lazyApi,
136
+ lazyStream
137
+ } from "./chunk-Y3G4J3TB.js";
137
138
  import {
138
139
  getProviderEnvValue
139
140
  } from "./chunk-OXGCUIKV.js";
@@ -17006,6 +17007,7 @@ function analyzeA2UIBindings(protocol) {
17006
17007
  const listRoots = inferListRoots(components, issues);
17007
17008
  for (const component of components) {
17008
17009
  const context = {
17010
+ surfaceId,
17009
17011
  component,
17010
17012
  listRoot: listRoots.get(component.id),
17011
17013
  occurrences,
@@ -17019,6 +17021,7 @@ function analyzeA2UIBindings(protocol) {
17019
17021
  issues.push(issue2(`card.surfaces.${surfaceId}.components.${component.id}.children.path`, "INVALID_BINDING_PATH", `Invalid list path ${children.path}`));
17020
17022
  } else {
17021
17023
  occurrences.push({
17024
+ surfaceId,
17022
17025
  componentId: component.id,
17023
17026
  componentName: component.component,
17024
17027
  propertyPath: "children.path",
@@ -17037,6 +17040,16 @@ function analyzeA2UIBindings(protocol) {
17037
17040
  issues
17038
17041
  };
17039
17042
  }
17043
+ function collectReferencedA2UICardBusinessFieldIds(protocol, fields) {
17044
+ const businessFields = fields.filter((field) => field.source === "business").slice().sort((left, right) => right.path.length - left.path.length);
17045
+ const result = /* @__PURE__ */ new Set();
17046
+ for (const occurrence of analyzeA2UIBindings(protocol).occurrences) {
17047
+ const field = businessFields.find((candidate) => occurrence.canonicalPath === candidate.path || occurrence.canonicalPath.startsWith(`${candidate.path}/*/`) || occurrence.canonicalPath.startsWith(`${candidate.path}/`));
17048
+ if (field)
17049
+ result.add(field.fieldId);
17050
+ }
17051
+ return result;
17052
+ }
17040
17053
  function visitValue(value, propertyPath, context) {
17041
17054
  if (propertyPath === "action.local.path" && typeof value === "string") {
17042
17055
  addOccurrence(value, propertyPath, "local", context);
@@ -17068,6 +17081,7 @@ function addOccurrence(rawPath, propertyPath, usage, context) {
17068
17081
  return;
17069
17082
  }
17070
17083
  context.occurrences.push({
17084
+ surfaceId: context.surfaceId,
17071
17085
  componentId: context.component.id,
17072
17086
  componentName: context.component.component,
17073
17087
  propertyPath,
@@ -17479,9 +17493,9 @@ function getA2UICardResourceConfigIssues(value) {
17479
17493
  validateLooseJsonSchema(value.presentationInputSchema, "config.presentationInputSchema", issues);
17480
17494
  const fields = validateFields(value.fields, "config.fields", issues);
17481
17495
  const resolver = validateResolver(value.resolver, "config.resolver", issues);
17482
- validateTemplate(value.a2uiTemplate, fields, issues);
17496
+ const card = validateTemplate(value.a2uiTemplate, fields, issues);
17483
17497
  if (fields && resolver)
17484
- validateResolverCoverage(fields, resolver, issues);
17498
+ validateResolverCoverage(fields, resolver, issues, card);
17485
17499
  return issues;
17486
17500
  }
17487
17501
  function getA2UICardResourceConfigV3Issues(value) {
@@ -17514,9 +17528,9 @@ function getA2UICardResourceConfigV3Issues(value) {
17514
17528
  }
17515
17529
  const dataSources = validateDataSources(value.dataSources, "config.dataSources", issues);
17516
17530
  const bindings = validateV3OutputBindings(value.bindings, "config.bindings", issues);
17517
- validateTemplate(value.a2uiTemplate, fields, issues);
17531
+ const card = validateTemplate(value.a2uiTemplate, fields, issues);
17518
17532
  if (fields && dataSources && bindings) {
17519
- validateV3Coverage(fields, dataSources, bindings, issues);
17533
+ validateV3Coverage(fields, dataSources, bindings, issues, { card });
17520
17534
  }
17521
17535
  return issues;
17522
17536
  }
@@ -17630,7 +17644,8 @@ function validateV3Coverage(fields, dataSources, bindings, issues, options = {})
17630
17644
  bound.add(binding.fieldId);
17631
17645
  });
17632
17646
  if (options.requireComplete !== false) {
17633
- for (const fieldId of businessFields) {
17647
+ const requiredFields = options.card ? collectReferencedA2UICardBusinessFieldIds(options.card, fields.filter((field) => field.required)) : new Set(fields.filter((field) => field.source === "business" && field.required).map((field) => field.fieldId));
17648
+ for (const fieldId of requiredFields) {
17634
17649
  if (bound.has(fieldId))
17635
17650
  continue;
17636
17651
  issues.push(issue2("config.bindings", "CARD_BINDING_INCOMPLETE", `business field ${fieldId} is not bound`));
@@ -17930,13 +17945,13 @@ function validateInstructionShape(instruction, path2, issues) {
17930
17945
  function validateTemplate(value, fields, issues) {
17931
17946
  if (!isPlainRecord(value)) {
17932
17947
  issues.push(issue2("config.a2uiTemplate", "INVALID_A2UI_TEMPLATE", "a2uiTemplate must be an object"));
17933
- return;
17948
+ return void 0;
17934
17949
  }
17935
17950
  exactKeys(value, ["argsSchema", "content"], "config.a2uiTemplate", issues);
17936
17951
  validateLooseJsonSchema(value.argsSchema, "config.a2uiTemplate.argsSchema", issues);
17937
17952
  if (typeof value.content !== "string") {
17938
17953
  issues.push(issue2("config.a2uiTemplate.content", "INVALID_A2UI_CONTENT", "a2uiTemplate.content must be serialized A2UI JSON"));
17939
- return;
17954
+ return void 0;
17940
17955
  }
17941
17956
  try {
17942
17957
  const card = validateProtocol(JSON.parse(value.content), "config.a2uiTemplate.content", issues);
@@ -17944,9 +17959,11 @@ function validateTemplate(value, fields, issues) {
17944
17959
  const analysis = analyzeA2UIBindings(card);
17945
17960
  issues.push(...analysis.issues);
17946
17961
  }
17962
+ return card;
17947
17963
  } catch {
17948
17964
  issues.push(issue2("config.a2uiTemplate.content", "INVALID_A2UI_CONTENT", "a2uiTemplate.content must contain valid JSON"));
17949
17965
  }
17966
+ return void 0;
17950
17967
  }
17951
17968
  function validateLooseJsonSchema(value, path2, issues) {
17952
17969
  const schemaIssues = getJsonSchemaIssues2(value, path2, {
@@ -17955,7 +17972,7 @@ function validateLooseJsonSchema(value, path2, issues) {
17955
17972
  issues.push(...schemaIssues);
17956
17973
  return schemaIssues.length === 0;
17957
17974
  }
17958
- function validateResolverCoverage(fields, resolver, issues) {
17975
+ function validateResolverCoverage(fields, resolver, issues, card) {
17959
17976
  const businessFields = new Set(fields.filter((field) => field.source === "business").map((field) => field.fieldId));
17960
17977
  const bound = /* @__PURE__ */ new Set();
17961
17978
  resolver.outputBindings.forEach((binding, index2) => {
@@ -17964,7 +17981,8 @@ function validateResolverCoverage(fields, resolver, issues) {
17964
17981
  }
17965
17982
  bound.add(binding.fieldId);
17966
17983
  });
17967
- for (const fieldId of businessFields) {
17984
+ const requiredFields = card ? collectReferencedA2UICardBusinessFieldIds(card, fields.filter((field) => field.required)) : new Set(fields.filter((field) => field.source === "business" && field.required).map((field) => field.fieldId));
17985
+ for (const fieldId of requiredFields) {
17968
17986
  if (!bound.has(fieldId)) {
17969
17987
  issues.push(issue2("config.resolver.outputBindings", "CARD_BINDING_INCOMPLETE", `business field ${fieldId} is not bound`));
17970
17988
  }
@@ -18648,6 +18666,9 @@ var McpProxyTool = class {
18648
18666
  if (params.describe !== void 0) {
18649
18667
  return this.executeDescribe(params.describe, params.server, signal);
18650
18668
  }
18669
+ if (params.searches !== void 0) {
18670
+ return this.executeBatchSearch(params.searches, params.server);
18671
+ }
18651
18672
  if (params.search !== void 0) {
18652
18673
  return this.executeSearch(params.search, params.server);
18653
18674
  }
@@ -18744,6 +18765,20 @@ ${formatSchema(tool.inputSchema, " ")}`);
18744
18765
  }
18745
18766
  return lines.join("\n").trim();
18746
18767
  }
18768
+ /** `mcp({ searches: [...] })`:一次连接元数据并按 query 分组执行多组搜索。 */
18769
+ async executeBatchSearch(queries, serverHint) {
18770
+ const normalized = [
18771
+ ...new Set(queries.map((query) => query.trim()).filter(Boolean))
18772
+ ].slice(0, MCP_BATCH_SEARCH_MAX_ITEMS);
18773
+ if (normalized.length === 0) {
18774
+ return "Batch search requires at least one non-empty query.";
18775
+ }
18776
+ const specs = serverHint ? this.specsMatching(serverHint) : this.specs;
18777
+ await Promise.all(specs.map((spec) => this.ensureEntry(spec.serverName)));
18778
+ const results = await Promise.all(normalized.map((query) => this.executeSearch(query, serverHint)));
18779
+ return results.map((result, index2) => `Query ${index2 + 1}: "${normalized[index2]}"
18780
+ ${result}`).join("\n\n");
18781
+ }
18747
18782
  /** `mcp({ describe: "tool" })`:输出工具所属 server + 参数 schema。 */
18748
18783
  async executeDescribe(toolName, serverHint, signal) {
18749
18784
  const found = await this.findTool(toolName, serverHint, signal);
@@ -18835,6 +18870,9 @@ function parseProxyArgs(args) {
18835
18870
  out.describe = args.describe;
18836
18871
  if (typeof args.search === "string")
18837
18872
  out.search = args.search;
18873
+ if (Array.isArray(args.searches)) {
18874
+ out.searches = args.searches.filter((query) => typeof query === "string").slice(0, MCP_BATCH_SEARCH_MAX_ITEMS);
18875
+ }
18838
18876
  if (typeof args.tool === "string")
18839
18877
  out.tool = args.tool;
18840
18878
  if (typeof args.server === "string")
@@ -18878,12 +18916,14 @@ function truncate(text, max2) {
18878
18916
  function isRecord(value) {
18879
18917
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
18880
18918
  }
18919
+ var MCP_BATCH_SEARCH_MAX_ITEMS = 5;
18881
18920
  var MCP_PROXY_DESCRIPTION = [
18882
18921
  "MCP \u7F51\u5173:\u53D1\u73B0\u5E76\u8C03\u7528 MCP server \u63D0\u4F9B\u7684\u5DE5\u5177\u3002\u53EF\u7528\u52A8\u4F5C:",
18883
18922
  "- mcp({}) \u6216 mcp({ status: true }):\u67E5\u770B\u6240\u6709 server \u8FDE\u63A5\u72B6\u6001\u4E0E\u5DE5\u5177\u6570\u3002",
18884
18923
  '- mcp({ connect: "server" }):\u8FDE\u63A5\u5E76\u5237\u65B0\u67D0 server \u7684\u5DE5\u5177\u5217\u8868\u3002',
18885
18924
  '- mcp({ server: "name" }):\u5217\u51FA\u8BE5 server \u7684\u5DE5\u5177\u3002',
18886
18925
  '- mcp({ search: "\u5173\u952E\u8BCD" }):\u6309\u540D\u79F0/\u63CF\u8FF0\u6A21\u7CCA\u641C\u7D22\u5DE5\u5177(\u7A7A\u683C\u5206\u8BCD OR)\u3002',
18926
+ '- mcp({ searches: ["\u5173\u952E\u8BCD1", "\u5173\u952E\u8BCD2"] }):\u4E00\u6B21\u6267\u884C\u591A\u7EC4\u641C\u7D22\u5E76\u6309 query \u5206\u7EC4\u8FD4\u56DE(\u6700\u591A 5 \u7EC4)\u3002',
18887
18927
  '- mcp({ describe: "toolName" }):\u67E5\u770B\u67D0\u5DE5\u5177\u7684\u53C2\u6570 schema\u3002',
18888
18928
  '- mcp({ tool: "toolName", args: { ... } }):\u8C03\u7528\u67D0\u5DE5\u5177,args \u4E3A\u5BF9\u8C61\u3002',
18889
18929
  "\u53EF\u7528 server \u540D\u89C1 mcp({}) \u8F93\u51FA\u3002\u4EC5\u5728\u786E\u9700\u8C03\u7528 MCP \u5DE5\u5177\u65F6\u4F7F\u7528\u672C\u5DE5\u5177\u3002",
@@ -18906,6 +18946,13 @@ var MCP_PROXY_INPUT_SCHEMA = {
18906
18946
  type: "string",
18907
18947
  description: "\u6309\u540D\u79F0/\u63CF\u8FF0\u6A21\u7CCA\u641C\u7D22\u5DE5\u5177(\u7A7A\u683C\u5206\u8BCD OR)"
18908
18948
  },
18949
+ searches: {
18950
+ type: "array",
18951
+ description: "\u6279\u91CF\u641C\u7D22\u5173\u952E\u8BCD\uFF1B\u4E00\u6B21\u63D0\u4EA4\u6240\u6709\u5019\u9009 query\uFF0C\u6309 query \u5206\u7EC4\u8FD4\u56DE",
18952
+ minItems: 1,
18953
+ maxItems: MCP_BATCH_SEARCH_MAX_ITEMS,
18954
+ items: { type: "string", minLength: 1 }
18955
+ },
18909
18956
  describe: { type: "string", description: "\u67E5\u770B\u67D0\u5DE5\u5177\u7684\u53C2\u6570 schema" },
18910
18957
  tool: { type: "string", description: "\u8981\u8C03\u7528\u7684\u5DE5\u5177\u540D(\u53EF\u914D\u5408 server \u6D88\u6B67)" },
18911
18958
  args: {
@@ -20154,10 +20201,10 @@ function extractName(args) {
20154
20201
  }
20155
20202
 
20156
20203
  // ../../node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.lazy.js
20157
- var anthropicMessagesApi = () => lazyApi(() => import("./anthropic-messages-B5T6TFD2.js"));
20204
+ var anthropicMessagesApi = () => lazyApi(() => import("./anthropic-messages-YOPI234A.js"));
20158
20205
 
20159
20206
  // ../../node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.lazy.js
20160
- var azureOpenAIResponsesApi = () => lazyApi(() => import("./azure-openai-responses-S7HNQOSE.js"));
20207
+ var azureOpenAIResponsesApi = () => lazyApi(() => import("./azure-openai-responses-67YPFLZQ.js"));
20161
20208
 
20162
20209
  // ../../node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.lazy.js
20163
20210
  var __rewriteRelativeImportExtension = function(path2, preserveJsx) {
@@ -20176,22 +20223,22 @@ var bedrockModuleOverride;
20176
20223
  var bedrockConverseStreamApi = () => lazyApi(async () => bedrockModuleOverride ?? await importNodeOnlyApi("./bedrock-converse-stream.ts"));
20177
20224
 
20178
20225
  // ../../node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.lazy.js
20179
- var googleGenerativeAIApi = () => lazyApi(() => import("./google-generative-ai-IOXNKFEV.js"));
20226
+ var googleGenerativeAIApi = () => lazyApi(() => import("./google-generative-ai-R5DASQKW.js"));
20180
20227
 
20181
20228
  // ../../node_modules/@earendil-works/pi-ai/dist/api/google-vertex.lazy.js
20182
- var googleVertexApi = () => lazyApi(() => import("./google-vertex-U4ZV5IXZ.js"));
20229
+ var googleVertexApi = () => lazyApi(() => import("./google-vertex-OLX2NFGJ.js"));
20183
20230
 
20184
20231
  // ../../node_modules/@earendil-works/pi-ai/dist/api/mistral-conversations.lazy.js
20185
- var mistralConversationsApi = () => lazyApi(() => import("./mistral-conversations-G3K7SSWR.js"));
20232
+ var mistralConversationsApi = () => lazyApi(() => import("./mistral-conversations-L6T7EWC2.js"));
20186
20233
 
20187
20234
  // ../../node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.lazy.js
20188
- var openAICodexResponsesApi = () => lazyApi(() => import("./openai-codex-responses-4JJLPTCS.js"));
20235
+ var openAICodexResponsesApi = () => lazyApi(() => import("./openai-codex-responses-7QJMWGY5.js"));
20189
20236
 
20190
20237
  // ../../node_modules/@earendil-works/pi-ai/dist/api/openai-completions.lazy.js
20191
- var openAICompletionsApi = () => lazyApi(() => import("./openai-completions-PH4WW6E7.js"));
20238
+ var openAICompletionsApi = () => lazyApi(() => import("./openai-completions-75YD6VJJ.js"));
20192
20239
 
20193
20240
  // ../../node_modules/@earendil-works/pi-ai/dist/api/openai-responses.lazy.js
20194
- var openAIResponsesApi = () => lazyApi(() => import("./openai-responses-KGWAX6HR.js"));
20241
+ var openAIResponsesApi = () => lazyApi(() => import("./openai-responses-G6MVJCGC.js"));
20195
20242
 
20196
20243
  // ../../node_modules/@earendil-works/pi-ai/dist/api/pi-messages.lazy.js
20197
20244
  var piMessagesApi = () => lazyApi(() => import("./pi-messages-ZX3KUWSZ.js"));
@@ -51497,8 +51544,68 @@ var import_yaml2 = __toESM(require_dist(), 1);
51497
51544
  var DEFAULT_MAX_BYTES = 50 * 1024;
51498
51545
  var runtimeBuffer = globalThis.Buffer;
51499
51546
 
51547
+ // ../linkque-agent-runtime/dist/esm/impl/agent/pi/llmRequestThrottle.js
51548
+ var DEFAULT_LLM_REQUEST_MIN_INTERVAL_MS = 1e3;
51549
+ var LlmRequestThrottle = class {
51550
+ minIntervalMs;
51551
+ now;
51552
+ delay;
51553
+ onDelay;
51554
+ queue = Promise.resolve();
51555
+ nextRequestAt = 0;
51556
+ constructor(options = {}) {
51557
+ const configured = options.minIntervalMs ?? DEFAULT_LLM_REQUEST_MIN_INTERVAL_MS;
51558
+ this.minIntervalMs = Number.isFinite(configured) && configured > 0 ? Math.floor(configured) : 0;
51559
+ this.now = options.now ?? Date.now;
51560
+ this.delay = options.delay ?? delayWithSignal;
51561
+ this.onDelay = options.onDelay ?? (() => {
51562
+ });
51563
+ }
51564
+ /** 等到当前请求允许启动;取消信号会中断尚未开始的等待。 */
51565
+ waitForTurn(signal) {
51566
+ const scheduled = this.queue.then(async () => {
51567
+ signal?.throwIfAborted();
51568
+ const delayMs = Math.max(0, this.nextRequestAt - this.now());
51569
+ if (delayMs > 0) {
51570
+ this.onDelay(delayMs);
51571
+ await this.delay(delayMs, signal);
51572
+ }
51573
+ signal?.throwIfAborted();
51574
+ this.nextRequestAt = this.now() + this.minIntervalMs;
51575
+ });
51576
+ this.queue = scheduled.catch(() => void 0);
51577
+ return scheduled;
51578
+ }
51579
+ };
51580
+ function delayWithSignal(delayMs, signal) {
51581
+ return new Promise((resolve, reject) => {
51582
+ if (signal?.aborted) {
51583
+ reject(signal.reason);
51584
+ return;
51585
+ }
51586
+ const timer = setTimeout(() => {
51587
+ signal?.removeEventListener("abort", onAbort);
51588
+ resolve();
51589
+ }, delayMs);
51590
+ const onAbort = () => {
51591
+ clearTimeout(timer);
51592
+ reject(signal?.reason);
51593
+ };
51594
+ signal?.addEventListener("abort", onAbort, { once: true });
51595
+ });
51596
+ }
51597
+
51500
51598
  // ../linkque-agent-runtime/dist/esm/impl/agent/pi/createAgentSession.js
51501
51599
  async function createAgentSession(options) {
51600
+ const llmThrottle = new LlmRequestThrottle({
51601
+ minIntervalMs: options.llmRequestMinIntervalMs ?? DEFAULT_LLM_REQUEST_MIN_INTERVAL_MS,
51602
+ onDelay: (delayMs) => {
51603
+ try {
51604
+ options.debugLog?.(`[llm-throttle] wait ${delayMs}ms before next request`, EDebugLogScope.LLM);
51605
+ } catch {
51606
+ }
51607
+ }
51608
+ });
51502
51609
  const agent = new Agent({
51503
51610
  initialState: {
51504
51611
  model: options.model,
@@ -51518,28 +51625,30 @@ async function createAgentSession(options) {
51518
51625
  // 不 await/转换(否则破坏 stream)。
51519
51626
  streamFn: (model, context, streamOptions) => {
51520
51627
  const logSink = options.debugLog;
51521
- if (!logSink) {
51522
- return options.models.streamSimple(model, context, streamOptions);
51523
- }
51524
51628
  const opts = { ...streamOptions };
51525
- const baseUrl = model.baseUrl ?? "<unknown>";
51526
- const prevOnPayload = opts.onPayload;
51527
- opts.onPayload = async (payload, m) => {
51528
- await prevOnPayload?.(payload, m);
51529
- try {
51530
- logSink(formatHttpLogLine("llm", "req", `POST ${baseUrl} model=${m.id} payload=${summarizeBody(safeStringifyPayload(payload))}`), EDebugLogScope.LLM);
51531
- } catch {
51532
- }
51533
- };
51534
- const prevOnResponse = opts.onResponse;
51535
- opts.onResponse = async (response, m) => {
51536
- await prevOnResponse?.(response, m);
51537
- try {
51538
- logSink(formatHttpLogLine("llm", "resp", `POST ${baseUrl} model=${m.id} ${response.status} headers=${redactHeaders(response.headers)}`), EDebugLogScope.LLM);
51539
- } catch {
51540
- }
51541
- };
51542
- return options.models.streamSimple(model, context, opts);
51629
+ if (logSink) {
51630
+ const baseUrl = model.baseUrl ?? "<unknown>";
51631
+ const prevOnPayload = opts.onPayload;
51632
+ opts.onPayload = async (payload, m) => {
51633
+ await prevOnPayload?.(payload, m);
51634
+ try {
51635
+ logSink(formatHttpLogLine("llm", "req", `POST ${baseUrl} model=${m.id} payload=${summarizeBody(safeStringifyPayload(payload))}`), EDebugLogScope.LLM);
51636
+ } catch {
51637
+ }
51638
+ };
51639
+ const prevOnResponse = opts.onResponse;
51640
+ opts.onResponse = async (response, m) => {
51641
+ await prevOnResponse?.(response, m);
51642
+ try {
51643
+ logSink(formatHttpLogLine("llm", "resp", `POST ${baseUrl} model=${m.id} ${response.status} headers=${redactHeaders(response.headers)}`), EDebugLogScope.LLM);
51644
+ } catch {
51645
+ }
51646
+ };
51647
+ }
51648
+ return lazyStream(model, async () => {
51649
+ await llmThrottle.waitForTurn(opts.signal);
51650
+ return options.models.streamSimple(model, context, opts);
51651
+ });
51543
51652
  },
51544
51653
  getApiKey: options.getApiKey
51545
51654
  });
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-CT4G24PS.js";
10
10
  import {
11
11
  calculateCost
12
- } from "./chunk-3S3TOEBZ.js";
12
+ } from "./chunk-Y3G4J3TB.js";
13
13
  import {
14
14
  parseStreamingJson
15
15
  } from "./chunk-DYEQRE6N.js";
@@ -600,6 +600,7 @@ function clampThinkingLevel(model, level) {
600
600
  }
601
601
 
602
602
  export {
603
+ lazyStream,
603
604
  lazyApi,
604
605
  createModels,
605
606
  createProvider,
@@ -24,7 +24,7 @@ import {
24
24
  import {
25
25
  calculateCost,
26
26
  clampThinkingLevel
27
- } from "./chunk-3S3TOEBZ.js";
27
+ } from "./chunk-Y3G4J3TB.js";
28
28
  import {
29
29
  AssistantMessageEventStream
30
30
  } from "./chunk-46SEH6ER.js";
@@ -26,7 +26,7 @@ import {
26
26
  import {
27
27
  calculateCost,
28
28
  clampThinkingLevel
29
- } from "./chunk-3S3TOEBZ.js";
29
+ } from "./chunk-Y3G4J3TB.js";
30
30
  import {
31
31
  getProviderEnvValue
32
32
  } from "./chunk-OXGCUIKV.js";
@@ -73,7 +73,7 @@ import {
73
73
  import {
74
74
  calculateCost,
75
75
  clampThinkingLevel
76
- } from "./chunk-3S3TOEBZ.js";
76
+ } from "./chunk-Y3G4J3TB.js";
77
77
  import {
78
78
  parseStreamingJson
79
79
  } from "./chunk-DYEQRE6N.js";
@@ -13,7 +13,7 @@ import {
13
13
  convertResponsesMessages,
14
14
  convertResponsesTools,
15
15
  processResponsesStream
16
- } from "./chunk-IKZ25GJD.js";
16
+ } from "./chunk-LSBJJGJC.js";
17
17
  import "./chunk-UFVAKOTZ.js";
18
18
  import {
19
19
  clampOpenAIPromptCacheKey
@@ -31,7 +31,7 @@ import {
31
31
  } from "./chunk-Y6UTJIT4.js";
32
32
  import {
33
33
  clampThinkingLevel
34
- } from "./chunk-3S3TOEBZ.js";
34
+ } from "./chunk-Y3G4J3TB.js";
35
35
  import {
36
36
  getProviderEnvValue
37
37
  } from "./chunk-OXGCUIKV.js";
@@ -25,7 +25,7 @@ import {
25
25
  import {
26
26
  calculateCost,
27
27
  clampThinkingLevel
28
- } from "./chunk-3S3TOEBZ.js";
28
+ } from "./chunk-Y3G4J3TB.js";
29
29
  import {
30
30
  getProviderEnvValue
31
31
  } from "./chunk-OXGCUIKV.js";
@@ -9,7 +9,7 @@ import {
9
9
  convertResponsesMessages,
10
10
  convertResponsesTools,
11
11
  processResponsesStream
12
- } from "./chunk-IKZ25GJD.js";
12
+ } from "./chunk-LSBJJGJC.js";
13
13
  import "./chunk-UFVAKOTZ.js";
14
14
  import {
15
15
  OpenAI
@@ -30,7 +30,7 @@ import {
30
30
  } from "./chunk-Y6UTJIT4.js";
31
31
  import {
32
32
  clampThinkingLevel
33
- } from "./chunk-3S3TOEBZ.js";
33
+ } from "./chunk-Y3G4J3TB.js";
34
34
  import {
35
35
  getProviderEnvValue
36
36
  } from "./chunk-OXGCUIKV.js";
@@ -51,12 +51,12 @@ import {
51
51
  parseConversationRunRequest,
52
52
  parseSkillFile,
53
53
  streamToConversationEvents
54
- } from "../../chunk-MR5QT2A5.js";
54
+ } from "../../chunk-IMZDZMKV.js";
55
55
  import "../../chunk-XUFLSZM4.js";
56
56
  import "../../chunk-I64V3ICJ.js";
57
57
  import "../../chunk-6MHDOBWO.js";
58
58
  import "../../chunk-E2P6TIFG.js";
59
- import "../../chunk-3S3TOEBZ.js";
59
+ import "../../chunk-Y3G4J3TB.js";
60
60
  import "../../chunk-OXGCUIKV.js";
61
61
  import "../../chunk-DYEQRE6N.js";
62
62
  import "../../chunk-46SEH6ER.js";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  getBakedProtocol,
3
3
  setBakedProtocol
4
- } from "../chunk-MR5QT2A5.js";
4
+ } from "../chunk-IMZDZMKV.js";
5
5
  import "../chunk-XUFLSZM4.js";
6
6
  import "../chunk-I64V3ICJ.js";
7
7
  import "../chunk-6MHDOBWO.js";
8
8
  import "../chunk-E2P6TIFG.js";
9
- import "../chunk-3S3TOEBZ.js";
9
+ import "../chunk-Y3G4J3TB.js";
10
10
  import "../chunk-OXGCUIKV.js";
11
11
  import "../chunk-DYEQRE6N.js";
12
12
  import "../chunk-46SEH6ER.js";
package/worker.js CHANGED
@@ -13822,6 +13822,7 @@ function analyzeA2UIBindings(protocol) {
13822
13822
  const listRoots = inferListRoots(components, issues);
13823
13823
  for (const component of components) {
13824
13824
  const context2 = {
13825
+ surfaceId,
13825
13826
  component,
13826
13827
  listRoot: listRoots.get(component.id),
13827
13828
  occurrences,
@@ -13835,6 +13836,7 @@ function analyzeA2UIBindings(protocol) {
13835
13836
  issues.push(issue2(`card.surfaces.${surfaceId}.components.${component.id}.children.path`, "INVALID_BINDING_PATH", `Invalid list path ${children.path}`));
13836
13837
  } else {
13837
13838
  occurrences.push({
13839
+ surfaceId,
13838
13840
  componentId: component.id,
13839
13841
  componentName: component.component,
13840
13842
  propertyPath: "children.path",
@@ -13853,6 +13855,16 @@ function analyzeA2UIBindings(protocol) {
13853
13855
  issues
13854
13856
  };
13855
13857
  }
13858
+ function collectReferencedA2UICardBusinessFieldIds(protocol, fields) {
13859
+ const businessFields = fields.filter((field) => field.source === "business").slice().sort((left, right) => right.path.length - left.path.length);
13860
+ const result = /* @__PURE__ */ new Set();
13861
+ for (const occurrence of analyzeA2UIBindings(protocol).occurrences) {
13862
+ const field = businessFields.find((candidate) => occurrence.canonicalPath === candidate.path || occurrence.canonicalPath.startsWith(`${candidate.path}/*/`) || occurrence.canonicalPath.startsWith(`${candidate.path}/`));
13863
+ if (field)
13864
+ result.add(field.fieldId);
13865
+ }
13866
+ return result;
13867
+ }
13856
13868
  function visitValue(value, propertyPath, context2) {
13857
13869
  if (propertyPath === "action.local.path" && typeof value === "string") {
13858
13870
  addOccurrence(value, propertyPath, "local", context2);
@@ -13884,6 +13896,7 @@ function addOccurrence(rawPath, propertyPath, usage, context2) {
13884
13896
  return;
13885
13897
  }
13886
13898
  context2.occurrences.push({
13899
+ surfaceId: context2.surfaceId,
13887
13900
  componentId: context2.component.id,
13888
13901
  componentName: context2.component.component,
13889
13902
  propertyPath,
@@ -14258,6 +14271,7 @@ var init_binding_context = __esm({
14258
14271
  init_json2();
14259
14272
  init_schema2();
14260
14273
  init_expression();
14274
+ init_binding_analyzer();
14261
14275
  }
14262
14276
  });
14263
14277
 
@@ -14309,9 +14323,9 @@ function getA2UICardResourceConfigIssues(value) {
14309
14323
  validateLooseJsonSchema(value.presentationInputSchema, "config.presentationInputSchema", issues);
14310
14324
  const fields = validateFields(value.fields, "config.fields", issues);
14311
14325
  const resolver = validateResolver(value.resolver, "config.resolver", issues);
14312
- validateTemplate(value.a2uiTemplate, fields, issues);
14326
+ const card = validateTemplate(value.a2uiTemplate, fields, issues);
14313
14327
  if (fields && resolver)
14314
- validateResolverCoverage(fields, resolver, issues);
14328
+ validateResolverCoverage(fields, resolver, issues, card);
14315
14329
  return issues;
14316
14330
  }
14317
14331
  function getA2UICardResourceConfigV3Issues(value) {
@@ -14344,9 +14358,9 @@ function getA2UICardResourceConfigV3Issues(value) {
14344
14358
  }
14345
14359
  const dataSources = validateDataSources(value.dataSources, "config.dataSources", issues);
14346
14360
  const bindings = validateV3OutputBindings(value.bindings, "config.bindings", issues);
14347
- validateTemplate(value.a2uiTemplate, fields, issues);
14361
+ const card = validateTemplate(value.a2uiTemplate, fields, issues);
14348
14362
  if (fields && dataSources && bindings) {
14349
- validateV3Coverage(fields, dataSources, bindings, issues);
14363
+ validateV3Coverage(fields, dataSources, bindings, issues, { card });
14350
14364
  }
14351
14365
  return issues;
14352
14366
  }
@@ -14460,7 +14474,8 @@ function validateV3Coverage(fields, dataSources, bindings, issues, options = {})
14460
14474
  bound.add(binding.fieldId);
14461
14475
  });
14462
14476
  if (options.requireComplete !== false) {
14463
- for (const fieldId of businessFields) {
14477
+ const requiredFields = options.card ? collectReferencedA2UICardBusinessFieldIds(options.card, fields.filter((field) => field.required)) : new Set(fields.filter((field) => field.source === "business" && field.required).map((field) => field.fieldId));
14478
+ for (const fieldId of requiredFields) {
14464
14479
  if (bound.has(fieldId))
14465
14480
  continue;
14466
14481
  issues.push(issue2("config.bindings", "CARD_BINDING_INCOMPLETE", `business field ${fieldId} is not bound`));
@@ -14760,13 +14775,13 @@ function validateInstructionShape(instruction, path6, issues) {
14760
14775
  function validateTemplate(value, fields, issues) {
14761
14776
  if (!isPlainRecord(value)) {
14762
14777
  issues.push(issue2("config.a2uiTemplate", "INVALID_A2UI_TEMPLATE", "a2uiTemplate must be an object"));
14763
- return;
14778
+ return void 0;
14764
14779
  }
14765
14780
  exactKeys(value, ["argsSchema", "content"], "config.a2uiTemplate", issues);
14766
14781
  validateLooseJsonSchema(value.argsSchema, "config.a2uiTemplate.argsSchema", issues);
14767
14782
  if (typeof value.content !== "string") {
14768
14783
  issues.push(issue2("config.a2uiTemplate.content", "INVALID_A2UI_CONTENT", "a2uiTemplate.content must be serialized A2UI JSON"));
14769
- return;
14784
+ return void 0;
14770
14785
  }
14771
14786
  try {
14772
14787
  const card = validateProtocol(JSON.parse(value.content), "config.a2uiTemplate.content", issues);
@@ -14774,9 +14789,11 @@ function validateTemplate(value, fields, issues) {
14774
14789
  const analysis = analyzeA2UIBindings(card);
14775
14790
  issues.push(...analysis.issues);
14776
14791
  }
14792
+ return card;
14777
14793
  } catch {
14778
14794
  issues.push(issue2("config.a2uiTemplate.content", "INVALID_A2UI_CONTENT", "a2uiTemplate.content must contain valid JSON"));
14779
14795
  }
14796
+ return void 0;
14780
14797
  }
14781
14798
  function validateLooseJsonSchema(value, path6, issues) {
14782
14799
  const schemaIssues = getJsonSchemaIssues2(value, path6, {
@@ -14785,7 +14802,7 @@ function validateLooseJsonSchema(value, path6, issues) {
14785
14802
  issues.push(...schemaIssues);
14786
14803
  return schemaIssues.length === 0;
14787
14804
  }
14788
- function validateResolverCoverage(fields, resolver, issues) {
14805
+ function validateResolverCoverage(fields, resolver, issues, card) {
14789
14806
  const businessFields = new Set(fields.filter((field) => field.source === "business").map((field) => field.fieldId));
14790
14807
  const bound = /* @__PURE__ */ new Set();
14791
14808
  resolver.outputBindings.forEach((binding, index2) => {
@@ -14794,7 +14811,8 @@ function validateResolverCoverage(fields, resolver, issues) {
14794
14811
  }
14795
14812
  bound.add(binding.fieldId);
14796
14813
  });
14797
- for (const fieldId of businessFields) {
14814
+ const requiredFields = card ? collectReferencedA2UICardBusinessFieldIds(card, fields.filter((field) => field.required)) : new Set(fields.filter((field) => field.source === "business" && field.required).map((field) => field.fieldId));
14815
+ for (const fieldId of requiredFields) {
14798
14816
  if (!bound.has(fieldId)) {
14799
14817
  issues.push(issue2("config.resolver.outputBindings", "CARD_BINDING_INCOMPLETE", `business field ${fieldId} is not bound`));
14800
14818
  }
@@ -14847,6 +14865,7 @@ var init_compiler = __esm({
14847
14865
  "../agent-a2ui-card-contract/dist/esm/compiler.js"() {
14848
14866
  "use strict";
14849
14867
  init_json2();
14868
+ init_binding_analyzer();
14850
14869
  init_validation();
14851
14870
  init_schema2();
14852
14871
  }
@@ -15070,6 +15089,25 @@ var init_template = __esm({
15070
15089
  }
15071
15090
  });
15072
15091
 
15092
+ // ../agent-a2ui-card-contract/dist/esm/authoring-model.js
15093
+ var init_authoring_model = __esm({
15094
+ "../agent-a2ui-card-contract/dist/esm/authoring-model.js"() {
15095
+ "use strict";
15096
+ init_binding_analyzer();
15097
+ init_json2();
15098
+ init_validation();
15099
+ }
15100
+ });
15101
+
15102
+ // ../agent-a2ui-card-contract/dist/esm/authoring-operation.js
15103
+ var init_authoring_operation = __esm({
15104
+ "../agent-a2ui-card-contract/dist/esm/authoring-operation.js"() {
15105
+ "use strict";
15106
+ init_authoring_model();
15107
+ init_json2();
15108
+ }
15109
+ });
15110
+
15073
15111
  // ../agent-a2ui-card-contract/dist/esm/index.js
15074
15112
  var init_esm4 = __esm({
15075
15113
  "../agent-a2ui-card-contract/dist/esm/index.js"() {
@@ -15087,6 +15125,8 @@ var init_esm4 = __esm({
15087
15125
  init_binding_context();
15088
15126
  init_preview_binding();
15089
15127
  init_template();
15128
+ init_authoring_model();
15129
+ init_authoring_operation();
15090
15130
  }
15091
15131
  });
15092
15132
 
@@ -15467,6 +15507,9 @@ function parseProxyArgs(args) {
15467
15507
  out.describe = args.describe;
15468
15508
  if (typeof args.search === "string")
15469
15509
  out.search = args.search;
15510
+ if (Array.isArray(args.searches)) {
15511
+ out.searches = args.searches.filter((query) => typeof query === "string").slice(0, MCP_BATCH_SEARCH_MAX_ITEMS);
15512
+ }
15470
15513
  if (typeof args.tool === "string")
15471
15514
  out.tool = args.tool;
15472
15515
  if (typeof args.server === "string")
@@ -15510,7 +15553,7 @@ function truncate(text, max2) {
15510
15553
  function isRecord2(value) {
15511
15554
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
15512
15555
  }
15513
- var MCP_PROXY_TOOL_NAME, McpProxyTool, MCP_PROXY_DESCRIPTION, MCP_PROXY_INPUT_SCHEMA;
15556
+ var MCP_PROXY_TOOL_NAME, McpProxyTool, MCP_BATCH_SEARCH_MAX_ITEMS, MCP_PROXY_DESCRIPTION, MCP_PROXY_INPUT_SCHEMA;
15514
15557
  var init_mcpProxyTool = __esm({
15515
15558
  "../linkque-agent-runtime/dist/esm/core/mcpProxyTool.js"() {
15516
15559
  "use strict";
@@ -15655,6 +15698,9 @@ var init_mcpProxyTool = __esm({
15655
15698
  if (params.describe !== void 0) {
15656
15699
  return this.executeDescribe(params.describe, params.server, signal);
15657
15700
  }
15701
+ if (params.searches !== void 0) {
15702
+ return this.executeBatchSearch(params.searches, params.server);
15703
+ }
15658
15704
  if (params.search !== void 0) {
15659
15705
  return this.executeSearch(params.search, params.server);
15660
15706
  }
@@ -15751,6 +15797,20 @@ ${formatSchema(tool.inputSchema, " ")}`);
15751
15797
  }
15752
15798
  return lines.join("\n").trim();
15753
15799
  }
15800
+ /** `mcp({ searches: [...] })`:一次连接元数据并按 query 分组执行多组搜索。 */
15801
+ async executeBatchSearch(queries, serverHint) {
15802
+ const normalized = [
15803
+ ...new Set(queries.map((query) => query.trim()).filter(Boolean))
15804
+ ].slice(0, MCP_BATCH_SEARCH_MAX_ITEMS);
15805
+ if (normalized.length === 0) {
15806
+ return "Batch search requires at least one non-empty query.";
15807
+ }
15808
+ const specs = serverHint ? this.specsMatching(serverHint) : this.specs;
15809
+ await Promise.all(specs.map((spec) => this.ensureEntry(spec.serverName)));
15810
+ const results = await Promise.all(normalized.map((query) => this.executeSearch(query, serverHint)));
15811
+ return results.map((result, index2) => `Query ${index2 + 1}: "${normalized[index2]}"
15812
+ ${result}`).join("\n\n");
15813
+ }
15754
15814
  /** `mcp({ describe: "tool" })`:输出工具所属 server + 参数 schema。 */
15755
15815
  async executeDescribe(toolName, serverHint, signal) {
15756
15816
  const found = await this.findTool(toolName, serverHint, signal);
@@ -15832,12 +15892,14 @@ ${formatSchema(tool.inputSchema)}`);
15832
15892
  return lines.join("\n").trim();
15833
15893
  }
15834
15894
  };
15895
+ MCP_BATCH_SEARCH_MAX_ITEMS = 5;
15835
15896
  MCP_PROXY_DESCRIPTION = [
15836
15897
  "MCP \u7F51\u5173:\u53D1\u73B0\u5E76\u8C03\u7528 MCP server \u63D0\u4F9B\u7684\u5DE5\u5177\u3002\u53EF\u7528\u52A8\u4F5C:",
15837
15898
  "- mcp({}) \u6216 mcp({ status: true }):\u67E5\u770B\u6240\u6709 server \u8FDE\u63A5\u72B6\u6001\u4E0E\u5DE5\u5177\u6570\u3002",
15838
15899
  '- mcp({ connect: "server" }):\u8FDE\u63A5\u5E76\u5237\u65B0\u67D0 server \u7684\u5DE5\u5177\u5217\u8868\u3002',
15839
15900
  '- mcp({ server: "name" }):\u5217\u51FA\u8BE5 server \u7684\u5DE5\u5177\u3002',
15840
15901
  '- mcp({ search: "\u5173\u952E\u8BCD" }):\u6309\u540D\u79F0/\u63CF\u8FF0\u6A21\u7CCA\u641C\u7D22\u5DE5\u5177(\u7A7A\u683C\u5206\u8BCD OR)\u3002',
15902
+ '- mcp({ searches: ["\u5173\u952E\u8BCD1", "\u5173\u952E\u8BCD2"] }):\u4E00\u6B21\u6267\u884C\u591A\u7EC4\u641C\u7D22\u5E76\u6309 query \u5206\u7EC4\u8FD4\u56DE(\u6700\u591A 5 \u7EC4)\u3002',
15841
15903
  '- mcp({ describe: "toolName" }):\u67E5\u770B\u67D0\u5DE5\u5177\u7684\u53C2\u6570 schema\u3002',
15842
15904
  '- mcp({ tool: "toolName", args: { ... } }):\u8C03\u7528\u67D0\u5DE5\u5177,args \u4E3A\u5BF9\u8C61\u3002',
15843
15905
  "\u53EF\u7528 server \u540D\u89C1 mcp({}) \u8F93\u51FA\u3002\u4EC5\u5728\u786E\u9700\u8C03\u7528 MCP \u5DE5\u5177\u65F6\u4F7F\u7528\u672C\u5DE5\u5177\u3002",
@@ -15860,6 +15922,13 @@ ${formatSchema(tool.inputSchema)}`);
15860
15922
  type: "string",
15861
15923
  description: "\u6309\u540D\u79F0/\u63CF\u8FF0\u6A21\u7CCA\u641C\u7D22\u5DE5\u5177(\u7A7A\u683C\u5206\u8BCD OR)"
15862
15924
  },
15925
+ searches: {
15926
+ type: "array",
15927
+ description: "\u6279\u91CF\u641C\u7D22\u5173\u952E\u8BCD\uFF1B\u4E00\u6B21\u63D0\u4EA4\u6240\u6709\u5019\u9009 query\uFF0C\u6309 query \u5206\u7EC4\u8FD4\u56DE",
15928
+ minItems: 1,
15929
+ maxItems: MCP_BATCH_SEARCH_MAX_ITEMS,
15930
+ items: { type: "string", minLength: 1 }
15931
+ },
15863
15932
  describe: { type: "string", description: "\u67E5\u770B\u67D0\u5DE5\u5177\u7684\u53C2\u6570 schema" },
15864
15933
  tool: { type: "string", description: "\u8981\u8C03\u7528\u7684\u5DE5\u5177\u540D(\u53EF\u914D\u5408 server \u6D88\u6B67)" },
15865
15934
  args: {
@@ -187319,8 +187388,74 @@ var init_dist4 = __esm({
187319
187388
  }
187320
187389
  });
187321
187390
 
187391
+ // ../linkque-agent-runtime/dist/esm/impl/agent/pi/llmRequestThrottle.js
187392
+ function delayWithSignal(delayMs, signal) {
187393
+ return new Promise((resolve, reject) => {
187394
+ if (signal?.aborted) {
187395
+ reject(signal.reason);
187396
+ return;
187397
+ }
187398
+ const timer = setTimeout(() => {
187399
+ signal?.removeEventListener("abort", onAbort);
187400
+ resolve();
187401
+ }, delayMs);
187402
+ const onAbort = () => {
187403
+ clearTimeout(timer);
187404
+ reject(signal?.reason);
187405
+ };
187406
+ signal?.addEventListener("abort", onAbort, { once: true });
187407
+ });
187408
+ }
187409
+ var DEFAULT_LLM_REQUEST_MIN_INTERVAL_MS, LlmRequestThrottle;
187410
+ var init_llmRequestThrottle = __esm({
187411
+ "../linkque-agent-runtime/dist/esm/impl/agent/pi/llmRequestThrottle.js"() {
187412
+ "use strict";
187413
+ DEFAULT_LLM_REQUEST_MIN_INTERVAL_MS = 1e3;
187414
+ LlmRequestThrottle = class {
187415
+ minIntervalMs;
187416
+ now;
187417
+ delay;
187418
+ onDelay;
187419
+ queue = Promise.resolve();
187420
+ nextRequestAt = 0;
187421
+ constructor(options = {}) {
187422
+ const configured = options.minIntervalMs ?? DEFAULT_LLM_REQUEST_MIN_INTERVAL_MS;
187423
+ this.minIntervalMs = Number.isFinite(configured) && configured > 0 ? Math.floor(configured) : 0;
187424
+ this.now = options.now ?? Date.now;
187425
+ this.delay = options.delay ?? delayWithSignal;
187426
+ this.onDelay = options.onDelay ?? (() => {
187427
+ });
187428
+ }
187429
+ /** 等到当前请求允许启动;取消信号会中断尚未开始的等待。 */
187430
+ waitForTurn(signal) {
187431
+ const scheduled = this.queue.then(async () => {
187432
+ signal?.throwIfAborted();
187433
+ const delayMs = Math.max(0, this.nextRequestAt - this.now());
187434
+ if (delayMs > 0) {
187435
+ this.onDelay(delayMs);
187436
+ await this.delay(delayMs, signal);
187437
+ }
187438
+ signal?.throwIfAborted();
187439
+ this.nextRequestAt = this.now() + this.minIntervalMs;
187440
+ });
187441
+ this.queue = scheduled.catch(() => void 0);
187442
+ return scheduled;
187443
+ }
187444
+ };
187445
+ }
187446
+ });
187447
+
187322
187448
  // ../linkque-agent-runtime/dist/esm/impl/agent/pi/createAgentSession.js
187323
187449
  async function createAgentSession(options) {
187450
+ const llmThrottle = new LlmRequestThrottle({
187451
+ minIntervalMs: options.llmRequestMinIntervalMs ?? DEFAULT_LLM_REQUEST_MIN_INTERVAL_MS,
187452
+ onDelay: (delayMs) => {
187453
+ try {
187454
+ options.debugLog?.(`[llm-throttle] wait ${delayMs}ms before next request`, EDebugLogScope.LLM);
187455
+ } catch {
187456
+ }
187457
+ }
187458
+ });
187324
187459
  const agent = new Agent({
187325
187460
  initialState: {
187326
187461
  model: options.model,
@@ -187340,28 +187475,30 @@ async function createAgentSession(options) {
187340
187475
  // 不 await/转换(否则破坏 stream)。
187341
187476
  streamFn: (model, context2, streamOptions) => {
187342
187477
  const logSink = options.debugLog;
187343
- if (!logSink) {
187344
- return options.models.streamSimple(model, context2, streamOptions);
187345
- }
187346
187478
  const opts = { ...streamOptions };
187347
- const baseUrl = model.baseUrl ?? "<unknown>";
187348
- const prevOnPayload = opts.onPayload;
187349
- opts.onPayload = async (payload, m2) => {
187350
- await prevOnPayload?.(payload, m2);
187351
- try {
187352
- logSink(formatHttpLogLine("llm", "req", `POST ${baseUrl} model=${m2.id} payload=${summarizeBody(safeStringifyPayload(payload))}`), EDebugLogScope.LLM);
187353
- } catch {
187354
- }
187355
- };
187356
- const prevOnResponse = opts.onResponse;
187357
- opts.onResponse = async (response, m2) => {
187358
- await prevOnResponse?.(response, m2);
187359
- try {
187360
- logSink(formatHttpLogLine("llm", "resp", `POST ${baseUrl} model=${m2.id} ${response.status} headers=${redactHeaders(response.headers)}`), EDebugLogScope.LLM);
187361
- } catch {
187362
- }
187363
- };
187364
- return options.models.streamSimple(model, context2, opts);
187479
+ if (logSink) {
187480
+ const baseUrl = model.baseUrl ?? "<unknown>";
187481
+ const prevOnPayload = opts.onPayload;
187482
+ opts.onPayload = async (payload, m2) => {
187483
+ await prevOnPayload?.(payload, m2);
187484
+ try {
187485
+ logSink(formatHttpLogLine("llm", "req", `POST ${baseUrl} model=${m2.id} payload=${summarizeBody(safeStringifyPayload(payload))}`), EDebugLogScope.LLM);
187486
+ } catch {
187487
+ }
187488
+ };
187489
+ const prevOnResponse = opts.onResponse;
187490
+ opts.onResponse = async (response, m2) => {
187491
+ await prevOnResponse?.(response, m2);
187492
+ try {
187493
+ logSink(formatHttpLogLine("llm", "resp", `POST ${baseUrl} model=${m2.id} ${response.status} headers=${redactHeaders(response.headers)}`), EDebugLogScope.LLM);
187494
+ } catch {
187495
+ }
187496
+ };
187497
+ }
187498
+ return lazyStream(model, async () => {
187499
+ await llmThrottle.waitForTurn(opts.signal);
187500
+ return options.models.streamSimple(model, context2, opts);
187501
+ });
187365
187502
  },
187366
187503
  getApiKey: options.getApiKey
187367
187504
  });
@@ -187451,9 +187588,11 @@ var init_createAgentSession = __esm({
187451
187588
  "../linkque-agent-runtime/dist/esm/impl/agent/pi/createAgentSession.js"() {
187452
187589
  "use strict";
187453
187590
  init_dist4();
187591
+ init_dist3();
187454
187592
  init_types2();
187455
187593
  init_cardTools();
187456
187594
  init_httpLoggingFetch();
187595
+ init_llmRequestThrottle();
187457
187596
  }
187458
187597
  });
187459
187598