@zuora/agent-toolkit 0.0.1-alpha.0 → 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +279 -63
- package/dist/{async-jobs-Dd8Jafv0.d.ts → async-jobs-DJ_GygII.d.ts} +8 -16
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/langchain/index.d.ts +52 -1
- package/dist/langchain/index.js +4972 -0
- package/dist/langchain/index.js.map +1 -1
- package/dist/openai/index.d.ts +3 -3
- package/dist/openai/index.js +52 -135
- package/dist/openai/index.js.map +1 -1
- package/dist/openai-agents/index.d.ts +32 -3
- package/dist/openai-agents/index.js +126 -135
- package/dist/openai-agents/index.js.map +1 -1
- package/dist/shared/toolkit-core.d.ts +1 -1
- package/dist/shared/toolkit-core.js +47 -91
- package/dist/shared/toolkit-core.js.map +1 -1
- package/dist/{toolkit-CafRZuAV.d.ts → toolkit-Bjw46goJ.d.ts} +1 -1
- package/dist/vercel-ai/index.d.ts +64 -1
- package/dist/vercel-ai/index.js +5006 -0
- package/dist/vercel-ai/index.js.map +1 -1
- package/package.json +10 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { tool } from '@openai/agents';
|
|
2
2
|
import { ToolkitCore } from '../shared/toolkit-core.js';
|
|
3
|
-
import { Z as ZuoraToolDefinition, a as ZuoraAgentToolkitConfigInput, T as ToolSelection } from '../async-jobs-
|
|
4
|
-
import { Z as ZuoraOpenAIAgentToolkit } from '../toolkit-
|
|
3
|
+
import { b as ZuoraToolExecutionResult, Z as ZuoraToolDefinition, a as ZuoraAgentToolkitConfigInput, T as ToolSelection } from '../async-jobs-DJ_GygII.js';
|
|
4
|
+
import { Z as ZuoraOpenAIAgentToolkit } from '../toolkit-Bjw46goJ.js';
|
|
5
5
|
import 'openai/resources/chat/completions';
|
|
6
6
|
|
|
7
7
|
/** Native tool type returned by `tool()` from `@openai/agents`. */
|
|
@@ -22,6 +22,35 @@ type AgentsFunctionTool = ReturnType<typeof tool>;
|
|
|
22
22
|
* automatically inside `convertTools()` — callers do not need to know about it.
|
|
23
23
|
*/
|
|
24
24
|
declare class ZuoraOpenAIAgentsToolkit extends ToolkitCore<AgentsFunctionTool> {
|
|
25
|
+
/** Maps sanitized adapter tool names back to their original ZuoraToolDefinition. */
|
|
26
|
+
private sanitizedToolMap;
|
|
27
|
+
/**
|
|
28
|
+
* Look up a ZuoraToolDefinition by its sanitized adapter tool name.
|
|
29
|
+
*
|
|
30
|
+
* The OpenAI Agents SDK registers tools with sanitized names (see convertTools),
|
|
31
|
+
* but external code may reference tools by their original MCP names. This method
|
|
32
|
+
* provides resolution in both directions.
|
|
33
|
+
*/
|
|
34
|
+
private resolveToolName;
|
|
35
|
+
/**
|
|
36
|
+
* Resolve a tool name that may be either sanitized or original MCP format.
|
|
37
|
+
*
|
|
38
|
+
* This provides additional name normalization to handle cases where:
|
|
39
|
+
* - A tool name contains unsanitized characters (like dots)
|
|
40
|
+
* - A tool name was learned from descriptions or logs
|
|
41
|
+
*
|
|
42
|
+
* We attempt to find a match with relaxed sanitization rules before giving up.
|
|
43
|
+
*/
|
|
44
|
+
private normalizeToolName;
|
|
45
|
+
/**
|
|
46
|
+
* Override callTool to provide flexible name resolution.
|
|
47
|
+
*
|
|
48
|
+
* The OpenAI Agents SDK may receive tool calls with names that were learned
|
|
49
|
+
* from descriptions or other sources (not directly from tool registration).
|
|
50
|
+
* This override allows us to handle both sanitized and original tool names
|
|
51
|
+
* by falling back to name normalization when the direct lookup fails.
|
|
52
|
+
*/
|
|
53
|
+
callTool(operationName: string, input: Record<string, unknown>): Promise<ZuoraToolExecutionResult>;
|
|
25
54
|
/**
|
|
26
55
|
* Serialises the agent tool response, emits an `agent.tool.response`
|
|
27
56
|
* observability event (with the response in `metadata` when
|
|
@@ -42,7 +71,7 @@ declare class ZuoraOpenAIAgentsToolkit extends ToolkitCore<AgentsFunctionTool> {
|
|
|
42
71
|
* import { createZuoraOpenAIAgentsToolkit } from "@zuora/agent-toolkit/openai-agents";
|
|
43
72
|
*
|
|
44
73
|
* const toolkit = await createZuoraOpenAIAgentsToolkit({ env: true });
|
|
45
|
-
* const tools = await toolkit.getTools({ bundles: ["query"], mode:
|
|
74
|
+
* const tools = await toolkit.getTools({ bundles: ["query"], mode: SafetyMode.ReadOnly });
|
|
46
75
|
* const agent = new Agent({ name: "Cli Agent", tools });
|
|
47
76
|
* const result = await run(agent, "How many active accounts?");
|
|
48
77
|
* ```
|
|
@@ -22,6 +22,10 @@ var ZuoraAgentToolkitError = class extends Error {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
// src/shared/types.ts
|
|
25
|
+
var SafetyMode = {
|
|
26
|
+
ReadOnly: "readOnly",
|
|
27
|
+
WriteEnabled: "writeEnabled"
|
|
28
|
+
};
|
|
25
29
|
var ApprovalPolicyPreset = {
|
|
26
30
|
Off: "off",
|
|
27
31
|
AllWrites: "all_writes",
|
|
@@ -117,15 +121,15 @@ var evaluatePreset = (preset, request) => {
|
|
|
117
121
|
const isProduction = environment === "production";
|
|
118
122
|
switch (preset) {
|
|
119
123
|
case ApprovalPolicyPreset.Off:
|
|
120
|
-
return "
|
|
124
|
+
return "allow";
|
|
121
125
|
case ApprovalPolicyPreset.AllWrites:
|
|
122
|
-
return isWrite ? "deny" : "
|
|
126
|
+
return isWrite ? "deny" : "allow";
|
|
123
127
|
case ApprovalPolicyPreset.HighRisk:
|
|
124
|
-
return isHighRisk ? "deny" : "
|
|
128
|
+
return isHighRisk ? "deny" : "allow";
|
|
125
129
|
case ApprovalPolicyPreset.ProductionWrites:
|
|
126
|
-
return isProduction && isWrite ? "deny" : "
|
|
130
|
+
return isProduction && isWrite ? "deny" : "allow";
|
|
127
131
|
case ApprovalPolicyPreset.ProductionHighRisk:
|
|
128
|
-
return isProduction && isHighRisk ? "deny" : "
|
|
132
|
+
return isProduction && isHighRisk ? "deny" : "allow";
|
|
129
133
|
}
|
|
130
134
|
};
|
|
131
135
|
var throwApprovalRejected = (tool2) => {
|
|
@@ -2600,26 +2604,11 @@ var readEnvAllowedHosts = () => {
|
|
|
2600
2604
|
const hosts = raw.split(",").map((host) => host.trim()).filter(Boolean);
|
|
2601
2605
|
return hosts.length > 0 ? hosts : void 0;
|
|
2602
2606
|
};
|
|
2603
|
-
var isQueryBundleConfigured = (configuration) => {
|
|
2604
|
-
const bundles = configuration?.bundles;
|
|
2605
|
-
if (!bundles) {
|
|
2606
|
-
return false;
|
|
2607
|
-
}
|
|
2608
|
-
const query = bundles.query;
|
|
2609
|
-
if (query === true) {
|
|
2610
|
-
return true;
|
|
2611
|
-
}
|
|
2612
|
-
return typeof query === "object" && query !== null;
|
|
2613
|
-
};
|
|
2614
2607
|
var resolveNativeFileToolsInput = (config) => {
|
|
2615
2608
|
const explicit = config.nativeFileTools;
|
|
2616
2609
|
if (explicit?.enabled === false) {
|
|
2617
2610
|
return { enabled: false };
|
|
2618
2611
|
}
|
|
2619
|
-
const autoEnable = isQueryBundleConfigured(config.configuration);
|
|
2620
|
-
if (!autoEnable && explicit?.enabled !== true) {
|
|
2621
|
-
return explicit;
|
|
2622
|
-
}
|
|
2623
2612
|
const rootDir = nonEmptyString(explicit?.rootDir) ?? nonEmptyString(process.env["ZUORA_NATIVE_FILE_ROOT"]) ?? DEFAULT_NATIVE_ARTIFACT_ROOT;
|
|
2624
2613
|
const allowedHosts = explicit?.allowedHosts ?? readEnvAllowedHosts() ?? DEFAULT_NATIVE_ALLOWED_HOSTS;
|
|
2625
2614
|
return {
|
|
@@ -3490,21 +3479,10 @@ var OAuthTokenProvider = class {
|
|
|
3490
3479
|
category: "auth"
|
|
3491
3480
|
});
|
|
3492
3481
|
}
|
|
3493
|
-
if (this.config.auth.type === "accessToken" && this.config.auth.accessToken) {
|
|
3494
|
-
this.accessToken = this.config.auth.accessToken;
|
|
3495
|
-
return this.config.auth.accessToken;
|
|
3496
|
-
}
|
|
3497
3482
|
const now = Date.now();
|
|
3498
3483
|
if (this.accessToken && this.isAccessTokenFresh(now)) {
|
|
3499
3484
|
return this.accessToken;
|
|
3500
3485
|
}
|
|
3501
|
-
if (this.config.auth.type !== "oauthClientCredentials") {
|
|
3502
|
-
throw new ZuoraAgentToolkitError({
|
|
3503
|
-
code: "UNSUPPORTED_AUTH",
|
|
3504
|
-
message: "Unsupported auth configuration for Zuora HTTP MCP client.",
|
|
3505
|
-
category: "auth"
|
|
3506
|
-
});
|
|
3507
|
-
}
|
|
3508
3486
|
const token = await this.fetchOAuthToken();
|
|
3509
3487
|
this.accessToken = token.access_token;
|
|
3510
3488
|
this.tokenIssuedAt = now;
|
|
@@ -3523,10 +3501,8 @@ var OAuthTokenProvider = class {
|
|
|
3523
3501
|
sensitiveValues() {
|
|
3524
3502
|
const values = [this.accessToken];
|
|
3525
3503
|
const auth = this.config.auth;
|
|
3526
|
-
if (auth?.
|
|
3504
|
+
if (auth?.clientSecret) {
|
|
3527
3505
|
values.push(auth.clientSecret);
|
|
3528
|
-
} else if (auth?.type === "accessToken") {
|
|
3529
|
-
values.push(auth.accessToken);
|
|
3530
3506
|
}
|
|
3531
3507
|
return values.filter(
|
|
3532
3508
|
(value) => typeof value === "string" && value.length > 0
|
|
@@ -3590,11 +3566,8 @@ var OAuthTokenProvider = class {
|
|
|
3590
3566
|
});
|
|
3591
3567
|
}
|
|
3592
3568
|
async resolveTokenEndpoints() {
|
|
3593
|
-
if (this.config.tokenEndpoint) {
|
|
3594
|
-
return [this.config.tokenEndpoint];
|
|
3595
|
-
}
|
|
3596
3569
|
const restEndpoint = `${this.restBaseUrl}/oauth/token`;
|
|
3597
|
-
const oneIdEndpoint =
|
|
3570
|
+
const oneIdEndpoint = isStagingZuoraBaseUrl(this.restBaseUrl) ? "https://one.stg.na.zuora.com/oauth2/token" : "https://one.zuora.com/oauth2/token";
|
|
3598
3571
|
const endpoints = [restEndpoint, oneIdEndpoint];
|
|
3599
3572
|
const uniqueEndpoints = [...new Set(endpoints)];
|
|
3600
3573
|
if (!this.preferredTokenEndpoint) {
|
|
@@ -3607,29 +3580,8 @@ var OAuthTokenProvider = class {
|
|
|
3607
3580
|
)
|
|
3608
3581
|
];
|
|
3609
3582
|
}
|
|
3610
|
-
async resolveOneIdTokenEndpoint() {
|
|
3611
|
-
const fallback = isStagingZuoraBaseUrl(this.restBaseUrl) ? "https://one.stg.na.zuora.com/oauth2/token" : "https://one.zuora.com/oauth2/token";
|
|
3612
|
-
try {
|
|
3613
|
-
return await this.discoverTokenEndpoint() ?? fallback;
|
|
3614
|
-
} catch {
|
|
3615
|
-
return fallback;
|
|
3616
|
-
}
|
|
3617
|
-
}
|
|
3618
|
-
async discoverTokenEndpoint() {
|
|
3619
|
-
const metadataUrl = new URL(this.restBaseUrl);
|
|
3620
|
-
metadataUrl.pathname = "/.well-known/oauth-authorization-server";
|
|
3621
|
-
metadataUrl.search = "";
|
|
3622
|
-
const response = await fetch(metadataUrl, {
|
|
3623
|
-
headers: { accept: "application/json" }
|
|
3624
|
-
});
|
|
3625
|
-
if (!response.ok) {
|
|
3626
|
-
return void 0;
|
|
3627
|
-
}
|
|
3628
|
-
const metadata = await response.json().catch(() => ({}));
|
|
3629
|
-
return metadata.token_endpoint;
|
|
3630
|
-
}
|
|
3631
3583
|
async requestOAuthToken(tokenEndpoint) {
|
|
3632
|
-
if (!this.config.auth
|
|
3584
|
+
if (!this.config.auth) {
|
|
3633
3585
|
throw new ZuoraAgentToolkitError({
|
|
3634
3586
|
code: "UNSUPPORTED_AUTH",
|
|
3635
3587
|
message: "Unsupported auth configuration for Zuora HTTP MCP client.",
|
|
@@ -3642,17 +3594,8 @@ var OAuthTokenProvider = class {
|
|
|
3642
3594
|
accept: "application/json"
|
|
3643
3595
|
};
|
|
3644
3596
|
const auth = this.config.auth;
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
`${auth.clientId}:${auth.clientSecret}`
|
|
3648
|
-
)}`;
|
|
3649
|
-
} else {
|
|
3650
|
-
body.set("client_id", auth.clientId);
|
|
3651
|
-
body.set("client_secret", auth.clientSecret);
|
|
3652
|
-
}
|
|
3653
|
-
if (auth.scope) {
|
|
3654
|
-
body.set("scope", auth.scope);
|
|
3655
|
-
}
|
|
3597
|
+
body.set("client_id", auth.clientId);
|
|
3598
|
+
body.set("client_secret", auth.clientSecret);
|
|
3656
3599
|
const response = await fetch(tokenEndpoint, {
|
|
3657
3600
|
method: "POST",
|
|
3658
3601
|
headers,
|
|
@@ -3694,7 +3637,6 @@ var extractTenantId = (scope) => {
|
|
|
3694
3637
|
const tenantMatch = scope?.match(/tenant\.(\d+)/);
|
|
3695
3638
|
return tenantMatch?.[1];
|
|
3696
3639
|
};
|
|
3697
|
-
var base64Encode = (value) => Buffer.from(value).toString("base64");
|
|
3698
3640
|
|
|
3699
3641
|
// src/shared/transport/request-headers.ts
|
|
3700
3642
|
var RESERVED_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
@@ -3766,10 +3708,8 @@ var resolveZuoraConnectionConfig = (config, mcpUrl) => ({
|
|
|
3766
3708
|
clientName: config.clientName ?? "zuora-agent-toolkit",
|
|
3767
3709
|
clientVersion: config.clientVersion ?? "0.1.0",
|
|
3768
3710
|
protocolVersion: config.protocolVersion ?? "2025-03-26",
|
|
3769
|
-
tokenAuthMethod: config.tokenAuthMethod ?? "client_secret_post",
|
|
3770
3711
|
url: mcpUrl,
|
|
3771
3712
|
...config.auth ? { auth: config.auth } : {},
|
|
3772
|
-
...config.tokenEndpoint ? { tokenEndpoint: config.tokenEndpoint } : {},
|
|
3773
3713
|
...config.headers ? { headers: config.headers } : {},
|
|
3774
3714
|
...config.tenantAuth ? { tenantAuth: config.tenantAuth } : {},
|
|
3775
3715
|
...config.entityIds ? { entityIds: config.entityIds } : {},
|
|
@@ -3950,7 +3890,7 @@ var resolveToolSelectionPolicy = (configuration, selection) => ({
|
|
|
3950
3890
|
...selection?.exclude ?? []
|
|
3951
3891
|
])
|
|
3952
3892
|
});
|
|
3953
|
-
var resolveToolMode = (configuration, selection) => selection?.mode ?? configuration?.mode ??
|
|
3893
|
+
var resolveToolMode = (configuration, selection) => selection?.mode ?? configuration?.mode ?? SafetyMode.ReadOnly;
|
|
3954
3894
|
var resolveExcludedToolNames = (configuration) => /* @__PURE__ */ new Set([
|
|
3955
3895
|
...resolveConfiguredExcludedToolNames(configuration),
|
|
3956
3896
|
...resolveBundleExcludedToolNames(configuration)
|
|
@@ -4212,11 +4152,19 @@ var ZuoraHttpMcpClient = class _ZuoraHttpMcpClient extends ZuoraClient {
|
|
|
4212
4152
|
|
|
4213
4153
|
// src/shared/toolkit-core.ts
|
|
4214
4154
|
var createHttpMcpClientConfig = (config) => {
|
|
4215
|
-
|
|
4155
|
+
const contextEntityIds = config.configuration?.context?.entityIds;
|
|
4156
|
+
const contextOrgIds = config.configuration?.context?.orgIds;
|
|
4157
|
+
const contextOverrides = {
|
|
4158
|
+
...contextEntityIds ? { entityIds: contextEntityIds } : {},
|
|
4159
|
+
...contextOrgIds ? { orgIds: contextOrgIds } : {}
|
|
4160
|
+
};
|
|
4161
|
+
const connection = "connection" in config ? config.connection : void 0;
|
|
4162
|
+
if (isTenantAuthConnection(connection)) {
|
|
4216
4163
|
return {
|
|
4217
4164
|
url: config.baseUrl,
|
|
4218
4165
|
...config.auth ? { auth: config.auth } : {},
|
|
4219
|
-
...
|
|
4166
|
+
...connection,
|
|
4167
|
+
...contextOverrides
|
|
4220
4168
|
};
|
|
4221
4169
|
}
|
|
4222
4170
|
if (!config.auth) {
|
|
@@ -4229,13 +4177,23 @@ var createHttpMcpClientConfig = (config) => {
|
|
|
4229
4177
|
return {
|
|
4230
4178
|
url: config.baseUrl,
|
|
4231
4179
|
auth: config.auth,
|
|
4232
|
-
...
|
|
4180
|
+
...connection ?? {},
|
|
4181
|
+
...contextOverrides
|
|
4233
4182
|
};
|
|
4234
4183
|
};
|
|
4235
4184
|
var isTenantAuthConnection = (connection) => connection?.tenantAuth?.enabled === true;
|
|
4236
4185
|
var filterCatalogTools = (tools, policy) => tools.filter((tool2) => {
|
|
4237
|
-
if (policy.mode ===
|
|
4238
|
-
|
|
4186
|
+
if (policy.mode === SafetyMode.ReadOnly) {
|
|
4187
|
+
if (tool2.meta.operationAccess) {
|
|
4188
|
+
const hasReadOperation = Object.values(tool2.meta.operationAccess).some(
|
|
4189
|
+
(access) => access === "read"
|
|
4190
|
+
);
|
|
4191
|
+
if (!hasReadOperation) {
|
|
4192
|
+
return false;
|
|
4193
|
+
}
|
|
4194
|
+
} else if (tool2.meta.access === "write") {
|
|
4195
|
+
return false;
|
|
4196
|
+
}
|
|
4239
4197
|
}
|
|
4240
4198
|
if (policy.bundles.size > 0 && !policy.bundles.has(tool2.meta.bundle)) {
|
|
4241
4199
|
return false;
|
|
@@ -4396,19 +4354,19 @@ var ToolkitCore = class {
|
|
|
4396
4354
|
category: "configuration"
|
|
4397
4355
|
});
|
|
4398
4356
|
}
|
|
4399
|
-
const mode = this.config.configuration?.mode ??
|
|
4400
|
-
if (mode === "readOnly" && tool2.meta.access === "write") {
|
|
4401
|
-
throw new ZuoraAgentToolkitError({
|
|
4402
|
-
code: "TOOL_EXECUTION_ERROR",
|
|
4403
|
-
message: `Write tool "${operationName}" is disabled in readOnly mode.`,
|
|
4404
|
-
category: "tool_execution"
|
|
4405
|
-
});
|
|
4406
|
-
}
|
|
4357
|
+
const mode = this.config.configuration?.mode ?? SafetyMode.ReadOnly;
|
|
4407
4358
|
const nativeRuntimeTool = this.nativeToolRegistry?.get(operationName);
|
|
4408
4359
|
const nativeApprovalMetadata = nativeRuntimeTool?.approvalMetadata(input);
|
|
4409
4360
|
const invokedOperation = tool2.meta.operationSelector ? String(input[tool2.meta.operationSelector] ?? "") : void 0;
|
|
4410
4361
|
const effectiveAccess = (invokedOperation ? tool2.meta.operationAccess?.[invokedOperation] : void 0) ?? tool2.meta.access;
|
|
4411
4362
|
const effectiveRiskLevel = (invokedOperation ? tool2.meta.operationRiskLevel?.[invokedOperation] : void 0) ?? tool2.meta.riskLevel;
|
|
4363
|
+
if (mode === SafetyMode.ReadOnly && effectiveAccess === "write") {
|
|
4364
|
+
throw new ZuoraAgentToolkitError({
|
|
4365
|
+
code: "TOOL_EXECUTION_ERROR",
|
|
4366
|
+
message: `Write operation "${invokedOperation ?? operationName}" is disabled in readOnly mode.`,
|
|
4367
|
+
category: "tool_execution"
|
|
4368
|
+
});
|
|
4369
|
+
}
|
|
4412
4370
|
const effectiveTool = effectiveAccess === tool2.meta.access && effectiveRiskLevel === tool2.meta.riskLevel ? tool2 : { ...tool2, meta: { ...tool2.meta, access: effectiveAccess, riskLevel: effectiveRiskLevel } };
|
|
4413
4371
|
await enforceApproval(
|
|
4414
4372
|
effectiveTool,
|
|
@@ -4642,7 +4600,7 @@ var ToolkitCore = class {
|
|
|
4642
4600
|
return this.catalogTools ?? [];
|
|
4643
4601
|
}
|
|
4644
4602
|
resolveSplitOperations() {
|
|
4645
|
-
return this.config.configuration?.splitOperations ??
|
|
4603
|
+
return this.config.configuration?.splitOperations ?? false;
|
|
4646
4604
|
}
|
|
4647
4605
|
warnIfNotInitialized() {
|
|
4648
4606
|
if (!this._initialized) {
|
|
@@ -4711,13 +4669,11 @@ var ToolkitCore = class {
|
|
|
4711
4669
|
}
|
|
4712
4670
|
createEventContext() {
|
|
4713
4671
|
const configurationContext = this.config.configuration?.context ?? {};
|
|
4714
|
-
const tenantId = nonEmptyString(configurationContext.tenantId) ?? nonEmptyString(configurationContext.tenant_id);
|
|
4715
4672
|
const entityIds = normalizeIdList(configurationContext.entityIds) ?? normalizeIdList(configurationContext.entityId);
|
|
4716
4673
|
const orgIds = normalizeIdList(configurationContext.orgIds) ?? normalizeIdList(configurationContext.orgId);
|
|
4717
4674
|
const environment = inferZuoraEnvironment(this.config.baseUrl) ?? "sandbox";
|
|
4718
4675
|
return {
|
|
4719
4676
|
environment,
|
|
4720
|
-
...tenantId ? { tenantId } : {},
|
|
4721
4677
|
...entityIds ? { entityIds } : {},
|
|
4722
4678
|
...orgIds ? { orgIds } : {}
|
|
4723
4679
|
};
|
|
@@ -4809,51 +4765,21 @@ var readBooleanEnvValue = (name, rawValue) => {
|
|
|
4809
4765
|
var readBooleanEnv = (env, name) => readBooleanEnvValue(name, env[name]);
|
|
4810
4766
|
var readZuoraEndpoint = (env) => readTrimmedEnv(env, "ZUORA_BASE_URL") ?? readTrimmedEnv(env, "ZUORA_MCP_URL");
|
|
4811
4767
|
var readToolkitMode = (env) => {
|
|
4812
|
-
const mode = env.ZUORA_TOOLKIT_MODE?.trim() ??
|
|
4813
|
-
if (mode ===
|
|
4768
|
+
const mode = env.ZUORA_TOOLKIT_MODE?.trim() ?? SafetyMode.ReadOnly;
|
|
4769
|
+
if (mode === SafetyMode.ReadOnly || mode === SafetyMode.WriteEnabled) {
|
|
4814
4770
|
return mode;
|
|
4815
4771
|
}
|
|
4816
4772
|
throw new Error(
|
|
4817
|
-
`Invalid ZUORA_TOOLKIT_MODE: ${mode}. Expected
|
|
4818
|
-
);
|
|
4819
|
-
};
|
|
4820
|
-
var readOptionalUrlEnv = (env, name) => {
|
|
4821
|
-
const value = readTrimmedEnv(env, name);
|
|
4822
|
-
if (!value) {
|
|
4823
|
-
return void 0;
|
|
4824
|
-
}
|
|
4825
|
-
try {
|
|
4826
|
-
const url = new URL(value);
|
|
4827
|
-
if (url.protocol === "http:" || url.protocol === "https:") {
|
|
4828
|
-
return url.toString();
|
|
4829
|
-
}
|
|
4830
|
-
} catch {
|
|
4831
|
-
}
|
|
4832
|
-
throw new Error(`${name} must be an absolute HTTP(S) URL.`);
|
|
4833
|
-
};
|
|
4834
|
-
var readTokenAuthMethodEnv = (env) => {
|
|
4835
|
-
const value = readTrimmedEnv(env, "ZUORA_TOKEN_AUTH_METHOD");
|
|
4836
|
-
if (!value) {
|
|
4837
|
-
return void 0;
|
|
4838
|
-
}
|
|
4839
|
-
if (value === "client_secret_post" || value === "client_secret_basic") {
|
|
4840
|
-
return value;
|
|
4841
|
-
}
|
|
4842
|
-
throw new Error(
|
|
4843
|
-
"Invalid ZUORA_TOKEN_AUTH_METHOD: expected client_secret_post or client_secret_basic."
|
|
4773
|
+
`Invalid ZUORA_TOOLKIT_MODE: ${mode}. Expected ${SafetyMode.ReadOnly} or ${SafetyMode.WriteEnabled}.`
|
|
4844
4774
|
);
|
|
4845
4775
|
};
|
|
4846
4776
|
var readConnectionOptions = (env) => {
|
|
4847
|
-
const tokenEndpoint = readOptionalUrlEnv(env, "ZUORA_TOKEN_ENDPOINT");
|
|
4848
|
-
const tokenAuthMethod = readTokenAuthMethodEnv(env);
|
|
4849
4777
|
const entityIds = readTrimmedEnv(env, "ZUORA_ENTITY_IDS");
|
|
4850
4778
|
const orgIds = readTrimmedEnv(env, "ZUORA_ORG_IDS");
|
|
4851
4779
|
const zuoraVersion = readTrimmedEnv(env, "ZUORA_VERSION");
|
|
4852
4780
|
return {
|
|
4853
4781
|
...entityIds ? { entityIds } : {},
|
|
4854
4782
|
...orgIds ? { orgIds } : {},
|
|
4855
|
-
...tokenEndpoint ? { tokenEndpoint } : {},
|
|
4856
|
-
...tokenAuthMethod ? { tokenAuthMethod } : {},
|
|
4857
4783
|
...zuoraVersion ? { zuoraVersion } : {}
|
|
4858
4784
|
};
|
|
4859
4785
|
};
|
|
@@ -4878,28 +4804,19 @@ var zuoraAgentToolkitConfigFromEnv = (env = process.env) => {
|
|
|
4878
4804
|
}
|
|
4879
4805
|
},
|
|
4880
4806
|
configuration: {
|
|
4881
|
-
mode
|
|
4882
|
-
context: {
|
|
4883
|
-
tenantId
|
|
4884
|
-
}
|
|
4807
|
+
mode
|
|
4885
4808
|
}
|
|
4886
4809
|
};
|
|
4887
4810
|
}
|
|
4888
4811
|
return {
|
|
4889
4812
|
baseUrl,
|
|
4890
4813
|
auth: {
|
|
4891
|
-
type: "oauthClientCredentials",
|
|
4892
4814
|
clientId: requiredEnv(env, "ZUORA_CLIENT_ID"),
|
|
4893
4815
|
clientSecret: requiredEnv(env, "ZUORA_CLIENT_SECRET")
|
|
4894
4816
|
},
|
|
4895
4817
|
...Object.keys(connection).length > 0 ? { connection } : {},
|
|
4896
4818
|
configuration: {
|
|
4897
|
-
mode
|
|
4898
|
-
...readTrimmedEnv(env, "ZUORA_TENANT_ID") ? {
|
|
4899
|
-
context: {
|
|
4900
|
-
tenantId: readTrimmedEnv(env, "ZUORA_TENANT_ID")
|
|
4901
|
-
}
|
|
4902
|
-
} : {}
|
|
4819
|
+
mode
|
|
4903
4820
|
}
|
|
4904
4821
|
};
|
|
4905
4822
|
};
|
|
@@ -5067,6 +4984,79 @@ var strictifySchema = (schema) => {
|
|
|
5067
4984
|
|
|
5068
4985
|
// src/openai-agents/toolkit.ts
|
|
5069
4986
|
var ZuoraOpenAIAgentsToolkit = class extends ToolkitCore {
|
|
4987
|
+
/** Maps sanitized adapter tool names back to their original ZuoraToolDefinition. */
|
|
4988
|
+
sanitizedToolMap = /* @__PURE__ */ new Map();
|
|
4989
|
+
/**
|
|
4990
|
+
* Look up a ZuoraToolDefinition by its sanitized adapter tool name.
|
|
4991
|
+
*
|
|
4992
|
+
* The OpenAI Agents SDK registers tools with sanitized names (see convertTools),
|
|
4993
|
+
* but external code may reference tools by their original MCP names. This method
|
|
4994
|
+
* provides resolution in both directions.
|
|
4995
|
+
*/
|
|
4996
|
+
resolveToolName(name) {
|
|
4997
|
+
if (this.sanitizedToolMap.has(name)) {
|
|
4998
|
+
return name;
|
|
4999
|
+
}
|
|
5000
|
+
for (const [sanitized, def] of this.sanitizedToolMap) {
|
|
5001
|
+
if (def.name === name) {
|
|
5002
|
+
return sanitized;
|
|
5003
|
+
}
|
|
5004
|
+
}
|
|
5005
|
+
return void 0;
|
|
5006
|
+
}
|
|
5007
|
+
/**
|
|
5008
|
+
* Resolve a tool name that may be either sanitized or original MCP format.
|
|
5009
|
+
*
|
|
5010
|
+
* This provides additional name normalization to handle cases where:
|
|
5011
|
+
* - A tool name contains unsanitized characters (like dots)
|
|
5012
|
+
* - A tool name was learned from descriptions or logs
|
|
5013
|
+
*
|
|
5014
|
+
* We attempt to find a match with relaxed sanitization rules before giving up.
|
|
5015
|
+
*/
|
|
5016
|
+
normalizeToolName(name) {
|
|
5017
|
+
const directMatch = this.resolveToolName(name);
|
|
5018
|
+
if (directMatch) {
|
|
5019
|
+
return directMatch;
|
|
5020
|
+
}
|
|
5021
|
+
const normalized = name.replace(/\./g, "_");
|
|
5022
|
+
const normalizedMatch = this.resolveToolName(normalized);
|
|
5023
|
+
if (normalizedMatch) {
|
|
5024
|
+
return normalizedMatch;
|
|
5025
|
+
}
|
|
5026
|
+
for (const [sanitized, def] of this.sanitizedToolMap) {
|
|
5027
|
+
if (def.name === normalized) {
|
|
5028
|
+
return sanitized;
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
5031
|
+
return void 0;
|
|
5032
|
+
}
|
|
5033
|
+
/**
|
|
5034
|
+
* Override callTool to provide flexible name resolution.
|
|
5035
|
+
*
|
|
5036
|
+
* The OpenAI Agents SDK may receive tool calls with names that were learned
|
|
5037
|
+
* from descriptions or other sources (not directly from tool registration).
|
|
5038
|
+
* This override allows us to handle both sanitized and original tool names
|
|
5039
|
+
* by falling back to name normalization when the direct lookup fails.
|
|
5040
|
+
*/
|
|
5041
|
+
async callTool(operationName, input) {
|
|
5042
|
+
try {
|
|
5043
|
+
return await super.callTool(operationName, input);
|
|
5044
|
+
} catch (error) {
|
|
5045
|
+
if (error instanceof Error && (error.message.includes("Unknown Zuora tool") || error.message.includes("TOOL_NOT_FOUND"))) {
|
|
5046
|
+
const sanitized = this.normalizeToolName(operationName);
|
|
5047
|
+
if (sanitized) {
|
|
5048
|
+
const def = this.sanitizedToolMap.get(sanitized);
|
|
5049
|
+
if (def) {
|
|
5050
|
+
console.warn(
|
|
5051
|
+
`[zuora-agent-toolkit] Tool name normalized: "${operationName}" -> "${def.name}" (sanitized: "${sanitized}")`
|
|
5052
|
+
);
|
|
5053
|
+
return await super.callTool(def.name, input);
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
}
|
|
5057
|
+
throw error;
|
|
5058
|
+
}
|
|
5059
|
+
}
|
|
5070
5060
|
/**
|
|
5071
5061
|
* Serialises the agent tool response, emits an `agent.tool.response`
|
|
5072
5062
|
* observability event (with the response in `metadata` when
|
|
@@ -5090,6 +5080,7 @@ var ZuoraOpenAIAgentsToolkit = class extends ToolkitCore {
|
|
|
5090
5080
|
convertTools(tools) {
|
|
5091
5081
|
return tools.map((def) => {
|
|
5092
5082
|
const sanitizedName = sanitizeAdapterToolName(def.name);
|
|
5083
|
+
this.sanitizedToolMap.set(sanitizedName, def);
|
|
5093
5084
|
return tool({
|
|
5094
5085
|
name: sanitizedName,
|
|
5095
5086
|
description: def.description,
|