@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.
Files changed (148) hide show
  1. package/README.md +6 -2
  2. package/dist/client.d.ts +20 -3
  3. package/dist/client.js +130 -9
  4. package/dist/errors.d.ts +10 -0
  5. package/dist/errors.js +34 -1
  6. package/dist/evals.d.ts +135 -8
  7. package/dist/evals.js +1004 -73
  8. package/dist/index.d.ts +3 -2
  9. package/dist/index.js +7 -1
  10. package/dist/manifest.json +84 -11
  11. package/dist/raw/agent/apis/AgentsApi.d.ts +29 -0
  12. package/dist/raw/agent/apis/AgentsApi.js +62 -1
  13. package/dist/raw/agent/apis/SessionsApi.d.ts +2 -2
  14. package/dist/raw/agent/apis/SessionsApi.js +2 -2
  15. package/dist/raw/agent/models/AgentAgentArtifactView.d.ts +48 -0
  16. package/dist/raw/agent/models/AgentAgentArtifactView.js +13 -0
  17. package/dist/raw/agent/models/AgentAgentEnvironmentArtifactView.d.ts +12 -0
  18. package/dist/raw/agent/models/AgentAgentEnvironmentArtifactView.js +2 -0
  19. package/dist/raw/agent/models/AgentAgentEnvironmentMeta.d.ts +12 -0
  20. package/dist/raw/agent/models/AgentAgentEnvironmentMeta.js +2 -0
  21. package/dist/raw/agent/models/AgentAgentMeta.d.ts +48 -0
  22. package/dist/raw/agent/models/AgentAgentMeta.js +13 -0
  23. package/dist/raw/agent/models/AgentAgentProviderArtifactView.d.ts +55 -2
  24. package/dist/raw/agent/models/AgentAgentProviderArtifactView.js +8 -0
  25. package/dist/raw/agent/models/AgentAgentProviderCreate.d.ts +24 -3
  26. package/dist/raw/agent/models/AgentAgentProviderCreate.js +4 -0
  27. package/dist/raw/agent/models/AgentAgentProviderMeta.d.ts +56 -13
  28. package/dist/raw/agent/models/AgentAgentProviderMeta.js +8 -0
  29. package/dist/raw/agent/models/AgentAgentProviderPatch.d.ts +13 -0
  30. package/dist/raw/agent/models/AgentAgentProviderPatch.js +4 -0
  31. package/dist/raw/agent/models/AgentAgentProviderType.d.ts +19 -9
  32. package/dist/raw/agent/models/AgentAgentProviderType.js +18 -8
  33. package/dist/raw/agent/models/AgentListAgentFrameworks401Response.d.ts +1 -0
  34. package/dist/raw/agent/models/AgentListAgentFrameworks401Response.js +1 -0
  35. package/dist/raw/agent/models/AgentPageSessionEventView.d.ts +3 -3
  36. package/dist/raw/agent/models/AgentPageSessionEventView.js +3 -3
  37. package/dist/raw/agent/models/AgentRemoteSessionEvent.d.ts +38 -0
  38. package/dist/raw/agent/models/AgentRemoteSessionEvent.js +58 -0
  39. package/dist/raw/agent/models/AgentSessionArtifactView.d.ts +25 -0
  40. package/dist/raw/agent/models/AgentSessionArtifactView.js +2 -0
  41. package/dist/raw/agent/models/AgentSessionEventView.d.ts +30 -0
  42. package/dist/raw/agent/models/AgentSessionEventView.js +57 -0
  43. package/dist/raw/agent/models/AgentSessionMeta.d.ts +25 -0
  44. package/dist/raw/agent/models/AgentSessionMeta.js +2 -0
  45. package/dist/raw/agent/models/AgentSessionStreamFrame.d.ts +8 -6
  46. package/dist/raw/agent/models/AgentSessionStreamFrame.js +7 -0
  47. package/dist/raw/agent/models/AgentSyncState.d.ts +27 -0
  48. package/dist/raw/agent/models/AgentSyncState.js +55 -0
  49. package/dist/raw/agent/models/TriggerBody.d.ts +52 -0
  50. package/dist/raw/agent/models/TriggerBody.js +58 -0
  51. package/dist/raw/agent/models/index.d.ts +4 -1
  52. package/dist/raw/agent/models/index.js +4 -1
  53. package/dist/raw/eval/models/EvalListDatasets401Response.d.ts +1 -0
  54. package/dist/raw/eval/models/EvalListDatasets401Response.js +1 -0
  55. package/dist/raw/file/models/FileList401Response.d.ts +1 -0
  56. package/dist/raw/file/models/FileList401Response.js +1 -0
  57. package/dist/raw/mcp/apis/ServersApi.d.ts +2 -2
  58. package/dist/raw/mcp/apis/ServersApi.js +2 -2
  59. package/dist/raw/mcp/models/McpConnectionState.d.ts +2 -1
  60. package/dist/raw/mcp/models/McpConnectionState.js +2 -1
  61. package/dist/raw/mcp/models/McpListServers401Response.d.ts +1 -0
  62. package/dist/raw/mcp/models/McpListServers401Response.js +1 -0
  63. package/dist/raw/mcp/models/McpServerTestResponse.d.ts +13 -2
  64. package/dist/raw/model/models/ModelListProviders401Response.d.ts +1 -0
  65. package/dist/raw/model/models/ModelListProviders401Response.js +1 -0
  66. package/dist/raw/registry/apis/WorkspacesApi.d.ts +28 -0
  67. package/dist/raw/registry/apis/WorkspacesApi.js +61 -1
  68. package/dist/raw/registry/models/CreateWorkspaceBody.d.ts +9 -0
  69. package/dist/raw/registry/models/CreateWorkspaceBody.js +2 -0
  70. package/dist/raw/registry/models/RegistryAggregate401Response.d.ts +1 -0
  71. package/dist/raw/registry/models/RegistryAggregate401Response.js +1 -0
  72. package/dist/raw/registry/models/RegistryWorkspaceView.d.ts +9 -0
  73. package/dist/raw/registry/models/RegistryWorkspaceView.js +4 -0
  74. package/dist/raw/registry/models/SearchRequest.d.ts +1 -1
  75. package/dist/raw/registry/models/SetVisibilityBody.d.ts +33 -0
  76. package/dist/raw/registry/models/SetVisibilityBody.js +50 -0
  77. package/dist/raw/registry/models/index.d.ts +1 -0
  78. package/dist/raw/registry/models/index.js +1 -0
  79. package/dist/raw/secret/apis/OauthApi.d.ts +143 -0
  80. package/dist/raw/secret/apis/OauthApi.js +335 -0
  81. package/dist/raw/secret/apis/index.d.ts +1 -0
  82. package/dist/raw/secret/apis/index.js +19 -0
  83. package/dist/raw/secret/index.d.ts +1 -0
  84. package/dist/raw/secret/index.js +1 -0
  85. package/dist/raw/secret/models/GatewayOauthCompleteRequest.d.ts +32 -0
  86. package/dist/raw/secret/models/GatewayOauthCompleteRequest.js +50 -0
  87. package/dist/raw/secret/models/GatewayOauthCompletion.d.ts +46 -0
  88. package/dist/raw/secret/models/GatewayOauthCompletion.js +55 -0
  89. package/dist/raw/secret/models/GatewayOauthConnection.d.ts +83 -0
  90. package/dist/raw/secret/models/GatewayOauthConnection.js +83 -0
  91. package/dist/raw/secret/models/GatewayOauthOwner.d.ts +31 -0
  92. package/dist/raw/secret/models/GatewayOauthOwner.js +59 -0
  93. package/dist/raw/secret/models/GatewayOauthProviderView.d.ts +69 -0
  94. package/dist/raw/secret/models/GatewayOauthProviderView.js +69 -0
  95. package/dist/raw/secret/models/GatewayOauthStartRequest.d.ts +52 -0
  96. package/dist/raw/secret/models/GatewayOauthStartRequest.js +59 -0
  97. package/dist/raw/secret/models/GatewayOauthStarted.d.ts +39 -0
  98. package/dist/raw/secret/models/GatewayOauthStarted.js +54 -0
  99. package/dist/raw/secret/models/SecretCompleteOauth400Response.d.ts +70 -0
  100. package/dist/raw/secret/models/SecretCompleteOauth400Response.js +80 -0
  101. package/dist/raw/secret/models/SecretCompleteOauth413Response.d.ts +64 -0
  102. package/dist/raw/secret/models/SecretCompleteOauth413Response.js +74 -0
  103. package/dist/raw/secret/models/SecretCompleteOauth415Response.d.ts +64 -0
  104. package/dist/raw/secret/models/SecretCompleteOauth415Response.js +74 -0
  105. package/dist/raw/secret/models/SecretCompleteOauth422Response.d.ts +63 -0
  106. package/dist/raw/secret/models/SecretCompleteOauth422Response.js +75 -0
  107. package/dist/raw/secret/models/SecretDisconnectOauth400Response.d.ts +67 -0
  108. package/dist/raw/secret/models/SecretDisconnectOauth400Response.js +77 -0
  109. package/dist/raw/secret/models/SecretOauthCallback400Response.d.ts +68 -0
  110. package/dist/raw/secret/models/SecretOauthCallback400Response.js +78 -0
  111. package/dist/raw/secret/models/SecretOauthCallback401Response.d.ts +80 -0
  112. package/dist/raw/secret/models/SecretOauthCallback401Response.js +90 -0
  113. package/dist/raw/secret/models/SecretOauthCallback403Response.d.ts +66 -0
  114. package/dist/raw/secret/models/SecretOauthCallback403Response.js +76 -0
  115. package/dist/raw/secret/models/SecretOauthCallback404Response.d.ts +65 -0
  116. package/dist/raw/secret/models/SecretOauthCallback404Response.js +75 -0
  117. package/dist/raw/secret/models/SecretOauthCallback500Response.d.ts +64 -0
  118. package/dist/raw/secret/models/SecretOauthCallback500Response.js +74 -0
  119. package/dist/raw/secret/models/SecretOauthCallback503Response.d.ts +66 -0
  120. package/dist/raw/secret/models/SecretOauthCallback503Response.js +76 -0
  121. package/dist/raw/secret/models/SecretOauthCallback504Response.d.ts +63 -0
  122. package/dist/raw/secret/models/SecretOauthCallback504Response.js +75 -0
  123. package/dist/raw/secret/models/index.d.ts +19 -0
  124. package/dist/raw/secret/models/index.js +19 -0
  125. package/dist/raw/skill/models/SkillInsightSchemas401Response.d.ts +1 -0
  126. package/dist/raw/skill/models/SkillInsightSchemas401Response.js +1 -0
  127. package/dist/resource-types.d.ts +670 -0
  128. package/dist/resource-types.js +2 -0
  129. package/dist/resources.d.ts +10 -0
  130. package/dist/resources.js +54 -4
  131. package/dist/resources.json +86 -0
  132. package/dist/tracing/client.d.ts +8 -1
  133. package/dist/tracing/client.js +43 -16
  134. package/dist/tracing/config.d.ts +3 -1
  135. package/dist/tracing/config.js +7 -2
  136. package/dist/tracing/exporter.d.ts +19 -1
  137. package/dist/tracing/exporter.js +56 -14
  138. package/dist/tracing/propagation.d.ts +2 -0
  139. package/dist/tracing/propagation.js +16 -0
  140. package/dist/tracing/semconv.d.ts +4 -0
  141. package/dist/tracing/semconv.js +14 -2
  142. package/dist/tracing/spans.d.ts +2 -0
  143. package/dist/tracing/spans.js +12 -1
  144. package/dist/tracing/version.d.ts +1 -1
  145. package/dist/tracing/version.js +1 -1
  146. package/package.json +1 -1
  147. package/dist/raw/agent/models/Box.d.ts +0 -342
  148. 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
- constructor(name: string, module: GeneratedModule, configuration: GeneratedConfiguration, serviceOperations: readonly Omit<Operation, "service">[]);
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
- constructor(name, module, configuration, serviceOperations) {
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
- function wrapGeneratedAPI(api, operationMethods) {
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 Reflect.apply(value, target, args);
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
- const timer = setTimeout(() => controller.abort(new Error("request timed out")), timeoutMs);
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
- super(`Atlan API request failed with status ${options.status}${suffix}`);
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
- /** Options for `propagateAttributes` from `@atlanai/sdk/tracing`. */
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
- /** Registry dataset-record join; normally populated by `dataset`. */
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 a complete Registry evaluation from a compact Braintrust-shaped definition.
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
- * Every case is a root OTel trace. Task/provider spans and scorer spans nest
172
- * beneath it, verdicts cite immutable Registry scorer versions, result rows
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 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>>;
303
+ export declare function verifyExperiment(client: unknown, experimentId: string, options?: VerifyExperimentOptions): Promise<ExperimentVerification>;
177
304
  export {};