linkque-cli-v2 1.1.4 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/linkquejs.js +476 -51
- package/package.json +1 -1
- package/vendor/linkque-agent-appwrite-integrate/dist/esm/{chunk-YAKPGLYU.js → chunk-IMZDZMKV.js} +26 -9
- package/vendor/linkque-agent-appwrite-integrate/dist/esm/runtime/handler/chat.js +1 -1
- package/vendor/linkque-agent-appwrite-integrate/dist/esm/runtime/protocol.js +1 -1
- package/worker.js +49 -9
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
|
-
|
|
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
|
-
|
|
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
|
|
27082
|
-
if (
|
|
27083
|
-
throw new A2UICardCompileError("CARD_BINDING_INCOMPLETE", `
|
|
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
|
|
27203
|
-
if (
|
|
27204
|
-
throw new A2UICardCompileError("CARD_BINDING_INCOMPLETE", `
|
|
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 = {
|
|
@@ -27404,9 +27426,6 @@ function createA2UICardDraftStructureChecksum(draft) {
|
|
|
27404
27426
|
delete cloned.manifest.bindings;
|
|
27405
27427
|
return sha256Hex(stableJsonStringify(cloned));
|
|
27406
27428
|
}
|
|
27407
|
-
function createA2UICardMcpConfigChecksum(resources) {
|
|
27408
|
-
return sha256Hex(stableJsonStringify(resources));
|
|
27409
|
-
}
|
|
27410
27429
|
function createA2UICardRevision(draftChecksum2, bindings) {
|
|
27411
27430
|
const digest = sha256Hex(`${draftChecksum2}
|
|
27412
27431
|
${stableJsonStringify(bindings)}`);
|
|
@@ -27485,6 +27504,393 @@ var SHA256_CONSTANTS = [
|
|
|
27485
27504
|
3329325298
|
|
27486
27505
|
];
|
|
27487
27506
|
|
|
27507
|
+
// ../agent-a2ui-card-contract/dist/esm/authoring-model.js
|
|
27508
|
+
var INTERNAL_KEYS = /* @__PURE__ */ new Set([
|
|
27509
|
+
"__proto__",
|
|
27510
|
+
"constructor",
|
|
27511
|
+
"prototype",
|
|
27512
|
+
"id",
|
|
27513
|
+
"component",
|
|
27514
|
+
"surfaceId",
|
|
27515
|
+
"version",
|
|
27516
|
+
"child",
|
|
27517
|
+
"children"
|
|
27518
|
+
]);
|
|
27519
|
+
var MERCHANT_CONTENT_KEYS = /* @__PURE__ */ new Set([
|
|
27520
|
+
"caption",
|
|
27521
|
+
"description",
|
|
27522
|
+
"label",
|
|
27523
|
+
"placeholder",
|
|
27524
|
+
"subtitle",
|
|
27525
|
+
"text",
|
|
27526
|
+
"title"
|
|
27527
|
+
]);
|
|
27528
|
+
var DEFAULT_AUTHORING_PROJECTION = {
|
|
27529
|
+
directTargets: "content"
|
|
27530
|
+
};
|
|
27531
|
+
var COMPONENT_AUTHORING_PROJECTIONS = {
|
|
27532
|
+
Image: {
|
|
27533
|
+
directTargets: "image-source",
|
|
27534
|
+
fieldProperties: ["src"],
|
|
27535
|
+
groupLabel: "\u56FE\u7247"
|
|
27536
|
+
}
|
|
27537
|
+
};
|
|
27538
|
+
function extractA2UICardAuthoringModel(bundle, options = {}) {
|
|
27539
|
+
const analysis = analyzeA2UIBindings(bundle.card);
|
|
27540
|
+
const bindingByField = new Map((bundle.manifest.bindings ?? []).map((binding) => [
|
|
27541
|
+
binding.fieldId,
|
|
27542
|
+
binding
|
|
27543
|
+
]));
|
|
27544
|
+
const fields = bundle.manifest.fields.filter((field) => field.source === "business");
|
|
27545
|
+
const registered = options.registeredComponents ? new Set(options.registeredComponents) : void 0;
|
|
27546
|
+
const occurrencesByComponent = groupBindingOccurrences(analysis.occurrences);
|
|
27547
|
+
const allFieldOccurrenceTargets = [];
|
|
27548
|
+
const groups = [];
|
|
27549
|
+
let order = 0;
|
|
27550
|
+
for (const { surfaceId, component } of orderedComponents(bundle)) {
|
|
27551
|
+
const occurrenceId = createA2UICardAuthoringOccurrenceId(surfaceId, component.id);
|
|
27552
|
+
const targets = [];
|
|
27553
|
+
if (!registered || registered.has(component.component)) {
|
|
27554
|
+
const projection = componentAuthoringProjection(component);
|
|
27555
|
+
const componentOccurrences = occurrencesByComponent.get(componentKey(surfaceId, component.id)) ?? [];
|
|
27556
|
+
discoverComponentTargets(component, occurrenceId, projection, targets);
|
|
27557
|
+
allFieldOccurrenceTargets.push(...fieldTargets(component, occurrenceId, fields, componentOccurrences, false));
|
|
27558
|
+
targets.push(...fieldTargets(component, occurrenceId, fields, componentOccurrences, true));
|
|
27559
|
+
targets.push(...actionTargets(component, occurrenceId));
|
|
27560
|
+
}
|
|
27561
|
+
if (targets.length === 0) {
|
|
27562
|
+
targets.push({
|
|
27563
|
+
kind: "agent-only",
|
|
27564
|
+
targetId: createA2UICardAuthoringTargetId(occurrenceId, "agent-only"),
|
|
27565
|
+
occurrenceId,
|
|
27566
|
+
label: "\u901A\u8FC7 Coding Agent \u4FEE\u6539",
|
|
27567
|
+
reason: registered && !registered.has(component.component) ? "\u7EC4\u4EF6\u672A\u5728\u5F53\u524D Catalog \u6CE8\u518C" : "\u6CA1\u6709\u53EF\u5B89\u5168\u76F4\u63A5\u7F16\u8F91\u7684\u4E1A\u52A1\u5B57\u6BB5"
|
|
27568
|
+
});
|
|
27569
|
+
}
|
|
27570
|
+
groups.push({
|
|
27571
|
+
occurrenceId,
|
|
27572
|
+
surfaceId,
|
|
27573
|
+
componentId: component.id,
|
|
27574
|
+
componentName: component.component,
|
|
27575
|
+
order: order++,
|
|
27576
|
+
label: componentAuthoringProjection(component).groupLabel ?? componentLabel(component),
|
|
27577
|
+
targets: deduplicateTargets(targets),
|
|
27578
|
+
agentOnly: targets.every((target) => target.kind === "agent-only")
|
|
27579
|
+
});
|
|
27580
|
+
}
|
|
27581
|
+
const fieldStates = fields.map((field) => {
|
|
27582
|
+
const occurrences = allFieldOccurrenceTargets.filter((target) => target.fieldId === field.fieldId);
|
|
27583
|
+
const binding = bindingByField.get(field.fieldId);
|
|
27584
|
+
return {
|
|
27585
|
+
field,
|
|
27586
|
+
...binding ? { binding: cloneBinding(binding) } : {},
|
|
27587
|
+
occurrences,
|
|
27588
|
+
usageCount: new Set(occurrences.map((target) => `${target.occurrenceId}\0${target.propertyPath}`)).size,
|
|
27589
|
+
status: occurrences.length === 0 ? "unused" : binding ? "bound" : field.required ? "unbound-required" : "unbound-optional"
|
|
27590
|
+
};
|
|
27591
|
+
});
|
|
27592
|
+
const diagnostics = getA2UICardAuthoringDiagnostics(bundle, {
|
|
27593
|
+
groups,
|
|
27594
|
+
fields: fieldStates
|
|
27595
|
+
});
|
|
27596
|
+
return {
|
|
27597
|
+
draftId: bundle.manifest.draftId,
|
|
27598
|
+
resourceId: bundle.manifest.resourceId,
|
|
27599
|
+
groups,
|
|
27600
|
+
fields: fieldStates,
|
|
27601
|
+
diagnostics
|
|
27602
|
+
};
|
|
27603
|
+
}
|
|
27604
|
+
function componentAuthoringProjection(component) {
|
|
27605
|
+
return COMPONENT_AUTHORING_PROJECTIONS[component.component] ?? DEFAULT_AUTHORING_PROJECTION;
|
|
27606
|
+
}
|
|
27607
|
+
function discoverComponentTargets(component, occurrenceId, projection, targets) {
|
|
27608
|
+
if (projection.directTargets === "content") {
|
|
27609
|
+
discoverTargets(component, occurrenceId, "", targets);
|
|
27610
|
+
return;
|
|
27611
|
+
}
|
|
27612
|
+
if (typeof component.src !== "string")
|
|
27613
|
+
return;
|
|
27614
|
+
targets.push({
|
|
27615
|
+
kind: "image",
|
|
27616
|
+
targetId: createA2UICardAuthoringTargetId(occurrenceId, "src"),
|
|
27617
|
+
occurrenceId,
|
|
27618
|
+
propertyPath: "src",
|
|
27619
|
+
label: "\u56FE\u7247\u5730\u5740",
|
|
27620
|
+
value: component.src,
|
|
27621
|
+
role: "src"
|
|
27622
|
+
});
|
|
27623
|
+
}
|
|
27624
|
+
function getA2UICardAuthoringDiagnostics(bundle, partial) {
|
|
27625
|
+
const diagnostics = getA2UICardDraftBundleIssues(bundle).map((entry) => ({
|
|
27626
|
+
...entry,
|
|
27627
|
+
severity: "hard-error"
|
|
27628
|
+
}));
|
|
27629
|
+
const model = partial ?? extractA2UICardAuthoringModel(bundle);
|
|
27630
|
+
for (const field of model.fields) {
|
|
27631
|
+
if (field.status === "unbound-required") {
|
|
27632
|
+
diagnostics.push({
|
|
27633
|
+
code: "REQUIRED_BINDING_MISSING",
|
|
27634
|
+
path: `manifest.fields.${field.field.fieldId}`,
|
|
27635
|
+
message: `\u5FC5\u586B\u5B57\u6BB5\u201C${field.field.label}\u201D\u5C1A\u672A\u7ED1\u5B9A`,
|
|
27636
|
+
severity: "hard-error",
|
|
27637
|
+
fieldId: field.field.fieldId
|
|
27638
|
+
});
|
|
27639
|
+
}
|
|
27640
|
+
}
|
|
27641
|
+
for (const group of model.groups) {
|
|
27642
|
+
const component = findComponent(bundle, group.surfaceId, group.componentId);
|
|
27643
|
+
const action = isPlainRecord(component?.action) ? component.action : void 0;
|
|
27644
|
+
const client = action && isPlainRecord(action.client) ? action.client : void 0;
|
|
27645
|
+
if (client?.name === "ui.page.open") {
|
|
27646
|
+
const context = isPlainRecord(client.context) ? client.context : void 0;
|
|
27647
|
+
if (typeof context?.url === "string" && !isSafePageUrl(context.url)) {
|
|
27648
|
+
diagnostics.push({
|
|
27649
|
+
code: "UNSAFE_PAGE_URL",
|
|
27650
|
+
path: `${group.occurrenceId}.action.client.context.url`,
|
|
27651
|
+
message: "\u9875\u9762\u5730\u5740\u5FC5\u987B\u662F\u5B89\u5168\u7684 http(s) \u5730\u5740\u6216\u7AD9\u5185\u7EDD\u5BF9\u8DEF\u5F84",
|
|
27652
|
+
severity: "hard-error",
|
|
27653
|
+
occurrenceId: group.occurrenceId
|
|
27654
|
+
});
|
|
27655
|
+
}
|
|
27656
|
+
} else if (client && typeof client.name === "string" && !["ui.overlay.close", "ui.surface.open"].includes(client.name)) {
|
|
27657
|
+
diagnostics.push({
|
|
27658
|
+
code: "UNREGISTERED_CLIENT_ACTION",
|
|
27659
|
+
path: `${group.occurrenceId}.action.client.name`,
|
|
27660
|
+
message: `\u672A\u6CE8\u518C\u7684 Client Action\uFF1A${client.name}`,
|
|
27661
|
+
severity: "hard-error",
|
|
27662
|
+
occurrenceId: group.occurrenceId
|
|
27663
|
+
});
|
|
27664
|
+
}
|
|
27665
|
+
}
|
|
27666
|
+
return deduplicateDiagnostics(diagnostics);
|
|
27667
|
+
}
|
|
27668
|
+
function validateA2UICardForPublish(bundle) {
|
|
27669
|
+
return getA2UICardAuthoringDiagnostics(bundle).filter((diagnostic) => diagnostic.severity === "hard-error");
|
|
27670
|
+
}
|
|
27671
|
+
function createA2UICardAuthoringOccurrenceId(surfaceId, componentId) {
|
|
27672
|
+
return `${encodeURIComponent(surfaceId)}:${encodeURIComponent(componentId)}`;
|
|
27673
|
+
}
|
|
27674
|
+
function createA2UICardAuthoringTargetId(occurrenceId, propertyPath) {
|
|
27675
|
+
return `${occurrenceId}:${encodeURIComponent(propertyPath)}`;
|
|
27676
|
+
}
|
|
27677
|
+
function isSafePageUrl(url) {
|
|
27678
|
+
const trimmed = url.trim();
|
|
27679
|
+
if (trimmed.length === 0 || trimmed.length > 2e3)
|
|
27680
|
+
return false;
|
|
27681
|
+
const token = /\{\{([^{}]+)\}\}/gu;
|
|
27682
|
+
let tokenCount = 0;
|
|
27683
|
+
for (const match of trimmed.matchAll(token)) {
|
|
27684
|
+
tokenCount++;
|
|
27685
|
+
if (tokenCount > 32)
|
|
27686
|
+
return false;
|
|
27687
|
+
const path22 = match[1]?.trim() ?? "";
|
|
27688
|
+
if (!(path22 === "/" || path22.startsWith("/") || path22.startsWith("./")) || path22.split("/").some((part) => ["..", "__proto__", "constructor", "prototype"].includes(part))) {
|
|
27689
|
+
return false;
|
|
27690
|
+
}
|
|
27691
|
+
}
|
|
27692
|
+
const candidate = trimmed.replace(token, "value");
|
|
27693
|
+
if (candidate.includes("{{") || candidate.includes("}}"))
|
|
27694
|
+
return false;
|
|
27695
|
+
try {
|
|
27696
|
+
return ["https:", "alipays:"].includes(new URL(candidate).protocol);
|
|
27697
|
+
} catch {
|
|
27698
|
+
return false;
|
|
27699
|
+
}
|
|
27700
|
+
}
|
|
27701
|
+
function orderedComponents(bundle) {
|
|
27702
|
+
const result = [];
|
|
27703
|
+
for (const message of bundle.card) {
|
|
27704
|
+
for (const instruction of message.datas) {
|
|
27705
|
+
if (!("updateComponents" in instruction))
|
|
27706
|
+
continue;
|
|
27707
|
+
for (const component of instruction.updateComponents.components) {
|
|
27708
|
+
result.push({
|
|
27709
|
+
surfaceId: instruction.updateComponents.surfaceId,
|
|
27710
|
+
component
|
|
27711
|
+
});
|
|
27712
|
+
}
|
|
27713
|
+
}
|
|
27714
|
+
}
|
|
27715
|
+
return result;
|
|
27716
|
+
}
|
|
27717
|
+
function discoverTargets(value, occurrenceId, propertyPath, targets) {
|
|
27718
|
+
if (Array.isArray(value)) {
|
|
27719
|
+
value.forEach((entry, index) => discoverTargets(entry, occurrenceId, appendPath(propertyPath, String(index)), targets));
|
|
27720
|
+
return;
|
|
27721
|
+
}
|
|
27722
|
+
if (!isPlainRecord(value))
|
|
27723
|
+
return;
|
|
27724
|
+
if (typeof value.path === "string")
|
|
27725
|
+
return;
|
|
27726
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
27727
|
+
const nextPath = appendPath(propertyPath, key);
|
|
27728
|
+
if (INTERNAL_KEYS.has(key) || key === "action")
|
|
27729
|
+
continue;
|
|
27730
|
+
if (Array.isArray(entry) || isPlainRecord(entry)) {
|
|
27731
|
+
discoverTargets(entry, occurrenceId, nextPath, targets);
|
|
27732
|
+
continue;
|
|
27733
|
+
}
|
|
27734
|
+
if (!isJsonValue(entry))
|
|
27735
|
+
continue;
|
|
27736
|
+
if (typeof entry !== "string" || !MERCHANT_CONTENT_KEYS.has(key))
|
|
27737
|
+
continue;
|
|
27738
|
+
targets.push({
|
|
27739
|
+
kind: "literal",
|
|
27740
|
+
targetId: createA2UICardAuthoringTargetId(occurrenceId, nextPath),
|
|
27741
|
+
occurrenceId,
|
|
27742
|
+
propertyPath: nextPath,
|
|
27743
|
+
label: propertyLabel(nextPath),
|
|
27744
|
+
value: entry
|
|
27745
|
+
});
|
|
27746
|
+
}
|
|
27747
|
+
}
|
|
27748
|
+
function actionTargets(component, occurrenceId) {
|
|
27749
|
+
if (!isPlainRecord(component.action))
|
|
27750
|
+
return [];
|
|
27751
|
+
const action = component.action;
|
|
27752
|
+
const event = isPlainRecord(action.event) ? action.event : void 0;
|
|
27753
|
+
if (event) {
|
|
27754
|
+
const message = event["x2-user-message"];
|
|
27755
|
+
if (typeof message === "string" && typeof event.name === "string") {
|
|
27756
|
+
return [
|
|
27757
|
+
{
|
|
27758
|
+
kind: "agent-event",
|
|
27759
|
+
targetId: createA2UICardAuthoringTargetId(occurrenceId, "action"),
|
|
27760
|
+
occurrenceId,
|
|
27761
|
+
propertyPath: "action",
|
|
27762
|
+
label: "\u70B9\u51FB\u540E",
|
|
27763
|
+
message,
|
|
27764
|
+
eventName: event.name,
|
|
27765
|
+
hasContext: isPlainRecord(event.context)
|
|
27766
|
+
}
|
|
27767
|
+
];
|
|
27768
|
+
}
|
|
27769
|
+
return [agentOnlyAction(occurrenceId, "\u52A8\u6001\u6216\u590D\u6742\u4E8B\u4EF6\u901A\u8FC7\u667A\u80FD\u4F53\u4FEE\u6539")];
|
|
27770
|
+
}
|
|
27771
|
+
const client = isPlainRecord(action.client) ? action.client : void 0;
|
|
27772
|
+
if (client?.name === "ui.page.open") {
|
|
27773
|
+
const context = isPlainRecord(client.context) ? client.context : void 0;
|
|
27774
|
+
const url = context?.url;
|
|
27775
|
+
return [
|
|
27776
|
+
{
|
|
27777
|
+
kind: "page-open",
|
|
27778
|
+
targetId: createA2UICardAuthoringTargetId(occurrenceId, "action"),
|
|
27779
|
+
occurrenceId,
|
|
27780
|
+
propertyPath: "action",
|
|
27781
|
+
label: "\u6253\u5F00\u9875\u9762",
|
|
27782
|
+
...typeof url === "string" ? { url } : {},
|
|
27783
|
+
dynamic: isPlainRecord(url) && typeof url.path === "string"
|
|
27784
|
+
}
|
|
27785
|
+
];
|
|
27786
|
+
}
|
|
27787
|
+
return [agentOnlyAction(occurrenceId, "\u8BE5\u884C\u4E3A\u53EA\u80FD\u901A\u8FC7 Coding Agent \u4FEE\u6539")];
|
|
27788
|
+
}
|
|
27789
|
+
function fieldTargets(component, occurrenceId, fields, occurrences, projectedOnly) {
|
|
27790
|
+
const projection = componentAuthoringProjection(component);
|
|
27791
|
+
const ordered = [...fields].sort((left, right) => right.path.length - left.path.length);
|
|
27792
|
+
return occurrences.flatMap((occurrence) => {
|
|
27793
|
+
if (projectedOnly && !isProjectedFieldOccurrence(occurrence.propertyPath, projection)) {
|
|
27794
|
+
return [];
|
|
27795
|
+
}
|
|
27796
|
+
const field = ordered.find((candidate) => occurrence.canonicalPath === candidate.path || occurrence.canonicalPath.startsWith(`${candidate.path}/*/`) || occurrence.canonicalPath.startsWith(`${candidate.path}/`));
|
|
27797
|
+
if (!field)
|
|
27798
|
+
return [];
|
|
27799
|
+
const suffix = occurrence.canonicalPath.slice(field.path.length).replace(/^\/\*/u, "");
|
|
27800
|
+
const targetPath = suffix ? suffix.startsWith("/") ? suffix : `/${suffix}` : void 0;
|
|
27801
|
+
return [
|
|
27802
|
+
{
|
|
27803
|
+
kind: "field-occurrence",
|
|
27804
|
+
targetId: createA2UICardAuthoringTargetId(occurrenceId, occurrence.propertyPath),
|
|
27805
|
+
occurrenceId,
|
|
27806
|
+
propertyPath: occurrence.propertyPath,
|
|
27807
|
+
label: fieldOccurrenceLabel(targetPath, occurrence.propertyPath),
|
|
27808
|
+
fieldId: field.fieldId,
|
|
27809
|
+
...targetPath ? { targetPath } : {}
|
|
27810
|
+
}
|
|
27811
|
+
];
|
|
27812
|
+
});
|
|
27813
|
+
}
|
|
27814
|
+
function isProjectedFieldOccurrence(propertyPath, projection) {
|
|
27815
|
+
if (propertyPath === "action" || propertyPath.startsWith("action.")) {
|
|
27816
|
+
return false;
|
|
27817
|
+
}
|
|
27818
|
+
return projection.fieldProperties === void 0 || projection.fieldProperties.includes(propertyPath);
|
|
27819
|
+
}
|
|
27820
|
+
function fieldOccurrenceLabel(targetPath, propertyPath) {
|
|
27821
|
+
if (!targetPath)
|
|
27822
|
+
return propertyLabel(propertyPath);
|
|
27823
|
+
const segment = targetPath.split("/").filter(Boolean).at(-1);
|
|
27824
|
+
return segment ? decodeJsonPointerSegment(segment) : propertyLabel(propertyPath);
|
|
27825
|
+
}
|
|
27826
|
+
function decodeJsonPointerSegment(segment) {
|
|
27827
|
+
return segment.replace(/~1/gu, "/").replace(/~0/gu, "~");
|
|
27828
|
+
}
|
|
27829
|
+
function groupBindingOccurrences(occurrences) {
|
|
27830
|
+
const result = /* @__PURE__ */ new Map();
|
|
27831
|
+
for (const occurrence of occurrences) {
|
|
27832
|
+
if (!occurrence.surfaceId)
|
|
27833
|
+
continue;
|
|
27834
|
+
const key = componentKey(occurrence.surfaceId, occurrence.componentId);
|
|
27835
|
+
const entries = result.get(key) ?? [];
|
|
27836
|
+
entries.push(occurrence);
|
|
27837
|
+
result.set(key, entries);
|
|
27838
|
+
}
|
|
27839
|
+
return result;
|
|
27840
|
+
}
|
|
27841
|
+
function findComponent(bundle, surfaceId, componentId) {
|
|
27842
|
+
return orderedComponents(bundle).find((entry) => entry.surfaceId === surfaceId && entry.component.id === componentId)?.component;
|
|
27843
|
+
}
|
|
27844
|
+
function agentOnlyAction(occurrenceId, reason) {
|
|
27845
|
+
return {
|
|
27846
|
+
kind: "agent-only",
|
|
27847
|
+
targetId: createA2UICardAuthoringTargetId(occurrenceId, "action"),
|
|
27848
|
+
occurrenceId,
|
|
27849
|
+
propertyPath: "action",
|
|
27850
|
+
label: "\u901A\u8FC7 Coding Agent \u4FEE\u6539\u884C\u4E3A",
|
|
27851
|
+
reason
|
|
27852
|
+
};
|
|
27853
|
+
}
|
|
27854
|
+
function componentLabel(component) {
|
|
27855
|
+
const candidate = component.label ?? component.title ?? component.text;
|
|
27856
|
+
return typeof candidate === "string" && candidate.trim() ? candidate : component.component;
|
|
27857
|
+
}
|
|
27858
|
+
function propertyLabel(propertyPath) {
|
|
27859
|
+
const key = propertyPath.split(".").at(-1) ?? propertyPath;
|
|
27860
|
+
const labels = {
|
|
27861
|
+
text: "\u6587\u6848",
|
|
27862
|
+
title: "\u6807\u9898",
|
|
27863
|
+
subtitle: "\u526F\u6807\u9898",
|
|
27864
|
+
label: "\u6807\u7B7E",
|
|
27865
|
+
description: "\u8BF4\u660E",
|
|
27866
|
+
value: "\u5185\u5BB9",
|
|
27867
|
+
alt: "\u56FE\u7247\u8BF4\u660E"
|
|
27868
|
+
};
|
|
27869
|
+
return labels[key] ?? key;
|
|
27870
|
+
}
|
|
27871
|
+
function appendPath(base, segment) {
|
|
27872
|
+
return base ? `${base}.${segment}` : segment;
|
|
27873
|
+
}
|
|
27874
|
+
function componentKey(surfaceId, componentId) {
|
|
27875
|
+
return `${surfaceId}\0${componentId}`;
|
|
27876
|
+
}
|
|
27877
|
+
function deduplicateTargets(targets) {
|
|
27878
|
+
return [
|
|
27879
|
+
...new Map(targets.map((target) => [target.targetId, target])).values()
|
|
27880
|
+
];
|
|
27881
|
+
}
|
|
27882
|
+
function deduplicateDiagnostics(diagnostics) {
|
|
27883
|
+
return [
|
|
27884
|
+
...new Map(diagnostics.map((entry) => [
|
|
27885
|
+
`${entry.code}\0${entry.path}\0${entry.fieldId ?? ""}`,
|
|
27886
|
+
entry
|
|
27887
|
+
])).values()
|
|
27888
|
+
];
|
|
27889
|
+
}
|
|
27890
|
+
function cloneBinding(binding) {
|
|
27891
|
+
return JSON.parse(JSON.stringify(binding));
|
|
27892
|
+
}
|
|
27893
|
+
|
|
27488
27894
|
// src/commands/card/index.ts
|
|
27489
27895
|
var DRAFT_ROOT = ".card-drafts";
|
|
27490
27896
|
var AGENT_CONFIG_PATH = "agent_config.json";
|
|
@@ -27614,36 +28020,20 @@ async function validateCardBindingsFromDisk(cwd, draftId, fieldId) {
|
|
|
27614
28020
|
const directory = draftDirectory(cwd, draftId);
|
|
27615
28021
|
const [bundle, contextValue, configValue] = await Promise.all([
|
|
27616
28022
|
readBundle(directory, draftId),
|
|
27617
|
-
|
|
28023
|
+
readOptionalJson(import_path22.default.join(directory, "binding-context.json")),
|
|
27618
28024
|
readRequiredJson(import_path22.default.join(cwd, AGENT_CONFIG_PATH))
|
|
27619
28025
|
]);
|
|
27620
|
-
const
|
|
27621
|
-
if (!contextResult.success) {
|
|
27622
|
-
throw new LinkqueCliError(
|
|
27623
|
-
"CARD_BINDING_CONTEXT_INVALID",
|
|
27624
|
-
contextResult.issues.map((entry) => entry.message).join("; ")
|
|
27625
|
-
);
|
|
27626
|
-
}
|
|
27627
|
-
const context = contextResult.data;
|
|
28026
|
+
const context = parseOptionalBindingContext(contextValue);
|
|
27628
28027
|
const draftStructureChecksum = createA2UICardDraftStructureChecksum(bundle);
|
|
27629
28028
|
const config2 = parseAgentConfig(configValue);
|
|
27630
28029
|
const mcpResources = normalizedMcpResources(config2);
|
|
27631
|
-
|
|
27632
|
-
|
|
27633
|
-
"CARD_BINDING_CONTEXT_STALE",
|
|
27634
|
-
"MCP \u914D\u7F6E\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u53D1\u8D77 AI \u8F85\u52A9\u7ED1\u5B9A"
|
|
27635
|
-
);
|
|
27636
|
-
}
|
|
27637
|
-
const issues = validateA2UICardBindings(
|
|
27638
|
-
{
|
|
27639
|
-
draft: bundle,
|
|
27640
|
-
context,
|
|
27641
|
-
mountedMcpResourceIds: new Set(
|
|
27642
|
-
mcpResources.map((resource) => String(resource.resourceId))
|
|
27643
|
-
)
|
|
27644
|
-
},
|
|
27645
|
-
fieldId ? { fieldIds: /* @__PURE__ */ new Set([fieldId]) } : void 0
|
|
28030
|
+
const mountedMcpResourceIds = new Set(
|
|
28031
|
+
mcpResources.map((resource) => String(resource.resourceId))
|
|
27646
28032
|
);
|
|
28033
|
+
const issues = context ? validateA2UICardBindings(
|
|
28034
|
+
{ draft: bundle, context, mountedMcpResourceIds },
|
|
28035
|
+
fieldId ? { fieldIds: /* @__PURE__ */ new Set([fieldId]) } : void 0
|
|
28036
|
+
) : validateBindingsWithoutContext(bundle, mountedMcpResourceIds, fieldId);
|
|
27647
28037
|
if (issues.length > 0) {
|
|
27648
28038
|
throw new LinkqueCliError(
|
|
27649
28039
|
"CARD_BINDING_VALIDATION_FAILED",
|
|
@@ -27674,15 +28064,9 @@ async function finalizeCardWhileLocked(cwd, draftId, expectedDraftChecksum) {
|
|
|
27674
28064
|
}
|
|
27675
28065
|
const directory = draftDirectory(cwd, draftId);
|
|
27676
28066
|
const bundle = await readBundle(directory, draftId);
|
|
27677
|
-
const
|
|
27678
|
-
await
|
|
28067
|
+
const context = parseOptionalBindingContext(
|
|
28068
|
+
await readOptionalJson(import_path22.default.join(directory, "binding-context.json"))
|
|
27679
28069
|
);
|
|
27680
|
-
if (!contextResult.success) {
|
|
27681
|
-
throw new LinkqueCliError(
|
|
27682
|
-
"CARD_BINDING_CONTEXT_INVALID",
|
|
27683
|
-
contextResult.issues.map((entry) => entry.message).join("; ")
|
|
27684
|
-
);
|
|
27685
|
-
}
|
|
27686
28070
|
const configPath = import_path22.default.join(cwd, AGENT_CONFIG_PATH);
|
|
27687
28071
|
const oldConfigBytes = await (0, import_promises16.readFile)(configPath);
|
|
27688
28072
|
const config2 = parseAgentConfig(
|
|
@@ -27716,7 +28100,7 @@ async function finalizeCardWhileLocked(cwd, draftId, expectedDraftChecksum) {
|
|
|
27716
28100
|
// V3,让 Agent 直接按真实 MCP inputSchema 决定参数;不再把 presentation input
|
|
27717
28101
|
// 或 inputBindings 固化进 CARD。
|
|
27718
28102
|
...bindings.length > 0 ? { targetSchemaVersion: "3" } : {},
|
|
27719
|
-
tools:
|
|
28103
|
+
tools: (context?.candidates ?? []).flatMap(
|
|
27720
28104
|
(candidate) => candidate.status === "ready" ? [candidate.tool] : []
|
|
27721
28105
|
)
|
|
27722
28106
|
});
|
|
@@ -28043,6 +28427,47 @@ function normalizedMcpResources(config2) {
|
|
|
28043
28427
|
(left, right) => stableJsonStringify(left).localeCompare(stableJsonStringify(right))
|
|
28044
28428
|
);
|
|
28045
28429
|
}
|
|
28430
|
+
function parseOptionalBindingContext(value) {
|
|
28431
|
+
if (value === void 0) return void 0;
|
|
28432
|
+
const result = parseA2UICardBindingContext(value);
|
|
28433
|
+
if (!result.success) {
|
|
28434
|
+
throw new LinkqueCliError(
|
|
28435
|
+
"CARD_BINDING_CONTEXT_INVALID",
|
|
28436
|
+
result.issues.map((entry) => entry.message).join("; ")
|
|
28437
|
+
);
|
|
28438
|
+
}
|
|
28439
|
+
return result.data;
|
|
28440
|
+
}
|
|
28441
|
+
function validateBindingsWithoutContext(bundle, mountedMcpResourceIds, fieldId) {
|
|
28442
|
+
const selectedFields = fieldId ? /* @__PURE__ */ new Set([fieldId]) : void 0;
|
|
28443
|
+
const bindings = (bundle.manifest.bindings ?? []).filter(
|
|
28444
|
+
(binding) => !selectedFields || selectedFields.has(binding.fieldId)
|
|
28445
|
+
);
|
|
28446
|
+
const issues = getA2UICardBindingSelectionIssues(
|
|
28447
|
+
bindings,
|
|
28448
|
+
"draft.manifest.bindings",
|
|
28449
|
+
bundle.manifest.fields
|
|
28450
|
+
);
|
|
28451
|
+
for (const binding of bindings) {
|
|
28452
|
+
if (!mountedMcpResourceIds.has(binding.mcpResourceId)) {
|
|
28453
|
+
issues.push({
|
|
28454
|
+
code: "MCP_TOOL_UNAVAILABLE",
|
|
28455
|
+
message: `MCP resource ${binding.mcpResourceId} is not mounted`,
|
|
28456
|
+
path: `draft.manifest.bindings.${binding.fieldId}`
|
|
28457
|
+
});
|
|
28458
|
+
}
|
|
28459
|
+
}
|
|
28460
|
+
if (!selectedFields) {
|
|
28461
|
+
issues.push(
|
|
28462
|
+
...validateA2UICardForPublish(bundle).map((diagnostic) => ({
|
|
28463
|
+
code: diagnostic.code,
|
|
28464
|
+
message: diagnostic.message,
|
|
28465
|
+
path: diagnostic.path
|
|
28466
|
+
}))
|
|
28467
|
+
);
|
|
28468
|
+
}
|
|
28469
|
+
return issues;
|
|
28470
|
+
}
|
|
28046
28471
|
function isJsonObject(value) {
|
|
28047
28472
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
28048
28473
|
}
|
package/package.json
CHANGED
package/vendor/linkque-agent-appwrite-integrate/dist/esm/{chunk-YAKPGLYU.js → chunk-IMZDZMKV.js}
RENAMED
|
@@ -17007,6 +17007,7 @@ function analyzeA2UIBindings(protocol) {
|
|
|
17007
17007
|
const listRoots = inferListRoots(components, issues);
|
|
17008
17008
|
for (const component of components) {
|
|
17009
17009
|
const context = {
|
|
17010
|
+
surfaceId,
|
|
17010
17011
|
component,
|
|
17011
17012
|
listRoot: listRoots.get(component.id),
|
|
17012
17013
|
occurrences,
|
|
@@ -17020,6 +17021,7 @@ function analyzeA2UIBindings(protocol) {
|
|
|
17020
17021
|
issues.push(issue2(`card.surfaces.${surfaceId}.components.${component.id}.children.path`, "INVALID_BINDING_PATH", `Invalid list path ${children.path}`));
|
|
17021
17022
|
} else {
|
|
17022
17023
|
occurrences.push({
|
|
17024
|
+
surfaceId,
|
|
17023
17025
|
componentId: component.id,
|
|
17024
17026
|
componentName: component.component,
|
|
17025
17027
|
propertyPath: "children.path",
|
|
@@ -17038,6 +17040,16 @@ function analyzeA2UIBindings(protocol) {
|
|
|
17038
17040
|
issues
|
|
17039
17041
|
};
|
|
17040
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
|
+
}
|
|
17041
17053
|
function visitValue(value, propertyPath, context) {
|
|
17042
17054
|
if (propertyPath === "action.local.path" && typeof value === "string") {
|
|
17043
17055
|
addOccurrence(value, propertyPath, "local", context);
|
|
@@ -17069,6 +17081,7 @@ function addOccurrence(rawPath, propertyPath, usage, context) {
|
|
|
17069
17081
|
return;
|
|
17070
17082
|
}
|
|
17071
17083
|
context.occurrences.push({
|
|
17084
|
+
surfaceId: context.surfaceId,
|
|
17072
17085
|
componentId: context.component.id,
|
|
17073
17086
|
componentName: context.component.component,
|
|
17074
17087
|
propertyPath,
|
|
@@ -17480,9 +17493,9 @@ function getA2UICardResourceConfigIssues(value) {
|
|
|
17480
17493
|
validateLooseJsonSchema(value.presentationInputSchema, "config.presentationInputSchema", issues);
|
|
17481
17494
|
const fields = validateFields(value.fields, "config.fields", issues);
|
|
17482
17495
|
const resolver = validateResolver(value.resolver, "config.resolver", issues);
|
|
17483
|
-
validateTemplate(value.a2uiTemplate, fields, issues);
|
|
17496
|
+
const card = validateTemplate(value.a2uiTemplate, fields, issues);
|
|
17484
17497
|
if (fields && resolver)
|
|
17485
|
-
validateResolverCoverage(fields, resolver, issues);
|
|
17498
|
+
validateResolverCoverage(fields, resolver, issues, card);
|
|
17486
17499
|
return issues;
|
|
17487
17500
|
}
|
|
17488
17501
|
function getA2UICardResourceConfigV3Issues(value) {
|
|
@@ -17515,9 +17528,9 @@ function getA2UICardResourceConfigV3Issues(value) {
|
|
|
17515
17528
|
}
|
|
17516
17529
|
const dataSources = validateDataSources(value.dataSources, "config.dataSources", issues);
|
|
17517
17530
|
const bindings = validateV3OutputBindings(value.bindings, "config.bindings", issues);
|
|
17518
|
-
validateTemplate(value.a2uiTemplate, fields, issues);
|
|
17531
|
+
const card = validateTemplate(value.a2uiTemplate, fields, issues);
|
|
17519
17532
|
if (fields && dataSources && bindings) {
|
|
17520
|
-
validateV3Coverage(fields, dataSources, bindings, issues);
|
|
17533
|
+
validateV3Coverage(fields, dataSources, bindings, issues, { card });
|
|
17521
17534
|
}
|
|
17522
17535
|
return issues;
|
|
17523
17536
|
}
|
|
@@ -17631,7 +17644,8 @@ function validateV3Coverage(fields, dataSources, bindings, issues, options = {})
|
|
|
17631
17644
|
bound.add(binding.fieldId);
|
|
17632
17645
|
});
|
|
17633
17646
|
if (options.requireComplete !== false) {
|
|
17634
|
-
|
|
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) {
|
|
17635
17649
|
if (bound.has(fieldId))
|
|
17636
17650
|
continue;
|
|
17637
17651
|
issues.push(issue2("config.bindings", "CARD_BINDING_INCOMPLETE", `business field ${fieldId} is not bound`));
|
|
@@ -17931,13 +17945,13 @@ function validateInstructionShape(instruction, path2, issues) {
|
|
|
17931
17945
|
function validateTemplate(value, fields, issues) {
|
|
17932
17946
|
if (!isPlainRecord(value)) {
|
|
17933
17947
|
issues.push(issue2("config.a2uiTemplate", "INVALID_A2UI_TEMPLATE", "a2uiTemplate must be an object"));
|
|
17934
|
-
return;
|
|
17948
|
+
return void 0;
|
|
17935
17949
|
}
|
|
17936
17950
|
exactKeys(value, ["argsSchema", "content"], "config.a2uiTemplate", issues);
|
|
17937
17951
|
validateLooseJsonSchema(value.argsSchema, "config.a2uiTemplate.argsSchema", issues);
|
|
17938
17952
|
if (typeof value.content !== "string") {
|
|
17939
17953
|
issues.push(issue2("config.a2uiTemplate.content", "INVALID_A2UI_CONTENT", "a2uiTemplate.content must be serialized A2UI JSON"));
|
|
17940
|
-
return;
|
|
17954
|
+
return void 0;
|
|
17941
17955
|
}
|
|
17942
17956
|
try {
|
|
17943
17957
|
const card = validateProtocol(JSON.parse(value.content), "config.a2uiTemplate.content", issues);
|
|
@@ -17945,9 +17959,11 @@ function validateTemplate(value, fields, issues) {
|
|
|
17945
17959
|
const analysis = analyzeA2UIBindings(card);
|
|
17946
17960
|
issues.push(...analysis.issues);
|
|
17947
17961
|
}
|
|
17962
|
+
return card;
|
|
17948
17963
|
} catch {
|
|
17949
17964
|
issues.push(issue2("config.a2uiTemplate.content", "INVALID_A2UI_CONTENT", "a2uiTemplate.content must contain valid JSON"));
|
|
17950
17965
|
}
|
|
17966
|
+
return void 0;
|
|
17951
17967
|
}
|
|
17952
17968
|
function validateLooseJsonSchema(value, path2, issues) {
|
|
17953
17969
|
const schemaIssues = getJsonSchemaIssues2(value, path2, {
|
|
@@ -17956,7 +17972,7 @@ function validateLooseJsonSchema(value, path2, issues) {
|
|
|
17956
17972
|
issues.push(...schemaIssues);
|
|
17957
17973
|
return schemaIssues.length === 0;
|
|
17958
17974
|
}
|
|
17959
|
-
function validateResolverCoverage(fields, resolver, issues) {
|
|
17975
|
+
function validateResolverCoverage(fields, resolver, issues, card) {
|
|
17960
17976
|
const businessFields = new Set(fields.filter((field) => field.source === "business").map((field) => field.fieldId));
|
|
17961
17977
|
const bound = /* @__PURE__ */ new Set();
|
|
17962
17978
|
resolver.outputBindings.forEach((binding, index2) => {
|
|
@@ -17965,7 +17981,8 @@ function validateResolverCoverage(fields, resolver, issues) {
|
|
|
17965
17981
|
}
|
|
17966
17982
|
bound.add(binding.fieldId);
|
|
17967
17983
|
});
|
|
17968
|
-
|
|
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) {
|
|
17969
17986
|
if (!bound.has(fieldId)) {
|
|
17970
17987
|
issues.push(issue2("config.resolver.outputBindings", "CARD_BINDING_INCOMPLETE", `business field ${fieldId} is not bound`));
|
|
17971
17988
|
}
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
parseConversationRunRequest,
|
|
52
52
|
parseSkillFile,
|
|
53
53
|
streamToConversationEvents
|
|
54
|
-
} from "../../chunk-
|
|
54
|
+
} from "../../chunk-IMZDZMKV.js";
|
|
55
55
|
import "../../chunk-XUFLSZM4.js";
|
|
56
56
|
import "../../chunk-I64V3ICJ.js";
|
|
57
57
|
import "../../chunk-6MHDOBWO.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
|
-
|
|
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
|
-
|
|
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
|
|