@atlanai/sdk 0.2.2 → 0.2.4
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 +6 -2
- package/dist/client.d.ts +20 -3
- package/dist/client.js +130 -9
- package/dist/errors.d.ts +10 -0
- package/dist/errors.js +34 -1
- package/dist/evals.d.ts +135 -8
- package/dist/evals.js +1004 -73
- package/dist/index.d.ts +3 -2
- package/dist/index.js +7 -1
- package/dist/manifest.json +84 -11
- package/dist/raw/agent/apis/AgentsApi.d.ts +29 -0
- package/dist/raw/agent/apis/AgentsApi.js +62 -1
- package/dist/raw/agent/apis/SessionsApi.d.ts +2 -2
- package/dist/raw/agent/apis/SessionsApi.js +2 -2
- package/dist/raw/agent/models/AgentAgentArtifactView.d.ts +48 -0
- package/dist/raw/agent/models/AgentAgentArtifactView.js +13 -0
- package/dist/raw/agent/models/AgentAgentEnvironmentArtifactView.d.ts +12 -0
- package/dist/raw/agent/models/AgentAgentEnvironmentArtifactView.js +2 -0
- package/dist/raw/agent/models/AgentAgentEnvironmentMeta.d.ts +12 -0
- package/dist/raw/agent/models/AgentAgentEnvironmentMeta.js +2 -0
- package/dist/raw/agent/models/AgentAgentMeta.d.ts +48 -0
- package/dist/raw/agent/models/AgentAgentMeta.js +13 -0
- package/dist/raw/agent/models/AgentAgentProviderArtifactView.d.ts +55 -2
- package/dist/raw/agent/models/AgentAgentProviderArtifactView.js +8 -0
- package/dist/raw/agent/models/AgentAgentProviderCreate.d.ts +24 -3
- package/dist/raw/agent/models/AgentAgentProviderCreate.js +4 -0
- package/dist/raw/agent/models/AgentAgentProviderMeta.d.ts +56 -13
- package/dist/raw/agent/models/AgentAgentProviderMeta.js +8 -0
- package/dist/raw/agent/models/AgentAgentProviderPatch.d.ts +13 -0
- package/dist/raw/agent/models/AgentAgentProviderPatch.js +4 -0
- package/dist/raw/agent/models/AgentAgentProviderType.d.ts +19 -9
- package/dist/raw/agent/models/AgentAgentProviderType.js +18 -8
- package/dist/raw/agent/models/AgentListAgentFrameworks401Response.d.ts +1 -0
- package/dist/raw/agent/models/AgentListAgentFrameworks401Response.js +1 -0
- package/dist/raw/agent/models/AgentPageSessionEventView.d.ts +3 -3
- package/dist/raw/agent/models/AgentPageSessionEventView.js +3 -3
- package/dist/raw/agent/models/AgentRemoteSessionEvent.d.ts +38 -0
- package/dist/raw/agent/models/AgentRemoteSessionEvent.js +58 -0
- package/dist/raw/agent/models/AgentSessionArtifactView.d.ts +25 -0
- package/dist/raw/agent/models/AgentSessionArtifactView.js +2 -0
- package/dist/raw/agent/models/AgentSessionEventView.d.ts +30 -0
- package/dist/raw/agent/models/AgentSessionEventView.js +57 -0
- package/dist/raw/agent/models/AgentSessionMeta.d.ts +25 -0
- package/dist/raw/agent/models/AgentSessionMeta.js +2 -0
- package/dist/raw/agent/models/AgentSessionStreamFrame.d.ts +8 -6
- package/dist/raw/agent/models/AgentSessionStreamFrame.js +7 -0
- package/dist/raw/agent/models/AgentSyncState.d.ts +27 -0
- package/dist/raw/agent/models/AgentSyncState.js +55 -0
- package/dist/raw/agent/models/TriggerBody.d.ts +52 -0
- package/dist/raw/agent/models/TriggerBody.js +58 -0
- package/dist/raw/agent/models/index.d.ts +4 -1
- package/dist/raw/agent/models/index.js +4 -1
- package/dist/raw/eval/models/EvalListDatasets401Response.d.ts +1 -0
- package/dist/raw/eval/models/EvalListDatasets401Response.js +1 -0
- package/dist/raw/file/models/FileList401Response.d.ts +1 -0
- package/dist/raw/file/models/FileList401Response.js +1 -0
- package/dist/raw/mcp/apis/ServersApi.d.ts +2 -2
- package/dist/raw/mcp/apis/ServersApi.js +2 -2
- package/dist/raw/mcp/models/McpConnectionState.d.ts +2 -1
- package/dist/raw/mcp/models/McpConnectionState.js +2 -1
- package/dist/raw/mcp/models/McpListServers401Response.d.ts +1 -0
- package/dist/raw/mcp/models/McpListServers401Response.js +1 -0
- package/dist/raw/mcp/models/McpServerTestResponse.d.ts +13 -2
- package/dist/raw/model/models/ModelListProviders401Response.d.ts +1 -0
- package/dist/raw/model/models/ModelListProviders401Response.js +1 -0
- package/dist/raw/registry/apis/WorkspacesApi.d.ts +28 -0
- package/dist/raw/registry/apis/WorkspacesApi.js +61 -1
- package/dist/raw/registry/models/CreateWorkspaceBody.d.ts +9 -0
- package/dist/raw/registry/models/CreateWorkspaceBody.js +2 -0
- package/dist/raw/registry/models/RegistryAggregate401Response.d.ts +1 -0
- package/dist/raw/registry/models/RegistryAggregate401Response.js +1 -0
- package/dist/raw/registry/models/RegistryWorkspaceView.d.ts +9 -0
- package/dist/raw/registry/models/RegistryWorkspaceView.js +4 -0
- package/dist/raw/registry/models/SearchRequest.d.ts +1 -1
- package/dist/raw/registry/models/SetVisibilityBody.d.ts +33 -0
- package/dist/raw/registry/models/SetVisibilityBody.js +50 -0
- package/dist/raw/registry/models/index.d.ts +1 -0
- package/dist/raw/registry/models/index.js +1 -0
- package/dist/raw/secret/apis/OauthApi.d.ts +143 -0
- package/dist/raw/secret/apis/OauthApi.js +335 -0
- package/dist/raw/secret/apis/index.d.ts +1 -0
- package/dist/raw/secret/apis/index.js +19 -0
- package/dist/raw/secret/index.d.ts +1 -0
- package/dist/raw/secret/index.js +1 -0
- package/dist/raw/secret/models/GatewayOauthCompleteRequest.d.ts +32 -0
- package/dist/raw/secret/models/GatewayOauthCompleteRequest.js +50 -0
- package/dist/raw/secret/models/GatewayOauthCompletion.d.ts +46 -0
- package/dist/raw/secret/models/GatewayOauthCompletion.js +55 -0
- package/dist/raw/secret/models/GatewayOauthConnection.d.ts +83 -0
- package/dist/raw/secret/models/GatewayOauthConnection.js +83 -0
- package/dist/raw/secret/models/GatewayOauthOwner.d.ts +31 -0
- package/dist/raw/secret/models/GatewayOauthOwner.js +59 -0
- package/dist/raw/secret/models/GatewayOauthProviderView.d.ts +69 -0
- package/dist/raw/secret/models/GatewayOauthProviderView.js +69 -0
- package/dist/raw/secret/models/GatewayOauthStartRequest.d.ts +52 -0
- package/dist/raw/secret/models/GatewayOauthStartRequest.js +59 -0
- package/dist/raw/secret/models/GatewayOauthStarted.d.ts +39 -0
- package/dist/raw/secret/models/GatewayOauthStarted.js +54 -0
- package/dist/raw/secret/models/SecretCompleteOauth400Response.d.ts +70 -0
- package/dist/raw/secret/models/SecretCompleteOauth400Response.js +80 -0
- package/dist/raw/secret/models/SecretCompleteOauth413Response.d.ts +64 -0
- package/dist/raw/secret/models/SecretCompleteOauth413Response.js +74 -0
- package/dist/raw/secret/models/SecretCompleteOauth415Response.d.ts +64 -0
- package/dist/raw/secret/models/SecretCompleteOauth415Response.js +74 -0
- package/dist/raw/secret/models/SecretCompleteOauth422Response.d.ts +63 -0
- package/dist/raw/secret/models/SecretCompleteOauth422Response.js +75 -0
- package/dist/raw/secret/models/SecretDisconnectOauth400Response.d.ts +67 -0
- package/dist/raw/secret/models/SecretDisconnectOauth400Response.js +77 -0
- package/dist/raw/secret/models/SecretOauthCallback400Response.d.ts +68 -0
- package/dist/raw/secret/models/SecretOauthCallback400Response.js +78 -0
- package/dist/raw/secret/models/SecretOauthCallback401Response.d.ts +80 -0
- package/dist/raw/secret/models/SecretOauthCallback401Response.js +90 -0
- package/dist/raw/secret/models/SecretOauthCallback403Response.d.ts +66 -0
- package/dist/raw/secret/models/SecretOauthCallback403Response.js +76 -0
- package/dist/raw/secret/models/SecretOauthCallback404Response.d.ts +65 -0
- package/dist/raw/secret/models/SecretOauthCallback404Response.js +75 -0
- package/dist/raw/secret/models/SecretOauthCallback500Response.d.ts +64 -0
- package/dist/raw/secret/models/SecretOauthCallback500Response.js +74 -0
- package/dist/raw/secret/models/SecretOauthCallback503Response.d.ts +66 -0
- package/dist/raw/secret/models/SecretOauthCallback503Response.js +76 -0
- package/dist/raw/secret/models/SecretOauthCallback504Response.d.ts +63 -0
- package/dist/raw/secret/models/SecretOauthCallback504Response.js +75 -0
- package/dist/raw/secret/models/index.d.ts +19 -0
- package/dist/raw/secret/models/index.js +19 -0
- package/dist/raw/skill/models/SkillInsightSchemas401Response.d.ts +1 -0
- package/dist/raw/skill/models/SkillInsightSchemas401Response.js +1 -0
- package/dist/resource-types.d.ts +670 -0
- package/dist/resource-types.js +2 -0
- package/dist/resources.d.ts +10 -0
- package/dist/resources.js +54 -4
- package/dist/resources.json +86 -0
- package/dist/tracing/client.d.ts +8 -1
- package/dist/tracing/client.js +43 -16
- package/dist/tracing/config.d.ts +3 -1
- package/dist/tracing/config.js +7 -2
- package/dist/tracing/exporter.d.ts +19 -1
- package/dist/tracing/exporter.js +56 -14
- package/dist/tracing/propagation.d.ts +2 -0
- package/dist/tracing/propagation.js +16 -0
- package/dist/tracing/semconv.d.ts +4 -0
- package/dist/tracing/semconv.js +14 -2
- package/dist/tracing/spans.d.ts +2 -0
- package/dist/tracing/spans.js +12 -1
- package/dist/tracing/version.d.ts +1 -1
- package/dist/tracing/version.js +1 -1
- package/package.json +1 -1
- package/dist/raw/agent/models/Box.d.ts +0 -342
- package/dist/raw/agent/models/Box.js +0 -167
package/README.md
CHANGED
|
@@ -120,7 +120,10 @@ await logger.flush();
|
|
|
120
120
|
Tracing has its own API key and lifecycle. It does not reuse the management
|
|
121
121
|
client's transport. It ships as a separate subpath
|
|
122
122
|
(`@atlanai/sdk/tracing`) so importing it doesn't pull OpenTelemetry into a
|
|
123
|
-
management-only bundle.
|
|
123
|
+
management-only bundle. npm still installs the OpenTelemetry dependencies with
|
|
124
|
+
the package because npm cannot make dependencies conditional on an imported
|
|
125
|
+
subpath; splitting tracing into a second package would trade that install size
|
|
126
|
+
for a second version and release lifecycle.
|
|
124
127
|
|
|
125
128
|
Vercel AI SDK v3-v6 uses its native OpenTelemetry path:
|
|
126
129
|
|
|
@@ -138,7 +141,8 @@ context manifests, serverless flushing, and the tested integration matrix.
|
|
|
138
141
|
## Errors
|
|
139
142
|
|
|
140
143
|
Every non-2xx response rejects with `AtlanAPIError`, with `.status`, `.code`,
|
|
141
|
-
and (where the gateway includes one) `.traceId
|
|
144
|
+
and (where the gateway includes one) `.traceId`. A failure before any response
|
|
145
|
+
is also normalized as `AtlanAPIError` with `status === 0`:
|
|
142
146
|
|
|
143
147
|
```typescript
|
|
144
148
|
import { AtlanAPIError } from "@atlanai/sdk";
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Operation } from "./operations";
|
|
2
2
|
import { type Resource } from "./resources";
|
|
3
|
+
import type { ResourceMap, ResourceRoots } from "./resource-types";
|
|
3
4
|
type TokenProvider = () => string | Promise<string>;
|
|
4
5
|
type FetchImplementation = typeof fetch;
|
|
5
6
|
type GeneratedConfiguration = {
|
|
@@ -41,15 +42,31 @@ export declare class ServiceNamespace {
|
|
|
41
42
|
readonly operations: readonly Omit<Operation, "service">[];
|
|
42
43
|
/** Contract method names for this service, used to resolve a forwarded call. */
|
|
43
44
|
readonly operationMethods: ReadonlySet<string>;
|
|
44
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Whether the configured credential is an API key rather than a user token.
|
|
47
|
+
* Only the credential's shape was read, never its value.
|
|
48
|
+
*/
|
|
49
|
+
readonly apiKeyCredential: boolean;
|
|
50
|
+
constructor(name: string, module: GeneratedModule, configuration: GeneratedConfiguration, serviceOperations: readonly Omit<Operation, "service">[], apiKeyCredential?: boolean);
|
|
45
51
|
}
|
|
46
52
|
/** Build a namespace that also answers its operations by method name. */
|
|
47
|
-
export declare function createService(name: string, module: GeneratedModule, configuration: GeneratedConfiguration, serviceOperations: readonly Omit<Operation, "service">[]): Service;
|
|
53
|
+
export declare function createService(name: string, module: GeneratedModule, configuration: GeneratedConfiguration, serviceOperations: readonly Omit<Operation, "service">[], apiKeyCredential?: boolean): Service;
|
|
54
|
+
/**
|
|
55
|
+
* Whether a credential is a signed JWT, which is the user-token shape.
|
|
56
|
+
*
|
|
57
|
+
* Only the structure is read, and the value is never logged or compared to a
|
|
58
|
+
* literal: three base64url segments whose first decodes to a JSON object. The
|
|
59
|
+
* gateway draws the same line itself - its 401 vocabulary splits
|
|
60
|
+
* `invalid_api_key`/`unknown_key` from the whole `token_*` family.
|
|
61
|
+
*/
|
|
62
|
+
export declare function looksLikeAJwt(token: string): boolean;
|
|
63
|
+
export interface AtlanClient extends ResourceRoots {
|
|
64
|
+
}
|
|
48
65
|
export declare class AtlanClient {
|
|
49
66
|
/** Per-service generated clients, for an operation the map has not surfaced. */
|
|
50
67
|
readonly raw: Readonly<Record<string, Service>>;
|
|
51
68
|
/** Every resource, keyed by its dotted path. */
|
|
52
|
-
readonly resources: Readonly<Record<string, Resource>>;
|
|
69
|
+
readonly resources: ResourceMap & Readonly<Record<string, Resource>>;
|
|
53
70
|
readonly workspace: string | undefined;
|
|
54
71
|
constructor(options: AtlanClientOptions);
|
|
55
72
|
/**
|
package/dist/client.js
CHANGED
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.AtlanClient = exports.ServiceNamespace = exports.WORKSPACE_HEADER = void 0;
|
|
37
37
|
exports.createService = createService;
|
|
38
|
+
exports.looksLikeAJwt = looksLikeAJwt;
|
|
38
39
|
const agentRaw = __importStar(require("./raw/agent/index"));
|
|
39
40
|
const apiRaw = __importStar(require("./raw/api/index"));
|
|
40
41
|
const evalRaw = __importStar(require("./raw/eval/index"));
|
|
@@ -57,8 +58,14 @@ class ServiceNamespace {
|
|
|
57
58
|
operations;
|
|
58
59
|
/** Contract method names for this service, used to resolve a forwarded call. */
|
|
59
60
|
operationMethods;
|
|
60
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Whether the configured credential is an API key rather than a user token.
|
|
63
|
+
* Only the credential's shape was read, never its value.
|
|
64
|
+
*/
|
|
65
|
+
apiKeyCredential;
|
|
66
|
+
constructor(name, module, configuration, serviceOperations, apiKeyCredential = false) {
|
|
61
67
|
this.name = name;
|
|
68
|
+
this.apiKeyCredential = apiKeyCredential;
|
|
62
69
|
this.configuration = configuration;
|
|
63
70
|
this.operations = serviceOperations;
|
|
64
71
|
const operationMethods = new Set(serviceOperations.map((operation) => methodName(operation.operation_id)));
|
|
@@ -69,15 +76,15 @@ class ServiceNamespace {
|
|
|
69
76
|
continue;
|
|
70
77
|
const name = exportName.replace(/Api$/, "").replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase();
|
|
71
78
|
const raw = new value(configuration);
|
|
72
|
-
apis[name] = wrapGeneratedAPI(raw, operationMethods);
|
|
79
|
+
apis[name] = wrapGeneratedAPI(raw, operationMethods, apiKeyCredential);
|
|
73
80
|
}
|
|
74
81
|
this.apis = Object.freeze(apis);
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
exports.ServiceNamespace = ServiceNamespace;
|
|
78
85
|
/** Build a namespace that also answers its operations by method name. */
|
|
79
|
-
function createService(name, module, configuration, serviceOperations) {
|
|
80
|
-
const namespace = new ServiceNamespace(name, module, configuration, serviceOperations);
|
|
86
|
+
function createService(name, module, configuration, serviceOperations, apiKeyCredential = false) {
|
|
87
|
+
const namespace = new ServiceNamespace(name, module, configuration, serviceOperations, apiKeyCredential);
|
|
81
88
|
return forwardOperations(namespace, namespace.operationMethods);
|
|
82
89
|
}
|
|
83
90
|
/**
|
|
@@ -138,7 +145,69 @@ function methodName(operationId) {
|
|
|
138
145
|
const [service, operation] = operationId.split(".", 2);
|
|
139
146
|
return service + operation.charAt(0).toUpperCase() + operation.slice(1);
|
|
140
147
|
}
|
|
141
|
-
|
|
148
|
+
/**
|
|
149
|
+
* Recover a success body the generated client would have thrown away.
|
|
150
|
+
*
|
|
151
|
+
* A handful of operations document their 200 as `application/json` with no
|
|
152
|
+
* schema. The generator reads that as "no response type" and renders the
|
|
153
|
+
* method as `Promise<void>`: it awaits the `…Raw` sibling and returns nothing,
|
|
154
|
+
* never calling `value()` at all. `GET /skill/v1/skills/{skill_id}` is one -
|
|
155
|
+
* the gateway sends the whole skill and the caller receives `undefined`, which
|
|
156
|
+
* makes a skill impossible to read back.
|
|
157
|
+
*
|
|
158
|
+
* Hand-fixing the contract would not hold, since `contracts/` is synced from
|
|
159
|
+
* the gateway. So the generated method is still the one called, with its own
|
|
160
|
+
* parameter defaults intact, over a receiver that keeps hold of the
|
|
161
|
+
* `ApiResponse` it discards. Only when the call resolves to `undefined` is
|
|
162
|
+
* that response read, and its body is still unconsumed precisely because the
|
|
163
|
+
* generated method ignored it. One request either way, and nothing changes for
|
|
164
|
+
* an operation whose body the generator already keeps.
|
|
165
|
+
*/
|
|
166
|
+
async function callKeepingBody(target, method, property, args) {
|
|
167
|
+
const rawName = `${property}Raw`;
|
|
168
|
+
if (typeof target[rawName] !== "function") {
|
|
169
|
+
return await Reflect.apply(method, target, args);
|
|
170
|
+
}
|
|
171
|
+
let captured;
|
|
172
|
+
const receiver = new Proxy(target, {
|
|
173
|
+
get(proxied, name, self) {
|
|
174
|
+
const member = Reflect.get(proxied, name, self);
|
|
175
|
+
if (name !== rawName || typeof member !== "function")
|
|
176
|
+
return member;
|
|
177
|
+
return async (...rawArgs) => {
|
|
178
|
+
captured = (await Reflect.apply(member, proxied, rawArgs));
|
|
179
|
+
return captured;
|
|
180
|
+
};
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
const result = await Reflect.apply(method, receiver, args);
|
|
184
|
+
if (result !== undefined || captured === undefined)
|
|
185
|
+
return result;
|
|
186
|
+
return await recoverValue(captured);
|
|
187
|
+
}
|
|
188
|
+
async function recoverValue(response) {
|
|
189
|
+
let value;
|
|
190
|
+
try {
|
|
191
|
+
value = await response.value?.();
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// The generated method already read the body; there is nothing to recover.
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
if (value !== undefined || !response.raw)
|
|
198
|
+
return value;
|
|
199
|
+
const contentType = response.raw.headers.get("content-type") ?? "";
|
|
200
|
+
if (!contentType.toLowerCase().includes("json"))
|
|
201
|
+
return value;
|
|
202
|
+
try {
|
|
203
|
+
return await response.raw.json();
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// An empty or unparseable body is the `void` the generator promised.
|
|
207
|
+
return value;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function wrapGeneratedAPI(api, operationMethods, apiKeyCredential) {
|
|
142
211
|
return new Proxy(api, {
|
|
143
212
|
get(target, property, receiver) {
|
|
144
213
|
const value = Reflect.get(target, property, receiver);
|
|
@@ -147,19 +216,58 @@ function wrapGeneratedAPI(api, operationMethods) {
|
|
|
147
216
|
}
|
|
148
217
|
return async (...args) => {
|
|
149
218
|
try {
|
|
150
|
-
return await
|
|
219
|
+
return await callKeepingBody(target, value, property, args);
|
|
151
220
|
}
|
|
152
221
|
catch (error) {
|
|
153
222
|
const response = error?.response;
|
|
154
223
|
if (response instanceof Response) {
|
|
155
|
-
throw await errors_1.AtlanAPIError.fromResponse(response);
|
|
224
|
+
throw annotateCredential(await errors_1.AtlanAPIError.fromResponse(response), apiKeyCredential);
|
|
156
225
|
}
|
|
226
|
+
const cause = error?.cause;
|
|
227
|
+
if (cause instanceof errors_1.AtlanAPIError)
|
|
228
|
+
throw annotateCredential(cause, apiKeyCredential);
|
|
157
229
|
throw error;
|
|
158
230
|
}
|
|
159
231
|
};
|
|
160
232
|
},
|
|
161
233
|
});
|
|
162
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Say which kind of credential a 403 was refused for.
|
|
237
|
+
*
|
|
238
|
+
* A bare "403 forbidden" sends people hunting for a missing role when the
|
|
239
|
+
* credential kind is the whole story: the same POST an API key is refused is
|
|
240
|
+
* accepted from a user token.
|
|
241
|
+
*/
|
|
242
|
+
function annotateCredential(error, apiKeyCredential) {
|
|
243
|
+
if (error.status !== 403 || !apiKeyCredential)
|
|
244
|
+
return error;
|
|
245
|
+
return error.withHint("the configured credential is an API key, not a user token; the gateway grants " +
|
|
246
|
+
"an API key a narrower set of permissions - creating an agent or a skill, for " +
|
|
247
|
+
"one, is refused for an API key and accepted for a user token from " +
|
|
248
|
+
"`atlanai auth login` (read it with `atlanai auth token`)");
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Whether a credential is a signed JWT, which is the user-token shape.
|
|
252
|
+
*
|
|
253
|
+
* Only the structure is read, and the value is never logged or compared to a
|
|
254
|
+
* literal: three base64url segments whose first decodes to a JSON object. The
|
|
255
|
+
* gateway draws the same line itself - its 401 vocabulary splits
|
|
256
|
+
* `invalid_api_key`/`unknown_key` from the whole `token_*` family.
|
|
257
|
+
*/
|
|
258
|
+
function looksLikeAJwt(token) {
|
|
259
|
+
const segments = token.split(".");
|
|
260
|
+
if (segments.length !== 3 || segments.some((segment) => segment === ""))
|
|
261
|
+
return false;
|
|
262
|
+
try {
|
|
263
|
+
const header = segments[0].replace(/-/g, "+").replace(/_/g, "/");
|
|
264
|
+
const decoded = JSON.parse(atob(header));
|
|
265
|
+
return typeof decoded === "object" && decoded !== null && !Array.isArray(decoded);
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
163
271
|
class AtlanClient {
|
|
164
272
|
/** Per-service generated clients, for an operation the map has not surfaced. */
|
|
165
273
|
raw;
|
|
@@ -178,6 +286,10 @@ class AtlanClient {
|
|
|
178
286
|
const fetchApi = withTimeout(options.fetch ?? globalThis.fetch, timeoutMs);
|
|
179
287
|
const accessToken = safeTokenProvider(options.bearerToken, options.tokenProvider);
|
|
180
288
|
const workspace = validateWorkspace(options.workspace);
|
|
289
|
+
// Read once, from the shape alone. A tokenProvider is left unclassified
|
|
290
|
+
// rather than called here: resolving it early could refresh a credential
|
|
291
|
+
// nobody asked for yet.
|
|
292
|
+
const apiKeyCredential = options.bearerToken !== undefined && !looksLikeAJwt(options.bearerToken);
|
|
181
293
|
const modules = {
|
|
182
294
|
registry: registryRaw,
|
|
183
295
|
skill: skillRaw,
|
|
@@ -199,7 +311,7 @@ class AtlanClient {
|
|
|
199
311
|
accessToken,
|
|
200
312
|
...(workspace === undefined ? {} : { headers: { [exports.WORKSPACE_HEADER]: workspace } }),
|
|
201
313
|
});
|
|
202
|
-
namespaces[service.name] = createService(service.name, module, configuration, service.operations);
|
|
314
|
+
namespaces[service.name] = createService(service.name, module, configuration, service.operations, apiKeyCredential);
|
|
203
315
|
}
|
|
204
316
|
this.raw = Object.freeze(namespaces);
|
|
205
317
|
// Resources, not services. A service is a base path; a resource is what a
|
|
@@ -264,10 +376,19 @@ function withTimeout(baseFetch, timeoutMs) {
|
|
|
264
376
|
const callerSignal = init?.signal;
|
|
265
377
|
const forwardAbort = () => controller.abort(callerSignal?.reason);
|
|
266
378
|
callerSignal?.addEventListener("abort", forwardAbort, { once: true });
|
|
267
|
-
|
|
379
|
+
let timedOut = false;
|
|
380
|
+
const timer = setTimeout(() => {
|
|
381
|
+
timedOut = true;
|
|
382
|
+
controller.abort(new Error("request timed out"));
|
|
383
|
+
}, timeoutMs);
|
|
268
384
|
try {
|
|
269
385
|
return await baseFetch(input, { ...init, signal: controller.signal });
|
|
270
386
|
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
if (callerSignal?.aborted || error instanceof errors_1.AtlanAPIError)
|
|
389
|
+
throw error;
|
|
390
|
+
throw errors_1.AtlanAPIError.fromConnectionError(timedOut);
|
|
391
|
+
}
|
|
271
392
|
finally {
|
|
272
393
|
clearTimeout(timer);
|
|
273
394
|
callerSignal?.removeEventListener("abort", forwardAbort);
|
package/dist/errors.d.ts
CHANGED
|
@@ -4,12 +4,22 @@ export declare class AtlanAPIError extends Error {
|
|
|
4
4
|
readonly title: string;
|
|
5
5
|
readonly detail: string;
|
|
6
6
|
readonly traceId?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Set by the SDK when it, not the gateway, knows why the call failed - a
|
|
9
|
+
* 403 refused for the kind of credential configured, for instance. Never
|
|
10
|
+
* server-supplied, so unlike `detail` it is safe to put in the message.
|
|
11
|
+
*/
|
|
12
|
+
readonly hint: string;
|
|
7
13
|
constructor(options: {
|
|
8
14
|
status: number;
|
|
9
15
|
code?: string;
|
|
10
16
|
title?: string;
|
|
11
17
|
detail?: string;
|
|
12
18
|
traceId?: string;
|
|
19
|
+
hint?: string;
|
|
13
20
|
});
|
|
21
|
+
/** The same failure, carrying a client-side explanation in its message. */
|
|
22
|
+
withHint(hint: string): AtlanAPIError;
|
|
14
23
|
static fromResponse(response: Response): Promise<AtlanAPIError>;
|
|
24
|
+
static fromConnectionError(timedOut?: boolean): AtlanAPIError;
|
|
15
25
|
}
|
package/dist/errors.js
CHANGED
|
@@ -7,15 +7,40 @@ class AtlanAPIError extends Error {
|
|
|
7
7
|
title;
|
|
8
8
|
detail;
|
|
9
9
|
traceId;
|
|
10
|
+
/**
|
|
11
|
+
* Set by the SDK when it, not the gateway, knows why the call failed - a
|
|
12
|
+
* 403 refused for the kind of credential configured, for instance. Never
|
|
13
|
+
* server-supplied, so unlike `detail` it is safe to put in the message.
|
|
14
|
+
*/
|
|
15
|
+
hint;
|
|
10
16
|
constructor(options) {
|
|
11
17
|
const suffix = options.code ? ` (${options.code})` : "";
|
|
12
|
-
|
|
18
|
+
const hint = options.hint ? `; ${options.hint}` : "";
|
|
19
|
+
// `detail` stays out: it is server text and may echo what was sent.
|
|
20
|
+
// `traceId` is an opaque correlation id and is what support asks for.
|
|
21
|
+
const trace = options.traceId ? ` [trace_id=${options.traceId}]` : "";
|
|
22
|
+
const message = options.status === 0
|
|
23
|
+
? `${options.title ?? "Could not reach the Atlan Gateway"}${options.detail ? `; ${options.detail}` : ""}`
|
|
24
|
+
: `Atlan API request failed with status ${options.status}${suffix}${trace}${hint}`;
|
|
25
|
+
super(message);
|
|
13
26
|
this.name = "AtlanAPIError";
|
|
14
27
|
this.status = options.status;
|
|
15
28
|
this.code = options.code ?? "";
|
|
16
29
|
this.title = options.title ?? "";
|
|
17
30
|
this.detail = options.detail ?? "";
|
|
18
31
|
this.traceId = options.traceId;
|
|
32
|
+
this.hint = options.hint ?? "";
|
|
33
|
+
}
|
|
34
|
+
/** The same failure, carrying a client-side explanation in its message. */
|
|
35
|
+
withHint(hint) {
|
|
36
|
+
return new AtlanAPIError({
|
|
37
|
+
status: this.status,
|
|
38
|
+
code: this.code,
|
|
39
|
+
title: this.title,
|
|
40
|
+
detail: this.detail,
|
|
41
|
+
traceId: this.traceId,
|
|
42
|
+
hint,
|
|
43
|
+
});
|
|
19
44
|
}
|
|
20
45
|
static async fromResponse(response) {
|
|
21
46
|
let problem = {};
|
|
@@ -39,5 +64,13 @@ class AtlanAPIError extends Error {
|
|
|
39
64
|
traceId: typeof problem.trace_id === "string" ? problem.trace_id : undefined,
|
|
40
65
|
});
|
|
41
66
|
}
|
|
67
|
+
static fromConnectionError(timedOut = false) {
|
|
68
|
+
return new AtlanAPIError({
|
|
69
|
+
status: 0,
|
|
70
|
+
code: timedOut ? "request_timeout" : "connection_error",
|
|
71
|
+
title: timedOut ? "Atlan Gateway request timed out" : "Could not reach the Atlan Gateway",
|
|
72
|
+
detail: "Check gatewayOrigin, DNS, VPN, and network access",
|
|
73
|
+
});
|
|
74
|
+
}
|
|
42
75
|
}
|
|
43
76
|
exports.AtlanAPIError = AtlanAPIError;
|
package/dist/evals.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface ContextItem {
|
|
|
6
6
|
name: string;
|
|
7
7
|
digest: string;
|
|
8
8
|
version: string;
|
|
9
|
+
artifactKind?: string;
|
|
9
10
|
artifactId?: string;
|
|
10
11
|
versionOrdinal?: number;
|
|
11
12
|
}
|
|
@@ -14,6 +15,7 @@ export interface ContextManifestItem {
|
|
|
14
15
|
name: string;
|
|
15
16
|
digest: string;
|
|
16
17
|
version: string;
|
|
18
|
+
artifact_kind?: string;
|
|
17
19
|
artifact_id?: string;
|
|
18
20
|
version_ordinal?: number;
|
|
19
21
|
}
|
|
@@ -26,6 +28,47 @@ export interface ContextManifest {
|
|
|
26
28
|
export declare function createContextManifest(input: readonly ContextItem[]): Promise<ContextManifest>;
|
|
27
29
|
/** Resolve one dataset by artifact ID or exact name, never fuzzy matching. */
|
|
28
30
|
export declare function resolveDataset(client: AtlanClient, idOrExactName: string, workspaceId?: string): Promise<unknown>;
|
|
31
|
+
/**
|
|
32
|
+
* The Registry handle for the case called `key` inside `datasetId`.
|
|
33
|
+
*
|
|
34
|
+
* Deterministic, so pushing the same suite twice lands on the same row, and
|
|
35
|
+
* dataset-scoped, so the same suite can also be pushed into a new dataset.
|
|
36
|
+
*/
|
|
37
|
+
export declare function recordName(datasetId: string, key: string): Promise<string>;
|
|
38
|
+
/** What one case in a pushed suite ended up as. */
|
|
39
|
+
export interface RecordPush {
|
|
40
|
+
readonly key: string;
|
|
41
|
+
readonly name: string;
|
|
42
|
+
readonly id: string;
|
|
43
|
+
readonly action: "created" | "updated" | "unchanged";
|
|
44
|
+
readonly record: unknown;
|
|
45
|
+
}
|
|
46
|
+
/** A pushed suite: the dataset it landed in and what each case did. */
|
|
47
|
+
export interface DatasetPush {
|
|
48
|
+
readonly dataset: unknown;
|
|
49
|
+
readonly id: string;
|
|
50
|
+
readonly created: boolean;
|
|
51
|
+
readonly records: readonly RecordPush[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create or update each case, so the same suite can be pushed repeatedly.
|
|
55
|
+
*
|
|
56
|
+
* Each record's `name` is the developer's key for the case: it becomes the
|
|
57
|
+
* row's `displayName` and keys the Registry handle. A case already in the
|
|
58
|
+
* dataset is patched when its content moved and left alone when it did not.
|
|
59
|
+
*/
|
|
60
|
+
export declare function pushRecords(client: AtlanClient, datasetId: string, records: Iterable<Record<string, unknown>>, workspaceId?: string): Promise<RecordPush[]>;
|
|
61
|
+
/**
|
|
62
|
+
* Push a suite under `name`, creating the dataset the first time only.
|
|
63
|
+
*
|
|
64
|
+
* Idempotent: run it again after correcting an expected value and the
|
|
65
|
+
* correction lands on the same rows, in the same dataset, without a 409.
|
|
66
|
+
*/
|
|
67
|
+
export declare function pushDataset(client: AtlanClient, name: string, records: Iterable<Record<string, unknown>>, options?: {
|
|
68
|
+
workspaceId?: string;
|
|
69
|
+
displayName?: string;
|
|
70
|
+
description?: string;
|
|
71
|
+
}): Promise<DatasetPush>;
|
|
29
72
|
export interface StartExperimentOptions {
|
|
30
73
|
contextManifest?: ContextManifest;
|
|
31
74
|
}
|
|
@@ -33,23 +76,65 @@ export declare class EvalRun {
|
|
|
33
76
|
readonly experiment: unknown;
|
|
34
77
|
readonly dataset: unknown;
|
|
35
78
|
readonly contextManifest?: ContextManifest | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* The session id stamped on every span this run emits.
|
|
81
|
+
*
|
|
82
|
+
* It is the only join key the gateway promotes off an eval span that can
|
|
83
|
+
* reach the run's subject: `recordExperimentSession` registers this value
|
|
84
|
+
* against the experiment's subject.
|
|
85
|
+
*/
|
|
36
86
|
constructor(experiment: unknown, dataset: unknown, contextManifest?: ContextManifest | undefined);
|
|
37
87
|
get id(): string;
|
|
38
88
|
get experimentId(): string;
|
|
39
|
-
/**
|
|
89
|
+
/** Stable across retries because the experiment is the resumable unit. */
|
|
90
|
+
get sessionId(): string;
|
|
91
|
+
/**
|
|
92
|
+
* Options for `propagateAttributes` from `@atlanai/sdk/tracing`.
|
|
93
|
+
*
|
|
94
|
+
* Carries the experiment join and the subject join. A nested
|
|
95
|
+
* `propagateAttributes({ sessionId })` still wins for the spans inside it.
|
|
96
|
+
*/
|
|
40
97
|
get traceOptions(): {
|
|
41
98
|
experimentId: string;
|
|
99
|
+
sessionId: string;
|
|
42
100
|
metadata?: Record<string, unknown>;
|
|
43
101
|
};
|
|
44
102
|
}
|
|
45
103
|
/** Create a running experiment over a dataset ID or exact dataset name. */
|
|
46
104
|
export declare function startExperiment(client: AtlanClient, dataset: string, body: Readonly<Record<string, unknown>>, options?: StartExperimentOptions): Promise<EvalRun>;
|
|
105
|
+
export interface ExperimentTracesOptions {
|
|
106
|
+
limit?: number;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Every trace an experiment recorded, newest first.
|
|
110
|
+
*
|
|
111
|
+
* **The experiment is the scope eval traces are filed under.** A subject's own
|
|
112
|
+
* Traces tab (`GET /agent/v1/agents/{id}/traces`) resolves on the trace's
|
|
113
|
+
* *creator identity*, so it lists a run only when the run's spans were exported
|
|
114
|
+
* with that agent's own credential. An eval exported with your user key or a
|
|
115
|
+
* service-account key is filed under that identity instead, and the agent's
|
|
116
|
+
* Traces tab reads empty even though every trace exists. That is not the traces
|
|
117
|
+
* going missing; it is a different scope. Read them here, and call
|
|
118
|
+
* `recordExperimentSession` so the run is also reachable from the subject's
|
|
119
|
+
* Sessions tab.
|
|
120
|
+
*
|
|
121
|
+
* To fill the agent's own Traces tab, export the spans as the agent: pass
|
|
122
|
+
* `logger: initLogger({ apiKey: <the agent's credential> })` while the
|
|
123
|
+
* management `client` keeps your own, since the agent's identity is not
|
|
124
|
+
* entitled to create experiments.
|
|
125
|
+
*/
|
|
126
|
+
export declare function experimentTraces(client: AtlanClient, experimentId: string, options?: ExperimentTracesOptions): Promise<unknown[]>;
|
|
127
|
+
export interface RecordExperimentSessionOptions {
|
|
128
|
+
sessionStatus?: string;
|
|
129
|
+
title?: string;
|
|
130
|
+
}
|
|
131
|
+
export declare function recordExperimentSession(client: AtlanClient, run: EvalRun, options?: RecordExperimentSessionOptions): Promise<unknown | undefined>;
|
|
47
132
|
export interface EvalCase<Input, Expected = unknown, Metadata = Record<string, unknown>> {
|
|
48
133
|
input: Input;
|
|
49
134
|
expected?: Expected;
|
|
50
135
|
metadata?: Metadata;
|
|
51
136
|
tags?: readonly string[];
|
|
52
|
-
/**
|
|
137
|
+
/** Stable case checkpoint ID. Dataset-backed runs use the Registry record ID. */
|
|
53
138
|
id?: string;
|
|
54
139
|
}
|
|
55
140
|
export interface EvalHooks<Expected, Metadata> {
|
|
@@ -145,10 +230,18 @@ export interface EvalResultWithSummary<Input, Output, Expected, Metadata> {
|
|
|
145
230
|
dataset: unknown;
|
|
146
231
|
summary: Record<string, unknown>;
|
|
147
232
|
results: EvalCaseResult<Input, Output, Expected, Metadata>[];
|
|
233
|
+
/** The session id stamped on every span of the run. */
|
|
234
|
+
sessionId: string;
|
|
235
|
+
/**
|
|
236
|
+
* The `session` record that binds the run to the experiment's subject.
|
|
237
|
+
* `undefined` when the experiment named no subject to bind it to.
|
|
238
|
+
*/
|
|
239
|
+
session?: unknown;
|
|
148
240
|
}
|
|
149
241
|
/** Structural trace surface keeps the management bundle decoupled at build time. */
|
|
150
242
|
export interface EvalTraceSpan {
|
|
151
243
|
readonly traceId: string;
|
|
244
|
+
readonly spanId?: string;
|
|
152
245
|
update(fields: Record<string, unknown>): EvalTraceSpan;
|
|
153
246
|
score(name: string, value: unknown, options: {
|
|
154
247
|
scorerId: string;
|
|
@@ -156,6 +249,7 @@ export interface EvalTraceSpan {
|
|
|
156
249
|
comment?: string;
|
|
157
250
|
}): void;
|
|
158
251
|
recordFailure(error: unknown): void;
|
|
252
|
+
markEvidenceComplete?(): EvalTraceSpan;
|
|
159
253
|
}
|
|
160
254
|
interface EvalTraceClient {
|
|
161
255
|
readonly isEnabled: boolean;
|
|
@@ -165,13 +259,46 @@ export interface EvalTraceLogger {
|
|
|
165
259
|
readonly client: EvalTraceClient;
|
|
166
260
|
flush(): Promise<void>;
|
|
167
261
|
}
|
|
262
|
+
export declare function Eval<Input, Output, Expected = unknown, Metadata extends Record<string, unknown> = Record<string, unknown>>(name: string, evaluator: Evaluator<Input, Output, Expected, Metadata>, options?: EvalOptions): Promise<EvalResultWithSummary<Input, Output, Expected, Metadata>>;
|
|
263
|
+
/** One gate result. `ok` is undefined when only a human can answer it. */
|
|
264
|
+
export interface VerificationCheck {
|
|
265
|
+
readonly gate: number;
|
|
266
|
+
readonly name: string;
|
|
267
|
+
readonly ok: boolean | undefined;
|
|
268
|
+
readonly detail: string;
|
|
269
|
+
}
|
|
270
|
+
/** The structured report `verifyExperiment` returns. */
|
|
271
|
+
export interface ExperimentVerification {
|
|
272
|
+
readonly experimentId: string;
|
|
273
|
+
readonly experiment: unknown;
|
|
274
|
+
readonly checks: readonly VerificationCheck[];
|
|
275
|
+
readonly results: readonly unknown[];
|
|
276
|
+
readonly traceIds: readonly string[];
|
|
277
|
+
readonly verifiedTraceIds: readonly string[];
|
|
278
|
+
/** Checks that failed. */
|
|
279
|
+
readonly failures: readonly VerificationCheck[];
|
|
280
|
+
/** Checks a human has to decide. They do not make `ok` false. */
|
|
281
|
+
readonly manual: readonly VerificationCheck[];
|
|
282
|
+
readonly ok: boolean;
|
|
283
|
+
/** Turn a failed gate into an exception, for use in CI. */
|
|
284
|
+
raiseForStatus(): void;
|
|
285
|
+
toString(): string;
|
|
286
|
+
}
|
|
287
|
+
export interface VerifyExperimentOptions {
|
|
288
|
+
/** Fail the gate unless exactly this many result rows exist. */
|
|
289
|
+
readonly expectedCaseCount?: number;
|
|
290
|
+
/** How many case traces to read spans for. `null` reads every one. */
|
|
291
|
+
readonly maxTraces?: number | null;
|
|
292
|
+
}
|
|
168
293
|
/**
|
|
169
|
-
* Run
|
|
294
|
+
* Run the documented seven-point evidence gate over a finished experiment.
|
|
295
|
+
*
|
|
296
|
+
* Reads the experiment, its result rows, its trace list and the spans of up to
|
|
297
|
+
* `maxTraces` case traces, and reports whether the evidence chain actually
|
|
298
|
+
* holds. It only reads; nothing is written.
|
|
170
299
|
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
* carry the root trace ID, traces flush before summary, and the experiment is
|
|
174
|
-
* explicitly finalized.
|
|
300
|
+
* Gate 7, the content and masking policy, cannot be decided from the data and
|
|
301
|
+
* is reported as a manual check rather than silently passed.
|
|
175
302
|
*/
|
|
176
|
-
export declare function
|
|
303
|
+
export declare function verifyExperiment(client: unknown, experimentId: string, options?: VerifyExperimentOptions): Promise<ExperimentVerification>;
|
|
177
304
|
export {};
|