@neuraltrust/trustgate 0.1.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.
Files changed (63) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +132 -0
  3. package/dist/agent.d.ts +156 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +216 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/client.d.ts +88 -0
  8. package/dist/client.d.ts.map +1 -0
  9. package/dist/client.js +152 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/config.d.ts +44 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +40 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/connections.d.ts +13 -0
  16. package/dist/connections.d.ts.map +1 -0
  17. package/dist/connections.js +46 -0
  18. package/dist/connections.js.map +1 -0
  19. package/dist/errors.d.ts +91 -0
  20. package/dist/errors.d.ts.map +1 -0
  21. package/dist/errors.js +144 -0
  22. package/dist/errors.js.map +1 -0
  23. package/dist/formats.d.ts +44 -0
  24. package/dist/formats.d.ts.map +1 -0
  25. package/dist/formats.js +299 -0
  26. package/dist/formats.js.map +1 -0
  27. package/dist/http.d.ts +23 -0
  28. package/dist/http.d.ts.map +1 -0
  29. package/dist/http.js +94 -0
  30. package/dist/http.js.map +1 -0
  31. package/dist/index.d.ts +10 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +10 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/mcp.d.ts +43 -0
  36. package/dist/mcp.d.ts.map +1 -0
  37. package/dist/mcp.js +175 -0
  38. package/dist/mcp.js.map +1 -0
  39. package/dist/schema.d.ts +52 -0
  40. package/dist/schema.d.ts.map +1 -0
  41. package/dist/schema.js +168 -0
  42. package/dist/schema.js.map +1 -0
  43. package/dist/types.d.ts +78 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +52 -0
  46. package/dist/types.js.map +1 -0
  47. package/dist/whoami.d.ts +73 -0
  48. package/dist/whoami.d.ts.map +1 -0
  49. package/dist/whoami.js +79 -0
  50. package/dist/whoami.js.map +1 -0
  51. package/package.json +29 -0
  52. package/src/agent.ts +267 -0
  53. package/src/client.ts +203 -0
  54. package/src/config.ts +78 -0
  55. package/src/connections.ts +90 -0
  56. package/src/errors.ts +154 -0
  57. package/src/formats.ts +362 -0
  58. package/src/http.ts +106 -0
  59. package/src/index.ts +41 -0
  60. package/src/mcp.ts +203 -0
  61. package/src/schema.ts +193 -0
  62. package/src/types.ts +98 -0
  63. package/src/whoami.ts +172 -0
package/dist/agent.js ADDED
@@ -0,0 +1,216 @@
1
+ import { END_USER_HEADER } from './config.js';
2
+ import { createConnectLink, listConnections, requireEndUser } from './connections.js';
3
+ import { ToolNotFoundError } from './errors.js';
4
+ import { adapterFor, restoreArguments } from './formats.js';
5
+ import { MCPTransport } from './mcp.js';
6
+ import { Actor, resolveToolName, } from './types.js';
7
+ /**
8
+ * A tool surface in one provider's dialect, with the executor that belongs to
9
+ * it.
10
+ *
11
+ * They travel together because they are two halves of one translation: what
12
+ * `tools` added on the way out, `execute` has to undo on the way back.
13
+ *
14
+ * `Tool` and `Output` are the provider's own types, named by the caller:
15
+ *
16
+ * ```ts
17
+ * const { tools, execute } = agent.toolkit<
18
+ * OpenAI.Responses.Tool,
19
+ * OpenAI.Responses.ResponseInputItem
20
+ * >(ToolFormat.OpenAIResponses)
21
+ * ```
22
+ *
23
+ * They default to `unknown`, so nothing breaks by leaving them out — but then
24
+ * "pass this straight to the provider's API" is a promise the type does not
25
+ * keep, and the caller casts at the boundary. The SDK cannot name them itself:
26
+ * it carries no dependency on any provider's package, which is what lets one
27
+ * install serve all of them.
28
+ */
29
+ export class Toolkit {
30
+ tools;
31
+ warnings;
32
+ format;
33
+ originals;
34
+ transport;
35
+ constructor(
36
+ /** Pass this straight to the provider's API. */
37
+ tools,
38
+ /** Tools whose schema could not be expressed in the requested dialect. */
39
+ warnings, format, originals, transport) {
40
+ this.tools = tools;
41
+ this.warnings = warnings;
42
+ this.format = format;
43
+ this.originals = originals;
44
+ this.transport = transport;
45
+ // Bound, because the documented way to use this is to destructure it —
46
+ // `const { tools, execute } = agent.toolkit(…)` — and an unbound method
47
+ // loses the format it needs the moment it is called that way.
48
+ this.calls = this.calls.bind(this);
49
+ this.execute = this.execute.bind(this);
50
+ }
51
+ /** The calls the model asked for, read out of the provider's response. */
52
+ calls(output) {
53
+ return adapterFor(this.format).extractCalls(output);
54
+ }
55
+ /**
56
+ * Runs the calls the model asked for and returns what to send back.
57
+ *
58
+ * Every call goes to the gateway, so the policy, the audit trail and the
59
+ * upstream credentials stay where they were. The caller's process only
60
+ * decides whether to make the call at all.
61
+ */
62
+ async execute(output, signal) {
63
+ const adapter = adapterFor(this.format);
64
+ const calls = adapter.extractCalls(output);
65
+ const results = [];
66
+ for (const call of calls) {
67
+ const args = restoreArguments(call.arguments, this.originals.get(call.name));
68
+ const result = await this.transport.callTool(call.name, args, signal);
69
+ results.push({ call, result });
70
+ }
71
+ return adapter.toOutputs(results);
72
+ }
73
+ }
74
+ /**
75
+ * An application's handle on its gateway.
76
+ *
77
+ * It speaks as the application itself: one principal, its own upstream
78
+ * accounts, nothing per-user. Which handle you get is not a choice made here —
79
+ * it follows from how the consumer was configured, which is why `connect()`
80
+ * returns one of these or refuses.
81
+ */
82
+ export class Agent {
83
+ config;
84
+ slug;
85
+ transport;
86
+ tools;
87
+ missing;
88
+ connections;
89
+ actor = Actor.Application;
90
+ constructor(config, slug, transport,
91
+ /** The tools this consumer serves, as the gateway named them. */
92
+ tools,
93
+ /** Tools asked for in `requires` that the toolkit does not carry. */
94
+ missing,
95
+ /** The application's own upstream accounts, as of `connect()`. */
96
+ connections) {
97
+ this.config = config;
98
+ this.slug = slug;
99
+ this.transport = transport;
100
+ this.tools = tools;
101
+ this.missing = missing;
102
+ this.connections = connections;
103
+ }
104
+ /** URL and headers for a framework that brings its own MCP client. */
105
+ get mcp() {
106
+ return { url: this.transport.url, headers: this.transport.headers };
107
+ }
108
+ /**
109
+ * The same surface, translated for a provider you call directly.
110
+ *
111
+ * Name the provider's types to have them travel with it:
112
+ * `toolkit<OpenAI.Responses.Tool, OpenAI.Responses.ResponseInputItem>(…)`.
113
+ */
114
+ toolkit(format, options = {}) {
115
+ const { tools, warnings, originals } = adapterFor(format).convert(this.tools, {
116
+ strict: options.strict ?? false,
117
+ });
118
+ return new Toolkit(tools, warnings, format, originals, this.transport);
119
+ }
120
+ /**
121
+ * One tool, called directly. The escape hatch under the toolkits.
122
+ *
123
+ * The server prefix is optional here: "list_issues" reaches
124
+ * "linear_list_issues" while Linear is the only server of this application
125
+ * that serves it. The gateway put that prefix there, so a caller writing the
126
+ * name by hand should not have to.
127
+ */
128
+ async callTool(name, args = {}, signal) {
129
+ return this.transport.callTool(resolveToolName(name, this.tools), args, signal);
130
+ }
131
+ /**
132
+ * Re-reads the surface.
133
+ *
134
+ * An admin owns this toolkit and can change it under a running agent, so a
135
+ * long-lived process re-reads rather than trusting the list it took at
136
+ * startup.
137
+ */
138
+ async refresh(signal) {
139
+ this.tools = await this.transport.listTools(signal);
140
+ return this.tools;
141
+ }
142
+ /** What the application still owes before it can call every server. */
143
+ async refreshConnections(signal) {
144
+ return listConnections(this.config, this.slug, undefined, signal);
145
+ }
146
+ /**
147
+ * The same application, acting for one named person.
148
+ *
149
+ * No round trip and no second surface to read: the toolkit an admin bound
150
+ * is the application's, identical for everyone it acts for. What changes is
151
+ * one header, and with it whose upstream account the gateway reaches for.
152
+ */
153
+ forEndUser(endUser) {
154
+ return endUserAgent(this.config, this.slug, endUser, this.transport.url, this.tools);
155
+ }
156
+ }
157
+ /**
158
+ * An application's handle for one of its own end users.
159
+ *
160
+ * The user travels in a header, so a handle is a header and nothing more —
161
+ * but the MCP endpoint's headers are fixed when a client connects, which is
162
+ * why each user needs their own transport rather than a shared one.
163
+ */
164
+ export class EndUserAgent {
165
+ config;
166
+ slug;
167
+ endUser;
168
+ transport;
169
+ tools;
170
+ actor = Actor.EndUser;
171
+ constructor(config, slug, endUser, transport, tools) {
172
+ this.config = config;
173
+ this.slug = slug;
174
+ this.endUser = endUser;
175
+ this.transport = transport;
176
+ this.tools = tools;
177
+ }
178
+ get mcp() {
179
+ return { url: this.transport.url, headers: this.transport.headers };
180
+ }
181
+ toolkit(format, options = {}) {
182
+ const { tools, warnings, originals } = adapterFor(format).convert(this.tools, {
183
+ strict: options.strict ?? false,
184
+ });
185
+ return new Toolkit(tools, warnings, format, originals, this.transport);
186
+ }
187
+ async callTool(name, args = {}, signal) {
188
+ return this.transport.callTool(name, args, signal);
189
+ }
190
+ async refresh(signal) {
191
+ this.tools = await this.transport.listTools(signal);
192
+ return this.tools;
193
+ }
194
+ /** Which servers this user has connected, and which they have not. */
195
+ async connections(signal) {
196
+ return listConnections(this.config, this.slug, this.endUser, signal);
197
+ }
198
+ /**
199
+ * The page to put in front of this user so they can connect an account.
200
+ *
201
+ * Naming a provider narrows it to that one server; omitting it covers every
202
+ * server of the application that forwards a credential. The link expires,
203
+ * so it is minted when it is about to be shown, not cached.
204
+ */
205
+ async connectLink(provider, signal) {
206
+ return createConnectLink(this.config, this.slug, this.endUser, provider, signal);
207
+ }
208
+ }
209
+ /** Builds the per-user handle, with the header that names them. */
210
+ export function endUserAgent(config, slug, rawEndUser, url, tools) {
211
+ const endUser = requireEndUser(rawEndUser);
212
+ const transport = new MCPTransport(config, url, { [END_USER_HEADER]: endUser });
213
+ return new EndUserAgent(config, slug, endUser, transport, tools);
214
+ }
215
+ export { ToolNotFoundError };
216
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import { Agent, EndUserAgent } from './agent.js';
2
+ import { type TrustGateConfig } from './config.js';
3
+ import { type KeyIdentity } from './whoami.js';
4
+ export type ConnectOptions = {
5
+ /**
6
+ * Tool names this agent is written around.
7
+ *
8
+ * The toolkit belongs to an admin, not to the code that uses it, so it can
9
+ * be narrowed without warning. Declaring what you need turns that into a
10
+ * refusal at startup instead of a failure mid-conversation.
11
+ */
12
+ requires?: string[];
13
+ signal?: AbortSignal;
14
+ };
15
+ /** What the LLM plane needs to be handed to a provider's own client. */
16
+ export type LLMEndpoint = {
17
+ /** Pass as `baseURL` to the OpenAI client. It ends in `/v1`. */
18
+ baseUrl: string;
19
+ /**
20
+ * Pass as `baseURL` to the Anthropic client.
21
+ *
22
+ * The two clients disagree on where the version goes. OpenAI's is handed a
23
+ * base that already ends in `/v1` and appends `/chat/completions`;
24
+ * Anthropic's appends `/v1/messages` to what it is given, so handing it
25
+ * `baseUrl` asks the gateway for `/v1/v1/messages`. This is the
26
+ * application's root, the one every dialect but OpenAI's hangs from.
27
+ */
28
+ anthropicBaseUrl: string;
29
+ apiKey: string;
30
+ headers: Record<string, string>;
31
+ /** The consumer behind it, for logs and for error messages. */
32
+ consumer: string;
33
+ };
34
+ /**
35
+ * The entry point: a gateway and a key, and everything else is asked for.
36
+ *
37
+ * The key is attached to consumers, and a consumer has one type — so the tools
38
+ * live behind an MCP consumer and the models behind an LLM one. Their slugs
39
+ * were chosen by whoever created them, and the two planes do not share a host,
40
+ * so neither is something a caller should have to carry: the gateway is asked
41
+ * once, at `connect()`, and answers both.
42
+ */
43
+ export declare class TrustGate {
44
+ private readonly config;
45
+ private identityPromise?;
46
+ constructor(config?: TrustGateConfig);
47
+ /**
48
+ * What this key reaches. Read once and remembered: it is a property of the
49
+ * key, and a long-lived process should not re-ask on every call.
50
+ */
51
+ identity(signal?: AbortSignal): Promise<KeyIdentity>;
52
+ /**
53
+ * The LLM plane, ready for a provider's own SDK.
54
+ *
55
+ * The gateway speaks the providers' own APIs, so nothing here wraps their
56
+ * clients — it points them somewhere else. Wrapping would mean chasing
57
+ * every change they make and breaking streaming on the way.
58
+ */
59
+ llm(signal?: AbortSignal): Promise<LLMEndpoint>;
60
+ /**
61
+ * Opens the application's own surface and proves it is usable before
62
+ * anything runs.
63
+ *
64
+ * Two things happen here, and both are the kind that are cheap now and
65
+ * expensive later: whether the tools the agent needs are actually on its
66
+ * toolkit, and whether the servers behind it have an account to call with.
67
+ * The second has no runtime remedy for this handle — nobody is present to
68
+ * open a connect link once a batch is going — which is the whole reason it
69
+ * is checked at startup.
70
+ *
71
+ * This is the application actor: the key and nothing else, so the gateway
72
+ * runs the calls as `app:<consumer_id>`. For a call on behalf of a person,
73
+ * use {@link forEndUser}; both work on the same consumer, because who a
74
+ * request runs as is read from the request rather than declared anywhere.
75
+ */
76
+ connect(options?: ConnectOptions): Promise<Agent>;
77
+ /**
78
+ * The handle for one named person, on the same consumer and the same key.
79
+ *
80
+ * The name is asserted by this application and not verified, so the gateway
81
+ * namespaces it: two applications naming `user_123` never share an account.
82
+ * What that person still has to connect is theirs to connect — the handle's
83
+ * own `connections` mint the link to put in front of them — which is why
84
+ * there is no startup preflight here and one in {@link connect}.
85
+ */
86
+ forEndUser(endUser: string, options?: ConnectOptions): Promise<EndUserAgent>;
87
+ }
88
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,YAAY,EAAgB,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAsD,KAAK,eAAe,EAAE,MAAM,aAAa,CAAA;AAUtG,OAAO,EAA0B,KAAK,WAAW,EAAoB,MAAM,aAAa,CAAA;AAExF,MAAM,MAAM,cAAc,GAAG;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,MAAM,CAAC,EAAE,WAAW,CAAA;CACpB,CAAA;AAED,wEAAwE;AACxE,MAAM,MAAM,WAAW,GAAG;IACzB,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAA;IACf;;;;;;;;OAQG;IACH,gBAAgB,EAAE,MAAM,CAAA;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;;;;;GAQG;AACH,qBAAa,SAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,eAAe,CAAC,CAAsB;gBAElC,MAAM,GAAE,eAAoB;IAIxC;;;OAGG;IACG,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAQ1D;;;;;;OAMG;IACG,GAAG,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAYrD;;;;;;;;;;;;;;;OAeG;IACG,OAAO,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,KAAK,CAAC;IAsB3D;;;;;;;;OAQG;IACG,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,YAAY,CAAC;CAWtF"}
package/dist/client.js ADDED
@@ -0,0 +1,152 @@
1
+ import { Agent, endUserAgent } from './agent.js';
2
+ import { API_KEY_HEADER, resolveConfig } from './config.js';
3
+ import { listConnections } from './connections.js';
4
+ import { MissingToolsError, TrustGateError, UpstreamNotConnectedError, } from './errors.js';
5
+ import { MCPTransport } from './mcp.js';
6
+ import { resolveToolName } from './types.js';
7
+ import { selectConsumer, whoAmI } from './whoami.js';
8
+ /**
9
+ * The entry point: a gateway and a key, and everything else is asked for.
10
+ *
11
+ * The key is attached to consumers, and a consumer has one type — so the tools
12
+ * live behind an MCP consumer and the models behind an LLM one. Their slugs
13
+ * were chosen by whoever created them, and the two planes do not share a host,
14
+ * so neither is something a caller should have to carry: the gateway is asked
15
+ * once, at `connect()`, and answers both.
16
+ */
17
+ export class TrustGate {
18
+ config;
19
+ identityPromise;
20
+ constructor(config = {}) {
21
+ this.config = resolveConfig(config);
22
+ }
23
+ /**
24
+ * What this key reaches. Read once and remembered: it is a property of the
25
+ * key, and a long-lived process should not re-ask on every call.
26
+ */
27
+ async identity(signal) {
28
+ this.identityPromise ??= whoAmI(this.config, signal).catch((error) => {
29
+ this.identityPromise = undefined;
30
+ throw asIdentityError(error, this.config.baseUrl);
31
+ });
32
+ return this.identityPromise;
33
+ }
34
+ /**
35
+ * The LLM plane, ready for a provider's own SDK.
36
+ *
37
+ * The gateway speaks the providers' own APIs, so nothing here wraps their
38
+ * clients — it points them somewhere else. Wrapping would mean chasing
39
+ * every change they make and breaking streaming on the way.
40
+ */
41
+ async llm(signal) {
42
+ const identity = await this.identity(signal);
43
+ const consumer = selectConsumer(identity, 'LLM', this.config.llmConsumer, 'llmConsumer');
44
+ return {
45
+ baseUrl: consumer.url,
46
+ anthropicBaseUrl: withoutVersion(consumer.url),
47
+ apiKey: this.config.apiKey,
48
+ headers: { [API_KEY_HEADER]: this.config.apiKey },
49
+ consumer: consumer.slug,
50
+ };
51
+ }
52
+ /**
53
+ * Opens the application's own surface and proves it is usable before
54
+ * anything runs.
55
+ *
56
+ * Two things happen here, and both are the kind that are cheap now and
57
+ * expensive later: whether the tools the agent needs are actually on its
58
+ * toolkit, and whether the servers behind it have an account to call with.
59
+ * The second has no runtime remedy for this handle — nobody is present to
60
+ * open a connect link once a batch is going — which is the whole reason it
61
+ * is checked at startup.
62
+ *
63
+ * This is the application actor: the key and nothing else, so the gateway
64
+ * runs the calls as `app:<consumer_id>`. For a call on behalf of a person,
65
+ * use {@link forEndUser}; both work on the same consumer, because who a
66
+ * request runs as is read from the request rather than declared anywhere.
67
+ */
68
+ async connect(options = {}) {
69
+ const identity = await this.identity(options.signal);
70
+ const consumer = selectConsumer(identity, 'MCP', this.config.mcpConsumer, 'mcpConsumer');
71
+ // Accounts before tools: a server with no account for the application can
72
+ // fail the listing itself, which would surface as a bare gateway error
73
+ // before this check — the one that says who fixes it — ever ran.
74
+ const connections = await listConnections(this.config, consumer.slug, undefined, options.signal);
75
+ const blocked = blockedUpstreams(consumer.upstreams, connections);
76
+ if (blocked.length > 0) {
77
+ throw new UpstreamNotConnectedError(blocked);
78
+ }
79
+ const transport = new MCPTransport(this.config, consumer.url);
80
+ const tools = await transport.listTools(options.signal);
81
+ const missing = missingTools(tools, options.requires ?? []);
82
+ if (missing.length > 0) {
83
+ throw new MissingToolsError(missing, tools.map((tool) => tool.name));
84
+ }
85
+ return new Agent(this.config, consumer.slug, transport, tools, missing, connections);
86
+ }
87
+ /**
88
+ * The handle for one named person, on the same consumer and the same key.
89
+ *
90
+ * The name is asserted by this application and not verified, so the gateway
91
+ * namespaces it: two applications naming `user_123` never share an account.
92
+ * What that person still has to connect is theirs to connect — the handle's
93
+ * own `connections` mint the link to put in front of them — which is why
94
+ * there is no startup preflight here and one in {@link connect}.
95
+ */
96
+ async forEndUser(endUser, options = {}) {
97
+ const identity = await this.identity(options.signal);
98
+ const consumer = selectConsumer(identity, 'MCP', this.config.mcpConsumer, 'mcpConsumer');
99
+ const agent = endUserAgent(this.config, consumer.slug, endUser, consumer.url, []);
100
+ const tools = await agent.refresh(options.signal);
101
+ const missing = missingTools(tools, options.requires ?? []);
102
+ if (missing.length > 0) {
103
+ throw new MissingToolsError(missing, tools.map((tool) => tool.name));
104
+ }
105
+ return agent;
106
+ }
107
+ }
108
+ /**
109
+ * The required tools this toolkit does not carry.
110
+ *
111
+ * Each name is resolved the way callTool resolves it, so an agent may require
112
+ * the name its server gave the tool and leave the gateway's server prefix to
113
+ * the gateway.
114
+ */
115
+ function missingTools(tools, required) {
116
+ const names = new Set(tools.map((tool) => tool.name));
117
+ return required.filter((name) => !names.has(resolveToolName(name, tools)));
118
+ }
119
+ function withoutVersion(url) {
120
+ const trimmed = url.replace(/\/+$/, '');
121
+ return trimmed.endsWith('/v1') ? trimmed.slice(0, -'/v1'.length) : trimmed;
122
+ }
123
+ /** A gateway that cannot answer for a key cannot be used with one secret. */
124
+ function asIdentityError(error, baseUrl) {
125
+ if (error instanceof TrustGateError && error.status === 404) {
126
+ return new TrustGateError(`${baseUrl}/whoami answered 404, so the SDK cannot resolve which consumers ` +
127
+ 'this key reaches. Usually the base URL is the wrong address: it is the MCP ' +
128
+ "plane's host on its own, with no consumer path after it — not the " +
129
+ '/<application>/mcp endpoint, and not the LLM plane. Otherwise the gateway ' +
130
+ 'predates /whoami and needs upgrading.', { status: 404, cause: error });
131
+ }
132
+ return error;
133
+ }
134
+ /**
135
+ * What this application still has to have connected before it can run.
136
+ *
137
+ * `whoami` answers it best, because it also names who has to act. But the field
138
+ * is absent on a gateway too old to send it, and an absent list is not an empty
139
+ * one: taking it for "nothing to connect" is how a batch gets past its own
140
+ * startup check and fails on the first row instead, which is the failure the
141
+ * check exists to prevent. So when it is missing the connections list answers,
142
+ * as it did before `whoami` carried this at all.
143
+ */
144
+ function blockedUpstreams(upstreams, connections) {
145
+ if (upstreams) {
146
+ return upstreams.filter((upstream) => upstream.blocked);
147
+ }
148
+ return connections
149
+ .filter((connection) => connection.status !== 'connected')
150
+ .map((connection) => ({ server: connection.registry || connection.provider }));
151
+ }
152
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ export type TrustGateConfig = {
2
+ /**
3
+ * The gateway's base URL, without a consumer path:
4
+ * `https://gw.acme.ai`. Defaults to `TRUSTGATE_URL`.
5
+ */
6
+ baseUrl?: string;
7
+ /** The consumer's API key. Defaults to `TRUSTGATE_API_KEY`. */
8
+ apiKey?: string;
9
+ /**
10
+ * Slug of the MCP consumer — the one carrying the agent's tools. Defaults
11
+ * to `TRUSTGATE_MCP_CONSUMER`.
12
+ */
13
+ mcpConsumer?: string;
14
+ /**
15
+ * Slug of the LLM consumer — the one in front of the models. Defaults to
16
+ * `TRUSTGATE_LLM_CONSUMER`. It is a different consumer from the MCP one
17
+ * because a consumer has one type; the same API key may be attached to
18
+ * both.
19
+ */
20
+ llmConsumer?: string;
21
+ /** Overrides the fetch implementation. Tests and proxies use this. */
22
+ fetch?: typeof globalThis.fetch;
23
+ /** Per-request timeout in milliseconds. Default 30000. */
24
+ timeoutMs?: number;
25
+ };
26
+ export type ResolvedConfig = {
27
+ baseUrl: string;
28
+ apiKey: string;
29
+ mcpConsumer?: string;
30
+ llmConsumer?: string;
31
+ fetch: typeof globalThis.fetch;
32
+ timeoutMs: number;
33
+ };
34
+ export declare function resolveConfig(config?: TrustGateConfig): ResolvedConfig;
35
+ /**
36
+ * The header the gateway reads the consumer's API key from.
37
+ *
38
+ * It also accepts `x-api-key` and `Authorization: Bearer ag_…`; this one is
39
+ * the unambiguous spelling, so it is the one the SDK sends.
40
+ */
41
+ export declare const API_KEY_HEADER = "X-AG-API-Key";
42
+ /** The header that names which of the application's end users a call is for. */
43
+ export declare const END_USER_HEADER = "X-NeuralTrust-End-User";
44
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GAAG;IAC7B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,sEAAsE;IACtE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAC/B,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;CACjB,CAAA;AAOD,wBAAgB,aAAa,CAAC,MAAM,GAAE,eAAoB,GAAG,cAAc,CAwB1E;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,iBAAiB,CAAA;AAE5C,gFAAgF;AAChF,eAAO,MAAM,eAAe,2BAA2B,CAAA"}
package/dist/config.js ADDED
@@ -0,0 +1,40 @@
1
+ import { TrustGateError } from './errors.js';
2
+ function fromEnv(name) {
3
+ const env = globalThis.process?.env;
4
+ return env?.[name];
5
+ }
6
+ export function resolveConfig(config = {}) {
7
+ const baseUrl = (config.baseUrl ?? fromEnv('TRUSTGATE_URL') ?? '').trim().replace(/\/+$/, '');
8
+ const apiKey = (config.apiKey ?? fromEnv('TRUSTGATE_API_KEY') ?? '').trim();
9
+ if (!baseUrl) {
10
+ throw new TrustGateError('baseUrl is required (or set TRUSTGATE_URL)');
11
+ }
12
+ if (!/^https?:\/\//.test(baseUrl)) {
13
+ throw new TrustGateError(`baseUrl must be an http(s) URL, got "${baseUrl}"`);
14
+ }
15
+ if (!apiKey) {
16
+ throw new TrustGateError('apiKey is required (or set TRUSTGATE_API_KEY)');
17
+ }
18
+ const fetchImpl = config.fetch ?? globalThis.fetch;
19
+ if (typeof fetchImpl !== 'function') {
20
+ throw new TrustGateError('no fetch available; pass one in config.fetch (Node 18+ has a global)');
21
+ }
22
+ return {
23
+ baseUrl,
24
+ apiKey,
25
+ mcpConsumer: config.mcpConsumer?.trim() || fromEnv('TRUSTGATE_MCP_CONSUMER')?.trim(),
26
+ llmConsumer: config.llmConsumer?.trim() || fromEnv('TRUSTGATE_LLM_CONSUMER')?.trim(),
27
+ fetch: fetchImpl,
28
+ timeoutMs: config.timeoutMs ?? 30_000,
29
+ };
30
+ }
31
+ /**
32
+ * The header the gateway reads the consumer's API key from.
33
+ *
34
+ * It also accepts `x-api-key` and `Authorization: Bearer ag_…`; this one is
35
+ * the unambiguous spelling, so it is the one the SDK sends.
36
+ */
37
+ export const API_KEY_HEADER = 'X-AG-API-Key';
38
+ /** The header that names which of the application's end users a call is for. */
39
+ export const END_USER_HEADER = 'X-NeuralTrust-End-User';
40
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAqC5C,SAAS,OAAO,CAAC,IAAY;IAC5B,MAAM,GAAG,GAAI,UAAyE,CAAC,OAAO,EAAE,GAAG,CAAA;IACnG,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;AACnB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAA0B,EAAE;IACzD,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAC7F,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC3E,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,IAAI,cAAc,CAAC,4CAA4C,CAAC,CAAA;IACvE,CAAC;IACD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,cAAc,CAAC,wCAAwC,OAAO,GAAG,CAAC,CAAA;IAC7E,CAAC;IACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,IAAI,cAAc,CAAC,+CAA+C,CAAC,CAAA;IAC1E,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAA;IAClD,IAAI,OAAO,SAAS,KAAK,UAAU,EAAE,CAAC;QACrC,MAAM,IAAI,cAAc,CAAC,sEAAsE,CAAC,CAAA;IACjG,CAAC;IACD,OAAO;QACN,OAAO;QACP,MAAM;QACN,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,wBAAwB,CAAC,EAAE,IAAI,EAAE;QACpF,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,wBAAwB,CAAC,EAAE,IAAI,EAAE;QACpF,KAAK,EAAE,SAAS;QAChB,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,MAAM;KACrC,CAAA;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,cAAc,CAAA;AAE5C,gFAAgF;AAChF,MAAM,CAAC,MAAM,eAAe,GAAG,wBAAwB,CAAA"}
@@ -0,0 +1,13 @@
1
+ import type { ResolvedConfig } from './config.js';
2
+ import type { ConnectLink, Connection } from './types.js';
3
+ export declare function connectionsPath(slug: string, endUser?: string): string;
4
+ export declare function listConnections(config: ResolvedConfig, slug: string, endUser?: string, signal?: AbortSignal): Promise<Connection[]>;
5
+ export declare function createConnectLink(config: ResolvedConfig, slug: string, endUser: string, provider: string | undefined, signal?: AbortSignal): Promise<ConnectLink>;
6
+ /**
7
+ * The gateway is the authority on what an end-user id may be; this only
8
+ * catches the mistake worth catching locally, which is the empty one — it
9
+ * would otherwise be sent as a header the gateway reads as "no user named"
10
+ * and answer for the wrong actor.
11
+ */
12
+ export declare function requireEndUser(endUser: string): string;
13
+ //# sourceMappingURL=connections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../src/connections.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAwBzD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAGtE;AAED,wBAAsB,eAAe,CACpC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,UAAU,EAAE,CAAC,CAKvB;AAED,wBAAsB,iBAAiB,CACtC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,WAAW,CAAC,CAatB;AAaD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMtD"}
@@ -0,0 +1,46 @@
1
+ import { END_USER_HEADER } from './config.js';
2
+ import { requestJSON } from './http.js';
3
+ import { InvalidRequestError } from './errors.js';
4
+ export function connectionsPath(slug, endUser) {
5
+ const query = endUser ? `?end_user=${encodeURIComponent(endUser)}` : '';
6
+ return `/${encodeURIComponent(slug)}/connections${query}`;
7
+ }
8
+ export async function listConnections(config, slug, endUser, signal) {
9
+ const { body } = await requestJSON(config, 'GET', connectionsPath(slug, endUser), {
10
+ signal,
11
+ });
12
+ return (body?.connections ?? []).map(toConnection);
13
+ }
14
+ export async function createConnectLink(config, slug, endUser, provider, signal) {
15
+ const { body } = await requestJSON(config, 'POST', `/${encodeURIComponent(slug)}/connections/links`, { body: { end_user: endUser, ...(provider ? { provider } : {}) }, headers: { [END_USER_HEADER]: endUser }, signal });
16
+ return {
17
+ connectUrl: body.connect_url,
18
+ ticket: body.ticket,
19
+ provider: body.provider || undefined,
20
+ expiresAt: new Date(body.expires_at),
21
+ };
22
+ }
23
+ function toConnection(payload) {
24
+ return {
25
+ provider: payload.provider,
26
+ registry: payload.registry || undefined,
27
+ code: payload.code || undefined,
28
+ status: payload.status,
29
+ accountRef: payload.account_ref || undefined,
30
+ expiresAt: payload.expires_at ? new Date(payload.expires_at) : undefined,
31
+ };
32
+ }
33
+ /**
34
+ * The gateway is the authority on what an end-user id may be; this only
35
+ * catches the mistake worth catching locally, which is the empty one — it
36
+ * would otherwise be sent as a header the gateway reads as "no user named"
37
+ * and answer for the wrong actor.
38
+ */
39
+ export function requireEndUser(endUser) {
40
+ const trimmed = endUser?.trim() ?? '';
41
+ if (!trimmed) {
42
+ throw new InvalidRequestError('an end-user id is required to act for a user');
43
+ }
44
+ return trimmed;
45
+ }
46
+ //# sourceMappingURL=connections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connections.js","sourceRoot":"","sources":["../src/connections.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAyBjD,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAgB;IAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,aAAa,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IACvE,OAAO,IAAI,kBAAkB,CAAC,IAAI,CAAC,eAAe,KAAK,EAAE,CAAA;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACpC,MAAsB,EACtB,IAAY,EACZ,OAAgB,EAChB,MAAoB;IAEpB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,WAAW,CAAqB,MAAM,EAAE,KAAK,EAAE,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;QACrG,MAAM;KACN,CAAC,CAAA;IACF,OAAO,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACtC,MAAsB,EACtB,IAAY,EACZ,OAAe,EACf,QAA4B,EAC5B,MAAoB;IAEpB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,WAAW,CACjC,MAAM,EACN,MAAM,EACN,IAAI,kBAAkB,CAAC,IAAI,CAAC,oBAAoB,EAChD,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,CACnH,CAAA;IACD,OAAO;QACN,UAAU,EAAE,IAAI,CAAC,WAAW;QAC5B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,SAAS;QACpC,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;KACpC,CAAA;AACF,CAAC;AAED,SAAS,YAAY,CAAC,OAA0B;IAC/C,OAAO;QACN,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,SAAS;QACvC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,SAAS;QAC/B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,UAAU,EAAE,OAAO,CAAC,WAAW,IAAI,SAAS;QAC5C,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS;KACxE,CAAA;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC7C,MAAM,OAAO,GAAG,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,IAAI,mBAAmB,CAAC,8CAA8C,CAAC,CAAA;IAC9E,CAAC;IACD,OAAO,OAAO,CAAA;AACf,CAAC"}