linkque-cli-v2 1.1.4-beta.1 → 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.
Files changed (2) hide show
  1. package/linkquejs.js +439 -36
  2. package/package.json +1 -1
package/linkquejs.js CHANGED
@@ -27426,9 +27426,6 @@ function createA2UICardDraftStructureChecksum(draft) {
27426
27426
  delete cloned.manifest.bindings;
27427
27427
  return sha256Hex(stableJsonStringify(cloned));
27428
27428
  }
27429
- function createA2UICardMcpConfigChecksum(resources) {
27430
- return sha256Hex(stableJsonStringify(resources));
27431
- }
27432
27429
  function createA2UICardRevision(draftChecksum2, bindings) {
27433
27430
  const digest = sha256Hex(`${draftChecksum2}
27434
27431
  ${stableJsonStringify(bindings)}`);
@@ -27507,6 +27504,393 @@ var SHA256_CONSTANTS = [
27507
27504
  3329325298
27508
27505
  ];
27509
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
+
27510
27894
  // src/commands/card/index.ts
27511
27895
  var DRAFT_ROOT = ".card-drafts";
27512
27896
  var AGENT_CONFIG_PATH = "agent_config.json";
@@ -27636,36 +28020,20 @@ async function validateCardBindingsFromDisk(cwd, draftId, fieldId) {
27636
28020
  const directory = draftDirectory(cwd, draftId);
27637
28021
  const [bundle, contextValue, configValue] = await Promise.all([
27638
28022
  readBundle(directory, draftId),
27639
- readRequiredJson(import_path22.default.join(directory, "binding-context.json")),
28023
+ readOptionalJson(import_path22.default.join(directory, "binding-context.json")),
27640
28024
  readRequiredJson(import_path22.default.join(cwd, AGENT_CONFIG_PATH))
27641
28025
  ]);
27642
- const contextResult = parseA2UICardBindingContext(contextValue);
27643
- if (!contextResult.success) {
27644
- throw new LinkqueCliError(
27645
- "CARD_BINDING_CONTEXT_INVALID",
27646
- contextResult.issues.map((entry) => entry.message).join("; ")
27647
- );
27648
- }
27649
- const context = contextResult.data;
28026
+ const context = parseOptionalBindingContext(contextValue);
27650
28027
  const draftStructureChecksum = createA2UICardDraftStructureChecksum(bundle);
27651
28028
  const config2 = parseAgentConfig(configValue);
27652
28029
  const mcpResources = normalizedMcpResources(config2);
27653
- if (context.mcpConfigChecksum !== createA2UICardMcpConfigChecksum(mcpResources)) {
27654
- throw new LinkqueCliError(
27655
- "CARD_BINDING_CONTEXT_STALE",
27656
- "MCP \u914D\u7F6E\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u53D1\u8D77 AI \u8F85\u52A9\u7ED1\u5B9A"
27657
- );
27658
- }
27659
- const issues = validateA2UICardBindings(
27660
- {
27661
- draft: bundle,
27662
- context,
27663
- mountedMcpResourceIds: new Set(
27664
- mcpResources.map((resource) => String(resource.resourceId))
27665
- )
27666
- },
27667
- fieldId ? { fieldIds: /* @__PURE__ */ new Set([fieldId]) } : void 0
28030
+ const mountedMcpResourceIds = new Set(
28031
+ mcpResources.map((resource) => String(resource.resourceId))
27668
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);
27669
28037
  if (issues.length > 0) {
27670
28038
  throw new LinkqueCliError(
27671
28039
  "CARD_BINDING_VALIDATION_FAILED",
@@ -27696,15 +28064,9 @@ async function finalizeCardWhileLocked(cwd, draftId, expectedDraftChecksum) {
27696
28064
  }
27697
28065
  const directory = draftDirectory(cwd, draftId);
27698
28066
  const bundle = await readBundle(directory, draftId);
27699
- const contextResult = parseA2UICardBindingContext(
27700
- await readRequiredJson(import_path22.default.join(directory, "binding-context.json"))
28067
+ const context = parseOptionalBindingContext(
28068
+ await readOptionalJson(import_path22.default.join(directory, "binding-context.json"))
27701
28069
  );
27702
- if (!contextResult.success) {
27703
- throw new LinkqueCliError(
27704
- "CARD_BINDING_CONTEXT_INVALID",
27705
- contextResult.issues.map((entry) => entry.message).join("; ")
27706
- );
27707
- }
27708
28070
  const configPath = import_path22.default.join(cwd, AGENT_CONFIG_PATH);
27709
28071
  const oldConfigBytes = await (0, import_promises16.readFile)(configPath);
27710
28072
  const config2 = parseAgentConfig(
@@ -27738,7 +28100,7 @@ async function finalizeCardWhileLocked(cwd, draftId, expectedDraftChecksum) {
27738
28100
  // V3,让 Agent 直接按真实 MCP inputSchema 决定参数;不再把 presentation input
27739
28101
  // 或 inputBindings 固化进 CARD。
27740
28102
  ...bindings.length > 0 ? { targetSchemaVersion: "3" } : {},
27741
- tools: contextResult.data.candidates.flatMap(
28103
+ tools: (context?.candidates ?? []).flatMap(
27742
28104
  (candidate) => candidate.status === "ready" ? [candidate.tool] : []
27743
28105
  )
27744
28106
  });
@@ -28065,6 +28427,47 @@ function normalizedMcpResources(config2) {
28065
28427
  (left, right) => stableJsonStringify(left).localeCompare(stableJsonStringify(right))
28066
28428
  );
28067
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
+ }
28068
28471
  function isJsonObject(value) {
28069
28472
  return value !== null && typeof value === "object" && !Array.isArray(value);
28070
28473
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linkque-cli-v2",
3
- "version": "1.1.4-beta.1",
3
+ "version": "1.1.5",
4
4
  "description": "Public Linkque CLI bundle for sandbox debugging",
5
5
  "bin": {
6
6
  "linkquejs": "linkquejs.js"