@ductape/mcp 0.1.58 → 0.1.59
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/dist/index.js +22 -13
- package/dist/proxy-client.d.ts.map +1 -1
- package/dist/proxy-client.js +8 -2
- package/package.json +1 -1
- package/scripts/check-frontend-analytics-guidance.mjs +8 -0
- package/src/index.ts +22 -13
- package/src/proxy-client.ts +8 -2
package/dist/index.js
CHANGED
|
@@ -123,8 +123,9 @@ There are THREE categories of operations. Use the right tool for each:
|
|
|
123
123
|
ductape_cli("resources storage list")
|
|
124
124
|
ductape_cli("resources database create -f db-config.json")
|
|
125
125
|
This applies to: products, apps, and resources (databases, storage, caches, etc.),
|
|
126
|
-
cloud connections, and secrets. Environments, app actions, auths,
|
|
127
|
-
|
|
126
|
+
cloud connections, and secrets. Environments, app actions, auths, quotas, fallbacks,
|
|
127
|
+
jobs, and healthchecks are configured in the Workbench UI. Features have no CLI create
|
|
128
|
+
command because their definitions are code-first through features.define.
|
|
128
129
|
|
|
129
130
|
⚠ MULTI-ENV REQUIREMENT — applies to ALL product assets (storage, database, cache,
|
|
130
131
|
messageBroker, graph, vector, and any other resource with an envs array):
|
|
@@ -786,7 +787,7 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
|
|
|
786
787
|
// ctx.graph.execute({ graph, action, input })
|
|
787
788
|
// ctx.notification.send/email/push/sms({ notification, event, ... })
|
|
788
789
|
// ctx.storage.upload/download({ storage, event, input })
|
|
789
|
-
// ctx.
|
|
790
|
+
// ctx.events.produce({ event: "broker:topic", message: {} })
|
|
790
791
|
// ctx.quota.execute({ quota, input })
|
|
791
792
|
// ctx.fallback.execute({ fallback, input })
|
|
792
793
|
// ctx.healthcheck.getStatus(tag)
|
|
@@ -1231,7 +1232,9 @@ function runCli(command) {
|
|
|
1231
1232
|
try {
|
|
1232
1233
|
const output = execSync(`ductape ${finalCommand}`, {
|
|
1233
1234
|
encoding: 'utf8',
|
|
1234
|
-
timeout
|
|
1235
|
+
// Must exceed the proxy's operation timeout so stderr can preserve the structured timeout
|
|
1236
|
+
// instead of this wrapper killing the CLI first and reducing it to "(no data)".
|
|
1237
|
+
timeout: 90000,
|
|
1235
1238
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1236
1239
|
});
|
|
1237
1240
|
return { success: true, output: output.trim() };
|
|
@@ -2650,9 +2653,11 @@ STEP 4 — PRESENT the plan and get approval BEFORE writing any code or creating
|
|
|
2650
2653
|
STEP 5 — CREATE missing components (only with user approval)
|
|
2651
2654
|
Administrative assets must never be created through ductape_execute. Use ductape_cli for products,
|
|
2652
2655
|
apps, supported resources, broker topics, cloud connections, secrets, and declarative apply flows.
|
|
2653
|
-
App actions, auths,
|
|
2654
|
-
has no command must be configured in Workbench.
|
|
2655
|
-
|
|
2656
|
+
App actions, auths, quotas, fallbacks, health checks, and other administrative assets for which
|
|
2657
|
+
the CLI has no command must be configured in Workbench. Feature definitions are the exception:
|
|
2658
|
+
they are code-first via features.define, are registered by application boot/runtime initialization,
|
|
2659
|
+
and cannot be created with the CLI. Do not generate a Workbench-only or publishable-key
|
|
2660
|
+
create/update call for a Feature. For a missing database action, configure it in Workbench, then verify it exists.
|
|
2656
2661
|
For a missing child feature, recursively apply this same workflow.
|
|
2657
2662
|
Tell the user what you are about to create before each tool call.
|
|
2658
2663
|
|
|
@@ -2761,7 +2766,9 @@ When you call features.define({ handler }), the handler runs TWICE:
|
|
|
2761
2766
|
Features do NOT execute arbitrary NestJS or server code directly. A feature handler can only
|
|
2762
2767
|
call Ductape component primitives (ctx.api, ctx.database, ctx.notification, etc.) as steps.
|
|
2763
2768
|
To invoke internal application business logic, produce a broker event from a feature step
|
|
2764
|
-
(ctx.
|
|
2769
|
+
(ctx.events.produce in the currently published SDK) and consume it in your NestJS service.
|
|
2770
|
+
ctx.publish is deprecated; do not use it. Do not assume a ctx.messaging alias exists unless the
|
|
2771
|
+
installed SDK types explicitly expose it.
|
|
2765
2772
|
|
|
2766
2773
|
━━━ ORCHESTRATION DECISION RULE ━━━
|
|
2767
2774
|
|
|
@@ -2775,7 +2782,7 @@ When you call features.define({ handler }), the handler runs TWICE:
|
|
|
2775
2782
|
→ define a Feature, then features.dispatch to schedule it
|
|
2776
2783
|
|
|
2777
2784
|
Invoke internal application business logic (your own NestJS/backend service code):
|
|
2778
|
-
→ produce a broker event (ctx.
|
|
2785
|
+
→ produce a broker event (ctx.events.produce inside a Feature, or ductape.events.produce outside it)
|
|
2779
2786
|
→ follow ductape_docs({ topic: "events" }) and use the canonical NestJS decorator:
|
|
2780
2787
|
@Events.Consumer({ event: "broker-tag:topic-tag" })
|
|
2781
2788
|
async handle(message: MessageShape) { /* injected-service business logic; throw to nack */ }
|
|
@@ -3710,8 +3717,9 @@ const cliInputSchema = z.object({
|
|
|
3710
3717
|
'Use this tool for administrative operations: creating or updating products, apps, ' +
|
|
3711
3718
|
'resources (databases, storage, caches…), event broker topics, cloud connections, secrets, ' +
|
|
3712
3719
|
'and for apply/migrate workflows.\n\n' +
|
|
3713
|
-
'Note: environments, app actions,
|
|
3714
|
-
'
|
|
3720
|
+
'Note: environments, app actions, quotas, fallbacks, and jobs are configured in the ' +
|
|
3721
|
+
'Workbench UI. Features also have no CLI creation command: define them in application code ' +
|
|
3722
|
+
'with features.define so application boot/runtime registration makes them available.\n\n' +
|
|
3715
3723
|
'The CLI uses the user\'s local logged-in session (ductape login) — no key is required.'),
|
|
3716
3724
|
});
|
|
3717
3725
|
async function loadMcpSdk() {
|
|
@@ -4111,8 +4119,9 @@ async function main() {
|
|
|
4111
4119
|
' - Linking a project folder: "link --product <tag> --env <slug>"\n' +
|
|
4112
4120
|
' - Syncing sessions/notifications/events: "apply" or "apply sessions" etc.\n' +
|
|
4113
4121
|
' - Running database migrations: "db migrate", "db schema generate"\n\n' +
|
|
4114
|
-
'NOTE: Environments, app actions, auths,
|
|
4115
|
-
'
|
|
4122
|
+
'NOTE: Environments, app actions, auths, quotas, fallbacks, and jobs are configured ' +
|
|
4123
|
+
'in the Workbench UI. Features have no CLI creation command because definitions are ' +
|
|
4124
|
+
'code-first through features.define and registered by the application runtime.\n\n' +
|
|
4116
4125
|
'DO NOT use ductape_execute for admin operations — it uses a publishable key which only ' +
|
|
4117
4126
|
'covers runtime operations. Administrative operations will fail with "Authentication failed".\n\n' +
|
|
4118
4127
|
'The CLI uses the user\'s local logged-in session (ductape login). ' +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy-client.d.ts","sourceRoot":"","sources":["../src/proxy-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,YAAY,4BAA4B,CAAC;AAEtD,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,KAAK,GACL,WAAW,GACX,OAAO,GACP,UAAU,GACV,eAAe,GACf,gBAAgB,GAChB,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,SAAS,GACT,UAAU,GACV,MAAM,GACN,MAAM,GACN,YAAY,GACZ,QAAQ,GACR,UAAU,GACV,SAAS,CAAC;AAUd;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,GAAG,OAAO,EAC/C,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,OAAO,EAAO,GACrB,OAAO,CAAC,CAAC,CAAC,CAuBZ;AAED,MAAM,WAAW,iCAAiC;IAChD,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACpD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,kCAAkC;IACjD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AASD,wBAAsB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYvE;AA4BD,wBAAsB,yBAAyB,CAAC,CAAC,GAAG,kCAAkC,EACpF,OAAO,EAAE,iCAAiC,GACzC,OAAO,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"proxy-client.d.ts","sourceRoot":"","sources":["../src/proxy-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,YAAY,4BAA4B,CAAC;AAEtD,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,KAAK,GACL,WAAW,GACX,OAAO,GACP,UAAU,GACV,eAAe,GACf,gBAAgB,GAChB,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,SAAS,GACT,UAAU,GACV,MAAM,GACN,MAAM,GACN,YAAY,GACZ,QAAQ,GACR,UAAU,GACV,SAAS,CAAC;AAUd;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,GAAG,OAAO,EAC/C,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,OAAO,EAAO,GACrB,OAAO,CAAC,CAAC,CAAC,CAuBZ;AAED,MAAM,WAAW,iCAAiC;IAChD,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACpD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,kCAAkC;IACjD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AASD,wBAAsB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYvE;AA4BD,wBAAsB,yBAAyB,CAAC,CAAC,GAAG,kCAAkC,EACpF,OAAO,EAAE,iCAAiC,GACzC,OAAO,CAAC,CAAC,CAAC,CA8BZ"}
|
package/dist/proxy-client.js
CHANGED
|
@@ -67,9 +67,15 @@ function normalizeTargets(targets) {
|
|
|
67
67
|
return result;
|
|
68
68
|
}
|
|
69
69
|
export async function generateExecutablePayload(request) {
|
|
70
|
+
// execution_context is MCP guidance metadata, not part of the integrations
|
|
71
|
+
// payload-generator API contract. Keep it for local session-awareness output
|
|
72
|
+
// but never forward it to the backend validator.
|
|
73
|
+
const { execution_context: _executionContext, ...backendRequest } = request;
|
|
70
74
|
const normalizedRequest = {
|
|
71
|
-
...
|
|
72
|
-
targets:
|
|
75
|
+
...backendRequest,
|
|
76
|
+
targets: backendRequest.targets
|
|
77
|
+
? normalizeTargets(backendRequest.targets)
|
|
78
|
+
: backendRequest.targets,
|
|
73
79
|
};
|
|
74
80
|
const url = `${API_BASE_URL.replace(/\/$/, '')}/integrations/v1/payloads/generate`;
|
|
75
81
|
const res = await fetch(url, {
|
package/package.json
CHANGED
|
@@ -56,6 +56,8 @@ const safetyChecks = [
|
|
|
56
56
|
['notification declarations require array shape', /file MUST be a top-level JSON array/],
|
|
57
57
|
['external CLI login is re-read', /authState === 'unknown' \|\| authState === 'none'/],
|
|
58
58
|
['compact product inventory documented', /products components list --tag <tag> --json/],
|
|
59
|
+
['features use installed events context', /ctx\.events\.produce inside a Feature/],
|
|
60
|
+
['features are code-first rather than Workbench-created', /Features have no CLI (?:create|creation)\s+command because (?:their )?definitions are code-first/],
|
|
59
61
|
['Firebase GCP cloud connection documented', /FIREBASE THROUGH A GCP CLOUD CONNECTION[\s\S]*authMode.*cloud_connection/],
|
|
60
62
|
['Slack and Discord sends documented', /notifications\.slack\.send[\s\S]*notifications\.discord\.send/],
|
|
61
63
|
];
|
|
@@ -77,4 +79,10 @@ assert.doesNotMatch(
|
|
|
77
79
|
'Browser Events guidance must not import the server SDK',
|
|
78
80
|
);
|
|
79
81
|
|
|
82
|
+
assert.doesNotMatch(
|
|
83
|
+
source,
|
|
84
|
+
/ctx\.messaging\.produce/,
|
|
85
|
+
'Feature guidance must use the installed ctx.events API, not a nonexistent ctx.messaging alias',
|
|
86
|
+
);
|
|
87
|
+
|
|
80
88
|
console.log(`MCP guidance: ${checks.length + 1 + safetyChecks.length} acceptance checks passed`);
|
package/src/index.ts
CHANGED
|
@@ -134,8 +134,9 @@ There are THREE categories of operations. Use the right tool for each:
|
|
|
134
134
|
ductape_cli("resources storage list")
|
|
135
135
|
ductape_cli("resources database create -f db-config.json")
|
|
136
136
|
This applies to: products, apps, and resources (databases, storage, caches, etc.),
|
|
137
|
-
cloud connections, and secrets. Environments, app actions, auths,
|
|
138
|
-
|
|
137
|
+
cloud connections, and secrets. Environments, app actions, auths, quotas, fallbacks,
|
|
138
|
+
jobs, and healthchecks are configured in the Workbench UI. Features have no CLI create
|
|
139
|
+
command because their definitions are code-first through features.define.
|
|
139
140
|
|
|
140
141
|
⚠ MULTI-ENV REQUIREMENT — applies to ALL product assets (storage, database, cache,
|
|
141
142
|
messageBroker, graph, vector, and any other resource with an envs array):
|
|
@@ -797,7 +798,7 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
|
|
|
797
798
|
// ctx.graph.execute({ graph, action, input })
|
|
798
799
|
// ctx.notification.send/email/push/sms({ notification, event, ... })
|
|
799
800
|
// ctx.storage.upload/download({ storage, event, input })
|
|
800
|
-
// ctx.
|
|
801
|
+
// ctx.events.produce({ event: "broker:topic", message: {} })
|
|
801
802
|
// ctx.quota.execute({ quota, input })
|
|
802
803
|
// ctx.fallback.execute({ fallback, input })
|
|
803
804
|
// ctx.healthcheck.getStatus(tag)
|
|
@@ -1292,7 +1293,9 @@ function runCli(command: string): { success: boolean; output: string } {
|
|
|
1292
1293
|
try {
|
|
1293
1294
|
const output = execSync(`ductape ${finalCommand}`, {
|
|
1294
1295
|
encoding: 'utf8',
|
|
1295
|
-
timeout
|
|
1296
|
+
// Must exceed the proxy's operation timeout so stderr can preserve the structured timeout
|
|
1297
|
+
// instead of this wrapper killing the CLI first and reducing it to "(no data)".
|
|
1298
|
+
timeout: 90000,
|
|
1296
1299
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1297
1300
|
});
|
|
1298
1301
|
return { success: true, output: output.trim() };
|
|
@@ -2736,9 +2739,11 @@ STEP 4 — PRESENT the plan and get approval BEFORE writing any code or creating
|
|
|
2736
2739
|
STEP 5 — CREATE missing components (only with user approval)
|
|
2737
2740
|
Administrative assets must never be created through ductape_execute. Use ductape_cli for products,
|
|
2738
2741
|
apps, supported resources, broker topics, cloud connections, secrets, and declarative apply flows.
|
|
2739
|
-
App actions, auths,
|
|
2740
|
-
has no command must be configured in Workbench.
|
|
2741
|
-
|
|
2742
|
+
App actions, auths, quotas, fallbacks, health checks, and other administrative assets for which
|
|
2743
|
+
the CLI has no command must be configured in Workbench. Feature definitions are the exception:
|
|
2744
|
+
they are code-first via features.define, are registered by application boot/runtime initialization,
|
|
2745
|
+
and cannot be created with the CLI. Do not generate a Workbench-only or publishable-key
|
|
2746
|
+
create/update call for a Feature. For a missing database action, configure it in Workbench, then verify it exists.
|
|
2742
2747
|
For a missing child feature, recursively apply this same workflow.
|
|
2743
2748
|
Tell the user what you are about to create before each tool call.
|
|
2744
2749
|
|
|
@@ -2847,7 +2852,9 @@ When you call features.define({ handler }), the handler runs TWICE:
|
|
|
2847
2852
|
Features do NOT execute arbitrary NestJS or server code directly. A feature handler can only
|
|
2848
2853
|
call Ductape component primitives (ctx.api, ctx.database, ctx.notification, etc.) as steps.
|
|
2849
2854
|
To invoke internal application business logic, produce a broker event from a feature step
|
|
2850
|
-
(ctx.
|
|
2855
|
+
(ctx.events.produce in the currently published SDK) and consume it in your NestJS service.
|
|
2856
|
+
ctx.publish is deprecated; do not use it. Do not assume a ctx.messaging alias exists unless the
|
|
2857
|
+
installed SDK types explicitly expose it.
|
|
2851
2858
|
|
|
2852
2859
|
━━━ ORCHESTRATION DECISION RULE ━━━
|
|
2853
2860
|
|
|
@@ -2861,7 +2868,7 @@ When you call features.define({ handler }), the handler runs TWICE:
|
|
|
2861
2868
|
→ define a Feature, then features.dispatch to schedule it
|
|
2862
2869
|
|
|
2863
2870
|
Invoke internal application business logic (your own NestJS/backend service code):
|
|
2864
|
-
→ produce a broker event (ctx.
|
|
2871
|
+
→ produce a broker event (ctx.events.produce inside a Feature, or ductape.events.produce outside it)
|
|
2865
2872
|
→ follow ductape_docs({ topic: "events" }) and use the canonical NestJS decorator:
|
|
2866
2873
|
@Events.Consumer({ event: "broker-tag:topic-tag" })
|
|
2867
2874
|
async handle(message: MessageShape) { /* injected-service business logic; throw to nack */ }
|
|
@@ -3804,8 +3811,9 @@ const cliInputSchema = z.object({
|
|
|
3804
3811
|
'Use this tool for administrative operations: creating or updating products, apps, ' +
|
|
3805
3812
|
'resources (databases, storage, caches…), event broker topics, cloud connections, secrets, ' +
|
|
3806
3813
|
'and for apply/migrate workflows.\n\n' +
|
|
3807
|
-
'Note: environments, app actions,
|
|
3808
|
-
'
|
|
3814
|
+
'Note: environments, app actions, quotas, fallbacks, and jobs are configured in the ' +
|
|
3815
|
+
'Workbench UI. Features also have no CLI creation command: define them in application code ' +
|
|
3816
|
+
'with features.define so application boot/runtime registration makes them available.\n\n' +
|
|
3809
3817
|
'The CLI uses the user\'s local logged-in session (ductape login) — no key is required.',
|
|
3810
3818
|
),
|
|
3811
3819
|
});
|
|
@@ -4272,8 +4280,9 @@ async function main() {
|
|
|
4272
4280
|
' - Linking a project folder: "link --product <tag> --env <slug>"\n' +
|
|
4273
4281
|
' - Syncing sessions/notifications/events: "apply" or "apply sessions" etc.\n' +
|
|
4274
4282
|
' - Running database migrations: "db migrate", "db schema generate"\n\n' +
|
|
4275
|
-
'NOTE: Environments, app actions, auths,
|
|
4276
|
-
'
|
|
4283
|
+
'NOTE: Environments, app actions, auths, quotas, fallbacks, and jobs are configured ' +
|
|
4284
|
+
'in the Workbench UI. Features have no CLI creation command because definitions are ' +
|
|
4285
|
+
'code-first through features.define and registered by the application runtime.\n\n' +
|
|
4277
4286
|
'DO NOT use ductape_execute for admin operations — it uses a publishable key which only ' +
|
|
4278
4287
|
'covers runtime operations. Administrative operations will fail with "Authentication failed".\n\n' +
|
|
4279
4288
|
'The CLI uses the user\'s local logged-in session (ductape login). ' +
|
package/src/proxy-client.ts
CHANGED
|
@@ -137,9 +137,15 @@ function normalizeTargets(targets: Record<string, unknown>): Record<string, unkn
|
|
|
137
137
|
export async function generateExecutablePayload<T = IGenerateExecutablePayloadResponse>(
|
|
138
138
|
request: IGenerateExecutablePayloadRequest,
|
|
139
139
|
): Promise<T> {
|
|
140
|
+
// execution_context is MCP guidance metadata, not part of the integrations
|
|
141
|
+
// payload-generator API contract. Keep it for local session-awareness output
|
|
142
|
+
// but never forward it to the backend validator.
|
|
143
|
+
const { execution_context: _executionContext, ...backendRequest } = request;
|
|
140
144
|
const normalizedRequest = {
|
|
141
|
-
...
|
|
142
|
-
targets:
|
|
145
|
+
...backendRequest,
|
|
146
|
+
targets: backendRequest.targets
|
|
147
|
+
? normalizeTargets(backendRequest.targets as Record<string, unknown>)
|
|
148
|
+
: backendRequest.targets,
|
|
143
149
|
};
|
|
144
150
|
const url = `${API_BASE_URL.replace(/\/$/, '')}/integrations/v1/payloads/generate`;
|
|
145
151
|
const res = await fetch(url, {
|