@suveren/gateway 0.27.2 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/content/integrations/crm.json +11 -1
- package/content/integrations/erp.json +40 -2
- package/dist/mcp-server/http.mjs +212 -17
- package/dist/ui/assets/index-I9WCdLMY.js +120 -0
- package/dist/ui/assets/index-RX5juZkm.css +1 -0
- package/dist/ui/index.html +2 -2
- package/node_modules/@hono/node-server/README.md +2 -0
- package/node_modules/@hono/node-server/dist/index.cjs +1 -1
- package/node_modules/@hono/node-server/dist/index.mjs +1 -1
- package/node_modules/@hono/node-server/dist/serve-static.cjs +2 -1
- package/node_modules/@hono/node-server/dist/serve-static.mjs +2 -1
- package/node_modules/@hono/node-server/package.json +1 -1
- package/package.json +1 -1
- package/dist/ui/assets/index-DeEzJCqI.css +0 -1
- package/dist/ui/assets/index-M-BITdkM.js +0 -120
|
@@ -54,7 +54,17 @@
|
|
|
54
54
|
"staticExecution": {
|
|
55
55
|
"action_type": "write"
|
|
56
56
|
},
|
|
57
|
-
"actionLabel": "Contact created"
|
|
57
|
+
"actionLabel": "Contact created",
|
|
58
|
+
"preview": [
|
|
59
|
+
{ "tool": "find_contacts", "args": { "query": "email" } }
|
|
60
|
+
],
|
|
61
|
+
"display": {
|
|
62
|
+
"order": ["name", "email", "company", "role", "type", "stage", "tags", "notes"],
|
|
63
|
+
"labels": {
|
|
64
|
+
"name": "Name", "email": "Email", "company": "Company", "role": "Role",
|
|
65
|
+
"type": "Type", "stage": "Stage", "tags": "Tags", "notes": "Notes"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
58
68
|
},
|
|
59
69
|
"update_contact": {
|
|
60
70
|
"executionMapping": {
|
|
@@ -95,7 +95,29 @@
|
|
|
95
95
|
"staticExecution": {
|
|
96
96
|
"action_type": "quote"
|
|
97
97
|
},
|
|
98
|
-
"actionLabel": "Quote drafted"
|
|
98
|
+
"actionLabel": "Quote drafted",
|
|
99
|
+
"preview": [
|
|
100
|
+
{ "tool": "get_customer", "args": { "id": "customer_id" }, "attach": "customer_id" },
|
|
101
|
+
{ "tool": "get_item", "forEach": "lines", "args": { "id": "item_id" }, "attach": "item" }
|
|
102
|
+
],
|
|
103
|
+
"display": {
|
|
104
|
+
"order": ["customer_id", "lines", "discount_pct", "value", "valid_until", "notes"],
|
|
105
|
+
"money": ["value", "customer_id.credit_limit", "customer_id.open_balance", "customer_id.available_credit", "lines[].item.list_price"],
|
|
106
|
+
"percent": ["discount_pct"],
|
|
107
|
+
"currencyField": "currency",
|
|
108
|
+
"labels": {
|
|
109
|
+
"customer_id": "Customer",
|
|
110
|
+
"discount_pct": "Discount",
|
|
111
|
+
"value": "Total (net)",
|
|
112
|
+
"customer_id.credit_limit": "Credit limit",
|
|
113
|
+
"customer_id.open_balance": "Open balance",
|
|
114
|
+
"customer_id.available_credit": "Available credit",
|
|
115
|
+
"customer_id.payment_terms": "Payment terms",
|
|
116
|
+
"lines[].item": "Item",
|
|
117
|
+
"lines[].item.list_price": "List price",
|
|
118
|
+
"lines[].item.stock": "In stock"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
99
121
|
},
|
|
100
122
|
"update_quote": {
|
|
101
123
|
"executionMapping": {
|
|
@@ -106,7 +128,23 @@
|
|
|
106
128
|
"staticExecution": {
|
|
107
129
|
"action_type": "quote"
|
|
108
130
|
},
|
|
109
|
-
"actionLabel": "Quote updated"
|
|
131
|
+
"actionLabel": "Quote updated",
|
|
132
|
+
"preview": [
|
|
133
|
+
{ "tool": "get_item", "forEach": "lines", "args": { "id": "item_id" }, "attach": "item" }
|
|
134
|
+
],
|
|
135
|
+
"display": {
|
|
136
|
+
"order": ["lines", "discount_pct", "value", "valid_until", "notes"],
|
|
137
|
+
"money": ["value", "lines[].item.list_price"],
|
|
138
|
+
"percent": ["discount_pct"],
|
|
139
|
+
"currencyField": "currency",
|
|
140
|
+
"labels": {
|
|
141
|
+
"discount_pct": "Discount",
|
|
142
|
+
"value": "Total (net)",
|
|
143
|
+
"lines[].item": "Item",
|
|
144
|
+
"lines[].item.list_price": "List price",
|
|
145
|
+
"lines[].item.stock": "In stock"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
110
148
|
},
|
|
111
149
|
"send_quote": {
|
|
112
150
|
"executionMapping": {
|
package/dist/mcp-server/http.mjs
CHANGED
|
@@ -3469,6 +3469,12 @@ import { computeContentHash as computeContentHash2 } from "@hap/core";
|
|
|
3469
3469
|
// src/lib/manifest-loader.ts
|
|
3470
3470
|
import { readFileSync as readFileSync15, existsSync as existsSync14 } from "fs";
|
|
3471
3471
|
import { join as join14, resolve } from "path";
|
|
3472
|
+
|
|
3473
|
+
// src/lib/tool-gating-types.ts
|
|
3474
|
+
var MAX_PREVIEW_READS = 10;
|
|
3475
|
+
var MAX_FOREACH_ELEMENTS = 50;
|
|
3476
|
+
|
|
3477
|
+
// src/lib/manifest-loader.ts
|
|
3472
3478
|
var EXACT_SEMVER_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
3473
3479
|
function isExactSemver(value) {
|
|
3474
3480
|
return typeof value === "string" && EXACT_SEMVER_RE.test(value);
|
|
@@ -3483,44 +3489,101 @@ function invalidNpmPinReason(manifest) {
|
|
|
3483
3489
|
}
|
|
3484
3490
|
return null;
|
|
3485
3491
|
}
|
|
3486
|
-
function
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
if (preview === null || typeof preview !== "object" || Array.isArray(preview)) {
|
|
3491
|
-
return `override "${toolName}".preview must be an object`;
|
|
3492
|
+
function invalidReadConfigReason(toolName, idx, entry) {
|
|
3493
|
+
const label = idx === null ? `override "${toolName}".preview` : `override "${toolName}".preview[${idx}]`;
|
|
3494
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
|
|
3495
|
+
return `${label} must be an object`;
|
|
3492
3496
|
}
|
|
3493
|
-
const p =
|
|
3497
|
+
const p = entry;
|
|
3494
3498
|
if (typeof p.tool !== "string" || p.tool.length === 0) {
|
|
3495
|
-
return
|
|
3499
|
+
return `${label}.tool must be a non-empty string`;
|
|
3496
3500
|
}
|
|
3497
3501
|
if (p.args === void 0 || p.args === null || typeof p.args !== "object" || Array.isArray(p.args)) {
|
|
3498
|
-
return
|
|
3502
|
+
return `${label}.args must be an object mapping preview-tool arg names to action arg names`;
|
|
3499
3503
|
}
|
|
3500
3504
|
for (const [argName, source] of Object.entries(p.args)) {
|
|
3501
3505
|
if (typeof source !== "string" || source.length === 0) {
|
|
3502
|
-
return
|
|
3506
|
+
return `${label}.args.${argName} must name a non-empty source argument (string)`;
|
|
3503
3507
|
}
|
|
3504
3508
|
}
|
|
3509
|
+
if (p.forEach !== void 0 && (typeof p.forEach !== "string" || p.forEach.length === 0)) {
|
|
3510
|
+
return `${label}.forEach must be a non-empty string naming an action argument`;
|
|
3511
|
+
}
|
|
3512
|
+
if (p.attach !== void 0 && (typeof p.attach !== "string" || p.attach.length === 0)) {
|
|
3513
|
+
return `${label}.attach must be a non-empty string`;
|
|
3514
|
+
}
|
|
3505
3515
|
if (p.version !== void 0) {
|
|
3506
3516
|
if (p.version === null || typeof p.version !== "object" || Array.isArray(p.version)) {
|
|
3507
|
-
return
|
|
3517
|
+
return `${label}.version must be an object`;
|
|
3508
3518
|
}
|
|
3509
3519
|
const v = p.version;
|
|
3510
3520
|
if (typeof v.arg !== "string" || v.arg.length === 0) {
|
|
3511
|
-
return
|
|
3521
|
+
return `${label}.version.arg must be a non-empty string`;
|
|
3512
3522
|
}
|
|
3513
3523
|
if (typeof v.field !== "string" || v.field.length === 0) {
|
|
3514
|
-
return
|
|
3524
|
+
return `${label}.version.field must be a non-empty string`;
|
|
3515
3525
|
}
|
|
3516
3526
|
}
|
|
3517
3527
|
if (p.fields !== void 0) {
|
|
3518
3528
|
if (!Array.isArray(p.fields)) {
|
|
3519
|
-
return
|
|
3529
|
+
return `${label}.fields must be an array of field names`;
|
|
3520
3530
|
}
|
|
3521
3531
|
for (const [i, f] of p.fields.entries()) {
|
|
3522
3532
|
if (typeof f !== "string" || f.length === 0) {
|
|
3523
|
-
return
|
|
3533
|
+
return `${label}.fields[${i}] must be a non-empty string`;
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3536
|
+
}
|
|
3537
|
+
return null;
|
|
3538
|
+
}
|
|
3539
|
+
function invalidPreviewReason(toolName, entry) {
|
|
3540
|
+
if (entry === null || typeof entry !== "object") return null;
|
|
3541
|
+
const preview = entry.preview;
|
|
3542
|
+
if (preview === void 0) return null;
|
|
3543
|
+
if (Array.isArray(preview)) {
|
|
3544
|
+
if (preview.length === 0) {
|
|
3545
|
+
return `override "${toolName}".preview must not be an empty list \u2014 omit it, or use the single-object form`;
|
|
3546
|
+
}
|
|
3547
|
+
if (preview.length > MAX_PREVIEW_READS) {
|
|
3548
|
+
return `override "${toolName}".preview declares ${preview.length} reads \u2014 max ${MAX_PREVIEW_READS}`;
|
|
3549
|
+
}
|
|
3550
|
+
for (const [i, read] of preview.entries()) {
|
|
3551
|
+
const reason = invalidReadConfigReason(toolName, i, read);
|
|
3552
|
+
if (reason) return reason;
|
|
3553
|
+
}
|
|
3554
|
+
return null;
|
|
3555
|
+
}
|
|
3556
|
+
return invalidReadConfigReason(toolName, null, preview);
|
|
3557
|
+
}
|
|
3558
|
+
function invalidDisplayHintsReason(toolName, entry) {
|
|
3559
|
+
if (entry === null || typeof entry !== "object") return null;
|
|
3560
|
+
const display = entry.display;
|
|
3561
|
+
if (display === void 0) return null;
|
|
3562
|
+
if (display === null || typeof display !== "object" || Array.isArray(display)) {
|
|
3563
|
+
return `override "${toolName}".display must be an object`;
|
|
3564
|
+
}
|
|
3565
|
+
const d = display;
|
|
3566
|
+
for (const key of ["order", "money", "percent", "hidden"]) {
|
|
3567
|
+
if (d[key] === void 0) continue;
|
|
3568
|
+
if (!Array.isArray(d[key])) {
|
|
3569
|
+
return `override "${toolName}".display.${key} must be an array of field paths`;
|
|
3570
|
+
}
|
|
3571
|
+
for (const [i, v] of d[key].entries()) {
|
|
3572
|
+
if (typeof v !== "string" || v.length === 0) {
|
|
3573
|
+
return `override "${toolName}".display.${key}[${i}] must be a non-empty string`;
|
|
3574
|
+
}
|
|
3575
|
+
}
|
|
3576
|
+
}
|
|
3577
|
+
if (d.currencyField !== void 0 && (typeof d.currencyField !== "string" || d.currencyField.length === 0)) {
|
|
3578
|
+
return `override "${toolName}".display.currencyField must be a non-empty string`;
|
|
3579
|
+
}
|
|
3580
|
+
if (d.labels !== void 0) {
|
|
3581
|
+
if (d.labels === null || typeof d.labels !== "object" || Array.isArray(d.labels)) {
|
|
3582
|
+
return `override "${toolName}".display.labels must be an object mapping field paths to labels`;
|
|
3583
|
+
}
|
|
3584
|
+
for (const [path, label] of Object.entries(d.labels)) {
|
|
3585
|
+
if (typeof label !== "string" || label.length === 0) {
|
|
3586
|
+
return `override "${toolName}".display.labels.${path} must be a non-empty string`;
|
|
3524
3587
|
}
|
|
3525
3588
|
}
|
|
3526
3589
|
}
|
|
@@ -3529,7 +3592,7 @@ function invalidPreviewReason(toolName, entry) {
|
|
|
3529
3592
|
function invalidManifestPreviewReason(manifest) {
|
|
3530
3593
|
const overrides = manifest.toolGating?.overrides ?? {};
|
|
3531
3594
|
for (const [toolName, entry] of Object.entries(overrides)) {
|
|
3532
|
-
const reason = invalidPreviewReason(toolName, entry);
|
|
3595
|
+
const reason = invalidPreviewReason(toolName, entry) ?? invalidDisplayHintsReason(toolName, entry);
|
|
3533
3596
|
if (reason) return reason;
|
|
3534
3597
|
}
|
|
3535
3598
|
return null;
|
|
@@ -3598,6 +3661,13 @@ function getToolPreviewConfig(integrationManager2, integrationId, toolName) {
|
|
|
3598
3661
|
const entry = overrides[toolName];
|
|
3599
3662
|
return entry?.preview;
|
|
3600
3663
|
}
|
|
3664
|
+
function getToolDisplayHints(integrationManager2, integrationId, toolName) {
|
|
3665
|
+
if (integrationManager2.isBuiltin(integrationId)) return void 0;
|
|
3666
|
+
const manifest = getManifest(integrationId);
|
|
3667
|
+
const overrides = manifest?.toolGating?.overrides ?? {};
|
|
3668
|
+
const entry = overrides[toolName];
|
|
3669
|
+
return entry?.display;
|
|
3670
|
+
}
|
|
3601
3671
|
function mapPreviewArgs(preview, actionArgs) {
|
|
3602
3672
|
const mapped = {};
|
|
3603
3673
|
for (const [targetArg, sourceArg] of Object.entries(preview.args)) {
|
|
@@ -3656,10 +3726,105 @@ function hashPreviewBody(body) {
|
|
|
3656
3726
|
}
|
|
3657
3727
|
return computeContentHash2({ kind: "text", version: "1" }, body.text ?? "");
|
|
3658
3728
|
}
|
|
3729
|
+
function isPlainRecord(v) {
|
|
3730
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3731
|
+
}
|
|
3732
|
+
function planPreviewReads(declaration, actionArgs) {
|
|
3733
|
+
const reads = Array.isArray(declaration) ? declaration : [declaration];
|
|
3734
|
+
return reads.map((config) => {
|
|
3735
|
+
const base = {
|
|
3736
|
+
tool: config.tool,
|
|
3737
|
+
attach: config.attach,
|
|
3738
|
+
fields: config.fields,
|
|
3739
|
+
version: config.version,
|
|
3740
|
+
argsMapping: config.args
|
|
3741
|
+
};
|
|
3742
|
+
if (config.forEach) {
|
|
3743
|
+
const source = actionArgs[config.forEach];
|
|
3744
|
+
const list = Array.isArray(source) ? source : [];
|
|
3745
|
+
const capped = list.slice(0, MAX_FOREACH_ELEMENTS);
|
|
3746
|
+
const elements = capped.filter(isPlainRecord).map((el) => ({ args: mapPreviewArgs(config, el) }));
|
|
3747
|
+
return {
|
|
3748
|
+
...base,
|
|
3749
|
+
forEach: config.forEach,
|
|
3750
|
+
elements,
|
|
3751
|
+
...list.length > MAX_FOREACH_ELEMENTS ? { overflow: { shown: MAX_FOREACH_ELEMENTS, total: list.length } } : {}
|
|
3752
|
+
};
|
|
3753
|
+
}
|
|
3754
|
+
const mapped = mapPreviewArgs(config, actionArgs);
|
|
3755
|
+
return { ...base, args: mapped, rawSource: actionArgs, noTarget: previewHasNoTarget(config, mapped) };
|
|
3756
|
+
});
|
|
3757
|
+
}
|
|
3758
|
+
async function runPreviewReadPlan(integrationManager2, integrationId, plan) {
|
|
3759
|
+
const sections = [];
|
|
3760
|
+
for (const item of plan) {
|
|
3761
|
+
const sourceArgNames = Object.values(item.argsMapping);
|
|
3762
|
+
const base = {
|
|
3763
|
+
tool: item.tool,
|
|
3764
|
+
...item.attach ? { attach: item.attach } : {},
|
|
3765
|
+
...sourceArgNames.length === 1 ? { sourceArg: sourceArgNames[0] } : {},
|
|
3766
|
+
...item.fields ? { fields: item.fields } : {}
|
|
3767
|
+
};
|
|
3768
|
+
if (item.elements !== void 0) {
|
|
3769
|
+
const elements = [];
|
|
3770
|
+
for (const el of item.elements) {
|
|
3771
|
+
elements.push(await readPreview(integrationManager2, integrationId, item.tool, el.args));
|
|
3772
|
+
}
|
|
3773
|
+
sections.push({
|
|
3774
|
+
...base,
|
|
3775
|
+
forEach: item.forEach,
|
|
3776
|
+
elements,
|
|
3777
|
+
...item.overflow ? { overflow: item.overflow } : {}
|
|
3778
|
+
});
|
|
3779
|
+
continue;
|
|
3780
|
+
}
|
|
3781
|
+
if (item.noTarget) {
|
|
3782
|
+
sections.push({ ...base, result: { status: "none", reason: "no_target" } });
|
|
3783
|
+
continue;
|
|
3784
|
+
}
|
|
3785
|
+
const read1 = await readPreview(integrationManager2, integrationId, item.tool, item.args);
|
|
3786
|
+
if (read1.status !== "ok" || !item.version) {
|
|
3787
|
+
sections.push({ ...base, result: read1 });
|
|
3788
|
+
continue;
|
|
3789
|
+
}
|
|
3790
|
+
const approved = item.rawSource?.[item.version.arg];
|
|
3791
|
+
if (typeof approved !== "string" && typeof approved !== "number") {
|
|
3792
|
+
sections.push({ ...base, result: read1 });
|
|
3793
|
+
continue;
|
|
3794
|
+
}
|
|
3795
|
+
const { [item.version.arg]: _omit, ...withoutVersion } = item.rawSource;
|
|
3796
|
+
const mappedCurrentArgs = mapPreviewArgs({ args: item.argsMapping }, withoutVersion);
|
|
3797
|
+
const read2 = await readPreview(integrationManager2, integrationId, item.tool, mappedCurrentArgs);
|
|
3798
|
+
if (read2.status !== "ok" || read2.body.structured === void 0) {
|
|
3799
|
+
sections.push({ ...base, result: read1 });
|
|
3800
|
+
continue;
|
|
3801
|
+
}
|
|
3802
|
+
const current = read2.body.structured[item.version.field];
|
|
3803
|
+
if (typeof current !== "string" && typeof current !== "number") {
|
|
3804
|
+
sections.push({ ...base, result: read1 });
|
|
3805
|
+
continue;
|
|
3806
|
+
}
|
|
3807
|
+
const stale = String(current) !== String(approved);
|
|
3808
|
+
sections.push({
|
|
3809
|
+
...base,
|
|
3810
|
+
result: read1,
|
|
3811
|
+
version: {
|
|
3812
|
+
field: item.version.field,
|
|
3813
|
+
approved,
|
|
3814
|
+
current,
|
|
3815
|
+
stale,
|
|
3816
|
+
...stale ? { currentBody: read2.body } : {}
|
|
3817
|
+
}
|
|
3818
|
+
});
|
|
3819
|
+
}
|
|
3820
|
+
return sections;
|
|
3821
|
+
}
|
|
3659
3822
|
async function computeSubmissionPreviewHash(integrationManager2, integrationId, toolName, actionArgs) {
|
|
3660
3823
|
if (integrationManager2.isBuiltin(integrationId)) return void 0;
|
|
3661
3824
|
const preview = getToolPreviewConfig(integrationManager2, integrationId, toolName);
|
|
3662
|
-
if (!preview
|
|
3825
|
+
if (!preview) return void 0;
|
|
3826
|
+
if (Array.isArray(preview)) return combinedPreviewReadsHash(integrationManager2, integrationId, preview, actionArgs);
|
|
3827
|
+
if (preview.version) return void 0;
|
|
3663
3828
|
const mapped = mapPreviewArgs(preview, actionArgs);
|
|
3664
3829
|
if (previewHasNoTarget(preview, mapped)) return void 0;
|
|
3665
3830
|
const read = await readPreview(integrationManager2, integrationId, preview.tool, mapped);
|
|
@@ -3669,14 +3834,44 @@ async function computeSubmissionPreviewHash(integrationManager2, integrationId,
|
|
|
3669
3834
|
async function previewChangedSinceSubmission(integrationManager2, integrationId, toolName, actionArgs, previousHash) {
|
|
3670
3835
|
const preview = getToolPreviewConfig(integrationManager2, integrationId, toolName);
|
|
3671
3836
|
if (!preview) return true;
|
|
3837
|
+
if (Array.isArray(preview)) {
|
|
3838
|
+
const hash = await combinedPreviewReadsHash(integrationManager2, integrationId, preview, actionArgs);
|
|
3839
|
+
if (hash === void 0) return true;
|
|
3840
|
+
return hash !== previousHash;
|
|
3841
|
+
}
|
|
3672
3842
|
const mapped = mapPreviewArgs(preview, actionArgs);
|
|
3673
3843
|
const read = await readPreview(integrationManager2, integrationId, preview.tool, mapped);
|
|
3674
3844
|
if (read.status !== "ok") return true;
|
|
3675
3845
|
return hashPreviewBody(read.body) !== previousHash;
|
|
3676
3846
|
}
|
|
3847
|
+
async function combinedPreviewReadsHash(integrationManager2, integrationId, reads, actionArgs) {
|
|
3848
|
+
const plan = planPreviewReads(reads, actionArgs).filter((item) => !item.version);
|
|
3849
|
+
const hashes = [];
|
|
3850
|
+
for (const item of plan) {
|
|
3851
|
+
if (item.elements !== void 0) {
|
|
3852
|
+
for (const el of item.elements) {
|
|
3853
|
+
const read2 = await readPreview(integrationManager2, integrationId, item.tool, el.args);
|
|
3854
|
+
if (read2.status !== "ok") return void 0;
|
|
3855
|
+
hashes.push(hashPreviewBody(read2.body));
|
|
3856
|
+
}
|
|
3857
|
+
continue;
|
|
3858
|
+
}
|
|
3859
|
+
if (item.noTarget) continue;
|
|
3860
|
+
const read = await readPreview(integrationManager2, integrationId, item.tool, item.args);
|
|
3861
|
+
if (read.status !== "ok") return void 0;
|
|
3862
|
+
hashes.push(hashPreviewBody(read.body));
|
|
3863
|
+
}
|
|
3864
|
+
if (hashes.length === 0) return void 0;
|
|
3865
|
+
return computeContentHash2({ kind: "jcs", version: "1" }, { reads: hashes });
|
|
3866
|
+
}
|
|
3677
3867
|
async function buildInternalPreview(integrationManager2, integrationId, toolName, actionArgs) {
|
|
3678
3868
|
const preview = getToolPreviewConfig(integrationManager2, integrationId, toolName);
|
|
3679
3869
|
if (!preview) return { status: "none" };
|
|
3870
|
+
if (Array.isArray(preview)) {
|
|
3871
|
+
const reads = await runPreviewReadPlan(integrationManager2, integrationId, planPreviewReads(preview, actionArgs));
|
|
3872
|
+
const display = getToolDisplayHints(integrationManager2, integrationId, toolName);
|
|
3873
|
+
return { status: "ok", integration: integrationId, reads, ...display ? { display } : {} };
|
|
3874
|
+
}
|
|
3680
3875
|
const mappedArgs = mapPreviewArgs(preview, actionArgs);
|
|
3681
3876
|
if (previewHasNoTarget(preview, mappedArgs)) return { status: "none", reason: "no_target" };
|
|
3682
3877
|
const read1 = await readPreview(integrationManager2, integrationId, preview.tool, mappedArgs);
|