@aexhq/sdk 0.58.0 → 0.59.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/tools.js CHANGED
@@ -1,17 +1,14 @@
1
- import { inspectEnvironment, isEnvironmentRef, } from "@aexhq/environment";
1
+ import { callback as callbackComponent } from "@aexhq/env-app";
2
2
  import * as z from "zod";
3
3
  import { jcsSha256 } from "./json.js";
4
4
  const EMPTY_INPUT = z.object({});
5
5
  const TOOL_NAME = /^[A-Za-z_][A-Za-z0-9_-]{0,63}$/u;
6
- const ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/u;
7
- const SHA256 = /^[0-9a-f]{64}$/u;
8
6
  export function tool(inputOrHandler, maybeHandler) {
9
7
  if (typeof inputOrHandler === "function") {
10
8
  return makeTool({
11
9
  ...(inputOrHandler.name === "" ? {} : { name: inputOrHandler.name }),
12
10
  input: EMPTY_INPUT,
13
11
  handler: inputOrHandler,
14
- requirements: Object.freeze({}),
15
12
  });
16
13
  }
17
14
  if (typeof maybeHandler !== "function")
@@ -20,7 +17,6 @@ export function tool(inputOrHandler, maybeHandler) {
20
17
  ...(maybeHandler.name === "" ? {} : { name: maybeHandler.name }),
21
18
  input: inputOrHandler,
22
19
  handler: maybeHandler,
23
- requirements: Object.freeze({}),
24
20
  });
25
21
  }
26
22
  function makeTool(draft) {
@@ -30,10 +26,7 @@ function makeTool(draft) {
30
26
  ...(draft.description === undefined ? {} : { description: draft.description }),
31
27
  input: draft.input,
32
28
  ...(draft.output === undefined ? {} : { output: draft.output }),
33
- requirements: draft.requirements,
34
29
  handler: draft.handler,
35
- ...(draft.setupHandler === undefined ? {} : { setupHandler: draft.setupHandler }),
36
- ...(draft.artifact === undefined ? {} : { artifact: draft.artifact }),
37
30
  describe(description) {
38
31
  if (description.trim() === "" || description.length > 4096) {
39
32
  throw new TypeError("Tool description must contain 1 through 4096 characters");
@@ -48,65 +41,19 @@ function makeTool(draft) {
48
41
  schemaOf(output, `${draft.name ?? "Tool"} output`);
49
42
  return makeTool({ ...draft, output });
50
43
  },
51
- needs(requirements) {
52
- return makeTool({ ...draft, requirements: normalizeRequirements(requirements) });
53
- },
54
- setup(handler) {
55
- if (typeof handler !== "function")
56
- throw new TypeError("Tool setup requires a function");
57
- return makeTool({ ...draft, setupHandler: handler });
58
- },
59
- bind(environment) {
60
- if (!isEnvironmentRef(environment))
61
- throw new TypeError("Tool binding requires an EnvironmentRef");
62
- return Object.freeze({ kind: "aex.bound-tool", tool: makeTool(draft), environment });
63
- },
64
- });
65
- }
66
- export function withPreparedArtifact(value, artifact) {
67
- assertTool(value);
68
- assertArtifact(artifact);
69
- return makeTool({
70
- ...(value.name === undefined ? {} : { name: value.name }),
71
- ...(value.description === undefined ? {} : { description: value.description }),
72
- input: value.input,
73
- ...(value.output === undefined ? {} : { output: value.output }),
74
- requirements: value.requirements,
75
- handler: value.handler,
76
- ...(value.setupHandler === undefined ? {} : { setupHandler: value.setupHandler }),
77
- artifact: Object.freeze({
78
- ...artifact,
79
- layers: Object.freeze(artifact.layers.map((layer) => Object.freeze({ ...layer }))),
80
- }),
81
44
  });
82
45
  }
83
- export async function compileTools(selections, declared, secrets = {}) {
84
- const environments = normalizeEnvironments(declared);
85
- const selected = [...(selections ?? [])];
86
- if (selected.length > 0 && environments.byName.size === 0) {
87
- throw new TypeError("Tools require at least one declared environment");
88
- }
89
- const items = [];
90
- const bundles = new Map();
91
- const layers = new Map();
46
+ export async function compileCallbacks(selections) {
47
+ const components = [];
92
48
  const registrations = [];
93
49
  const names = new Set();
94
- let callbackClientId;
95
- for (const selection of selected) {
96
- const value = selection.kind === "aex.bound-tool" ? selection.tool : selection;
50
+ for (const value of selections) {
97
51
  assertTool(value);
98
52
  const contract = await compileContract(value);
99
- if (names.has(contract.name))
53
+ if (names.has(contract.name)) {
100
54
  throw new TypeError(`Tool ${JSON.stringify(contract.name)} was selected twice`);
101
- names.add(contract.name);
102
- const explicit = selection.kind === "aex.bound-tool" ? selection.environment : undefined;
103
- const environment = chooseEnvironment(contract.name, value, explicit, environments);
104
- const environmentName = environments.byRef.get(environment);
105
- const environmentProfile = inspectEnvironment(environment).serialized.profile;
106
- for (const key of value.requirements.env ?? []) {
107
- if (!(key in secrets))
108
- throw new TypeError(`Tool ${JSON.stringify(contract.name)} requires missing secret ${JSON.stringify(key)}`);
109
55
  }
56
+ names.add(contract.name);
110
57
  const definition = {
111
58
  name: contract.name,
112
59
  ...(contract.description === undefined ? {} : { description: contract.description }),
@@ -114,180 +61,22 @@ export async function compileTools(selections, declared, secrets = {}) {
114
61
  output_schema: contract.outputSchema ?? {},
115
62
  contract_digest: contract.contractDigest,
116
63
  };
117
- if (environmentProfile.kind === "callbacks") {
118
- const descriptor = inspectEnvironment(environment).serialized;
119
- const id = descriptor.configuration.id;
120
- if (typeof id !== "string" || id.trim() === "") {
121
- throw new TypeError(`Callback environment ${JSON.stringify(environmentName)} must serialize a non-empty id`);
122
- }
123
- if (callbackClientId !== undefined && callbackClientId !== id) {
124
- throw new TypeError("A session currently supports one callback process id");
125
- }
126
- callbackClientId = id;
127
- const registration = `tool:${contract.contractDigest}`;
128
- registrations.push(Object.freeze({
129
- registration,
130
- name: contract.name,
131
- contractDigest: contract.contractDigest,
132
- input: value.input,
133
- ...(value.output === undefined ? {} : { output: value.output }),
134
- handler: value.handler,
135
- }));
136
- items.push({
137
- definition,
138
- executor: {
139
- kind: "environment",
140
- environment: environmentName,
141
- callback_registration: registration,
142
- requirements: wireRequirements(value.requirements),
143
- },
144
- });
145
- continue;
146
- }
147
- if (value.artifact === undefined) {
148
- throw new TypeError(`Tool ${JSON.stringify(contract.name)} has no prepared computer artifact`);
149
- }
150
- assertArtifact(value.artifact);
151
- const layerRefs = [];
152
- for (const layer of value.artifact.layers) {
153
- const bytes = await readArtifactLayer(layer);
154
- const existing = layers.get(layer.digest);
155
- const payload = {
156
- checksum: layer.digest,
157
- bytes: layer.bytes,
158
- media_type: layer.mediaType,
159
- content: bytes,
160
- };
161
- if (existing !== undefined &&
162
- (existing.bytes !== payload.bytes || existing.media_type !== payload.media_type)) {
163
- throw new TypeError(`Prepared artifact layer ${layer.digest} conflicts with an earlier layer`);
164
- }
165
- layers.set(layer.digest, payload);
166
- layerRefs.push({
167
- checksum: layer.digest,
168
- bytes: layer.bytes,
169
- media_type: layer.mediaType,
170
- mount_path: layer.mountPath,
171
- unpack: layer.unpack,
172
- });
173
- }
174
- const manifest = {
175
- checksum: value.artifact.digest,
176
- bytes: value.artifact.bytes,
177
- target: value.artifact.target,
178
- execute_path: value.artifact.execute,
179
- ...(value.artifact.setup === undefined ? {} : { setup_path: value.artifact.setup }),
180
- layers: layerRefs,
181
- };
182
- const manifestIdentity = {
183
- profile: "computer/v1",
184
- target: value.artifact.target,
185
- execute_path: value.artifact.execute,
186
- setup_path: value.artifact.setup ?? null,
187
- layers: layerRefs,
188
- };
189
- if (await jcsSha256(manifestIdentity) !== value.artifact.digest) {
190
- throw new TypeError(`Prepared artifact ${value.artifact.digest} manifest digest changed`);
191
- }
192
- const existingManifest = bundles.get(value.artifact.digest);
193
- if (existingManifest !== undefined && JSON.stringify(existingManifest) !== JSON.stringify(manifest)) {
194
- throw new TypeError(`Prepared artifact ${value.artifact.digest} conflicts with an earlier manifest`);
195
- }
196
- bundles.set(value.artifact.digest, manifest);
197
- items.push({
198
- definition,
199
- executor: {
200
- kind: "environment",
201
- environment: environmentName,
202
- artifact_digest: value.artifact.digest,
203
- requirements: wireRequirements(value.requirements),
204
- },
205
- });
64
+ const registration = `tool:${contract.contractDigest}`;
65
+ components.push(callbackComponent(definition, registration));
66
+ registrations.push(Object.freeze({
67
+ registration,
68
+ name: contract.name,
69
+ contractDigest: contract.contractDigest,
70
+ input: value.input,
71
+ ...(value.output === undefined ? {} : { output: value.output }),
72
+ handler: value.handler,
73
+ }));
206
74
  }
207
75
  return {
208
- items: Object.freeze(items),
209
- bundles: Object.freeze([...bundles.values()]),
210
- layers: Object.freeze([...layers.values()]),
211
- clientRegistrations: Object.freeze(registrations),
212
- environments: environments.serialized,
213
- environmentNames: environments.byRef,
214
- ...(callbackClientId === undefined ? {} : { callbackClientId }),
76
+ components: Object.freeze(components),
77
+ registrations: Object.freeze(registrations),
215
78
  };
216
79
  }
217
- function normalizeEnvironments(declared) {
218
- const byName = new Map();
219
- const byRef = new Map();
220
- const serialized = Object.create(null);
221
- for (const [name, environment] of Object.entries(declared ?? {})) {
222
- if (!/^[A-Za-z][A-Za-z0-9_-]{0,63}$/u.test(name)) {
223
- throw new TypeError(`Invalid environment name ${JSON.stringify(name)}`);
224
- }
225
- if (!isEnvironmentRef(environment))
226
- throw new TypeError(`Environment ${JSON.stringify(name)} is not an EnvironmentRef`);
227
- const previous = byRef.get(environment);
228
- if (previous !== undefined) {
229
- throw new TypeError(`The same EnvironmentRef was declared as ${JSON.stringify(previous)} and ${JSON.stringify(name)}`);
230
- }
231
- byName.set(name, environment);
232
- byRef.set(environment, name);
233
- serialized[name] = inspectEnvironment(environment).serialized;
234
- }
235
- return { byName, byRef, serialized: Object.freeze(serialized) };
236
- }
237
- function chooseEnvironment(toolName, value, explicit, environments) {
238
- if (explicit !== undefined) {
239
- const name = environments.byRef.get(explicit);
240
- if (name === undefined)
241
- throw new TypeError(`Tool ${JSON.stringify(toolName)} is bound to an environment absent from environments`);
242
- const reasons = incompatibilities(value, inspectEnvironment(explicit).serialized.profile);
243
- if (reasons.length > 0) {
244
- throw new TypeError(`Tool ${JSON.stringify(toolName)} is bound to ${JSON.stringify(name)}, which ${reasons.join(" and ")}`);
245
- }
246
- return explicit;
247
- }
248
- const matches = [];
249
- const failures = [];
250
- for (const [name, environment] of environments.byName) {
251
- const reasons = incompatibilities(value, inspectEnvironment(environment).serialized.profile);
252
- if (reasons.length === 0)
253
- matches.push(environment);
254
- else
255
- failures.push(`- ${JSON.stringify(name)} ${reasons.join(" and ")}`);
256
- }
257
- if (matches.length === 1)
258
- return matches[0];
259
- if (matches.length === 0) {
260
- throw new TypeError(`Tool ${JSON.stringify(toolName)} has no compatible environment:\n${failures.join("\n")}`);
261
- }
262
- const names = matches.map((environment) => JSON.stringify(environments.byRef.get(environment))).join(", ");
263
- throw new TypeError(`Tool ${JSON.stringify(toolName)} matches more than one environment: ${names}. Bind it explicitly.`);
264
- }
265
- function incompatibilities(value, profile) {
266
- const reasons = [];
267
- if (profile.kind === "computer") {
268
- if (value.artifact === undefined || profile.platform !== value.artifact.target) {
269
- reasons.push(`cannot launch target ${JSON.stringify(value.artifact?.target ?? "application-callback")}`);
270
- }
271
- }
272
- else {
273
- if (value.artifact !== undefined)
274
- reasons.push("does not run prepared artifacts");
275
- if (value.setupHandler !== undefined)
276
- reasons.push("does not provide tool setup");
277
- }
278
- const needs = value.requirements;
279
- if (needs.workspace === true && profile.kind !== "computer")
280
- reasons.push("is missing workspace");
281
- if (needs.processes === true && profile.kind !== "computer")
282
- reasons.push("is missing processes");
283
- if (needs.network !== undefined && needs.network.length > 0 && profile.network !== "allowlist") {
284
- reasons.push("cannot enforce network allowlists");
285
- }
286
- if (needs.recovery !== undefined && needs.recovery !== profile.recovery) {
287
- reasons.push(`provides ${profile.recovery} recovery instead of ${needs.recovery}`);
288
- }
289
- return reasons;
290
- }
291
80
  async function compileContract(value) {
292
81
  const name = value.name;
293
82
  if (name === undefined)
@@ -309,46 +98,6 @@ async function compileContract(value) {
309
98
  contractDigest: await jcsSha256(canonical),
310
99
  };
311
100
  }
312
- function wireRequirements(requirements) {
313
- return {
314
- ...(requirements.env === undefined ? {} : { env: [...requirements.env] }),
315
- ...(requirements.workspace === undefined ? {} : { workspace: requirements.workspace }),
316
- ...(requirements.processes === undefined ? {} : { processes: requirements.processes }),
317
- ...(requirements.network === undefined
318
- ? {}
319
- : { network: requirements.network.map(({ host, port }) => ({ host, ports: [port], protocol: "tls" })) }),
320
- ...(requirements.streaming === undefined ? {} : { streaming: requirements.streaming }),
321
- ...(requirements.recovery === undefined
322
- ? {}
323
- : { recovery: requirements.recovery === "replay-safe" ? "replay_safe" : requirements.recovery }),
324
- };
325
- }
326
- function normalizeRequirements(requirements) {
327
- const env = [...(requirements.env ?? [])];
328
- if (new Set(env).size !== env.length)
329
- throw new TypeError("Tool environment requirements contain duplicates");
330
- for (const key of env)
331
- if (!ENV_NAME.test(key))
332
- throw new TypeError(`Invalid required environment name ${JSON.stringify(key)}`);
333
- const network = [...(requirements.network ?? [])];
334
- if (network.length > 32)
335
- throw new TypeError("Tool network requirements exceed 32 destinations");
336
- for (const destination of network) {
337
- if (destination.host.trim() === "" || destination.host.length > 253)
338
- throw new TypeError("Invalid tool network host");
339
- if (!Number.isInteger(destination.port) || destination.port < 1 || destination.port > 65535) {
340
- throw new TypeError("Invalid tool network port");
341
- }
342
- }
343
- return Object.freeze({
344
- ...(env.length === 0 ? {} : { env: Object.freeze(env) }),
345
- ...(requirements.workspace === undefined ? {} : { workspace: requirements.workspace }),
346
- ...(requirements.processes === undefined ? {} : { processes: requirements.processes }),
347
- ...(network.length === 0 ? {} : { network: Object.freeze(network.map((item) => Object.freeze({ ...item }))) }),
348
- ...(requirements.streaming === undefined ? {} : { streaming: requirements.streaming }),
349
- ...(requirements.recovery === undefined ? {} : { recovery: requirements.recovery }),
350
- });
351
- }
352
101
  function schemaOf(schema, label) {
353
102
  try {
354
103
  const value = z.toJSONSchema(schema, { target: "draft-2020-12", unrepresentable: "throw" });
@@ -368,57 +117,3 @@ function assertToolName(name) {
368
117
  if (!TOOL_NAME.test(name))
369
118
  throw new TypeError(`Invalid Tool name ${JSON.stringify(name)}`);
370
119
  }
371
- function assertArtifact(artifact) {
372
- if (!SHA256.test(artifact.digest))
373
- throw new TypeError("Prepared artifact digest must be lower-case SHA-256 hex");
374
- if (!Number.isSafeInteger(artifact.bytes) || artifact.bytes < 1)
375
- throw new TypeError("Prepared artifact bytes are invalid");
376
- if (!artifact.execute.startsWith("/"))
377
- throw new TypeError("Prepared artifact execute entrypoint must be absolute");
378
- if (artifact.setup !== undefined && !artifact.setup.startsWith("/")) {
379
- throw new TypeError("Prepared artifact setup entrypoint must be absolute");
380
- }
381
- if (!Array.isArray(artifact.layers) || artifact.layers.length === 0) {
382
- throw new TypeError("Prepared artifact must contain at least one immutable layer");
383
- }
384
- let bytes = 0;
385
- for (const layer of artifact.layers) {
386
- if (!SHA256.test(layer.digest))
387
- throw new TypeError("Prepared artifact layer digest must be lower-case SHA-256 hex");
388
- if (!Number.isSafeInteger(layer.bytes) || layer.bytes < 1)
389
- throw new TypeError("Prepared artifact layer bytes are invalid");
390
- if (!(layer.source instanceof URL))
391
- throw new TypeError("Prepared artifact layer source must be a URL");
392
- if (!layer.mountPath.startsWith("/"))
393
- throw new TypeError("Prepared artifact layer mount path must be absolute");
394
- bytes += layer.bytes;
395
- }
396
- if (bytes !== artifact.bytes)
397
- throw new TypeError("Prepared artifact bytes do not equal its layers");
398
- }
399
- async function readArtifactLayer(layer) {
400
- let bytes;
401
- if (layer.source.protocol === "file:") {
402
- const { readFile } = await import("node:fs/promises");
403
- bytes = await readFile(layer.source);
404
- }
405
- else if (layer.source.protocol === "https:" || layer.source.protocol === "data:") {
406
- const response = await fetch(layer.source);
407
- if (!response.ok)
408
- throw new TypeError(`Could not read artifact layer ${layer.digest}: HTTP ${response.status}`);
409
- bytes = new Uint8Array(await response.arrayBuffer());
410
- }
411
- else {
412
- throw new TypeError(`Unsupported artifact layer source protocol ${layer.source.protocol}`);
413
- }
414
- if (bytes.byteLength !== layer.bytes)
415
- throw new TypeError(`Artifact layer ${layer.digest} byte length changed`);
416
- const actual = await sha256(bytes);
417
- if (actual !== layer.digest)
418
- throw new TypeError(`Artifact layer ${layer.digest} content digest changed`);
419
- return bytes;
420
- }
421
- async function sha256(bytes) {
422
- const digest = await globalThis.crypto.subtle.digest("SHA-256", Uint8Array.from(bytes).buffer);
423
- return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
424
- }
@@ -1,5 +1,5 @@
1
- import type { Event } from "@aexhq/session-protocol/session";
2
- import type { JsonRequestOptions, TransferTicket } from "@aexhq/session-protocol";
1
+ import type { Event } from "@aexhq/brain/session";
2
+ import type { JsonRequestOptions, TransferTicket } from "@aexhq/brain";
3
3
  export type Fetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
4
4
  export interface EventOptions {
5
5
  after?: number;
@@ -21,7 +21,6 @@ export declare class Transport {
21
21
  downloadTransfer(ticket: TransferTicket, signal?: AbortSignal, expectedBytes?: number): Promise<Uint8Array>;
22
22
  downloadTransferStream(ticket: TransferTicket, signal?: AbortSignal, expectedBytes?: number): Promise<ReadableStream<Uint8Array>>;
23
23
  uploadTransfer(ticket: TransferTicket, content: Uint8Array | (() => ReadableStream<Uint8Array>), bytes: number, signal?: AbortSignal): Promise<void>;
24
- ensureArtifactLayer(digest: string, mediaType: string, content: Uint8Array, signal?: AbortSignal): Promise<void>;
25
24
  json<T>(method: "GET" | "POST" | "DELETE", path: string, options?: JsonRequestOptions): Promise<T>;
26
25
  /** Accept one durable deletion job; strict callers poll its short status resource client-side. */
27
26
  deleteSession(sessionId: string, waitForCompletion: boolean, signal?: AbortSignal): Promise<void>;
package/dist/transport.js CHANGED
@@ -1,4 +1,4 @@
1
- import { MAX_CREATE_SESSION_REQUEST_BYTES, MAX_CUSTOMER_OBSERVATION_BYTES, MAX_MESSAGE_REQUEST_BYTES, MAX_PUBLIC_EVENT_BYTES, } from "@aexhq/session-protocol";
1
+ import { MAX_CREATE_SESSION_REQUEST_BYTES, MAX_CUSTOMER_OBSERVATION_BYTES, MAX_MESSAGE_REQUEST_BYTES, MAX_PUBLIC_EVENT_BYTES, } from "@aexhq/brain";
2
2
  import { AbortError, AexError, SessionError, abortError, errorFromApi } from "./errors.js";
3
3
  const MAX_ORDINARY_JSON_BYTES = 2 * 1024 * 1024;
4
4
  const MAX_ERROR_RESPONSE_BYTES = 64 * 1024;
@@ -127,38 +127,6 @@ export class Transport {
127
127
  });
128
128
  }
129
129
  }
130
- async ensureArtifactLayer(digest, mediaType, content, signal) {
131
- const path = `/v1/artifacts/${encodeURIComponent(digest)}`;
132
- const authorization = `Bearer ${this.#apiKey}`;
133
- const existing = await this.#fetch(`${this.baseUrl}${path}`, {
134
- method: "HEAD",
135
- redirect: "error",
136
- headers: { Authorization: authorization },
137
- ...(signal === undefined ? {} : { signal }),
138
- });
139
- if (existing.ok) {
140
- const bytes = Number(existing.headers.get("content-length"));
141
- const storedMediaType = existing.headers.get("content-type");
142
- if (bytes !== content.byteLength || storedMediaType !== mediaType) {
143
- throw new SessionError(`Uploaded Tool artifact ${digest} has conflicting metadata`);
144
- }
145
- return;
146
- }
147
- if (existing.status !== 404)
148
- throw await this.responseError(existing);
149
- const uploaded = await this.#fetch(`${this.baseUrl}${path}`, {
150
- method: "PUT",
151
- redirect: "error",
152
- headers: {
153
- Authorization: authorization,
154
- "Content-Type": mediaType,
155
- },
156
- body: arrayBufferBody(content),
157
- ...(signal === undefined ? {} : { signal }),
158
- });
159
- if (!uploaded.ok)
160
- throw await this.responseError(uploaded);
161
- }
162
130
  async json(method, path, options = {}) {
163
131
  const attempts = options.retry === true ? 2 : 1;
164
132
  // Serialize once before the first await. A caller mutating its source object after a lost
@@ -453,13 +421,13 @@ function assertTransferTicket(ticket, method) {
453
421
  }
454
422
  function validateCustomerEnvironmentGrant(baseUrl, grant) {
455
423
  if (!/^[A-Za-z0-9_.-]{1,128}$/u.test(grant.grant_id)) {
456
- throw new SessionError("Aex returned an invalid customer Hand grant id");
424
+ throw new SessionError("Aex returned an invalid customer Environment grant id");
457
425
  }
458
426
  if (!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]{1,2048}$/u.test(grant.protocol)) {
459
- throw new SessionError("Aex returned an invalid customer Hand WebSocket protocol");
427
+ throw new SessionError("Aex returned an invalid customer Environment WebSocket protocol");
460
428
  }
461
429
  if (!/^[\x21-\x7e]{1,2048}$/u.test(grant.observation_token)) {
462
- throw new SessionError("Aex returned an invalid customer Hand observation token");
430
+ throw new SessionError("Aex returned an invalid customer Environment observation token");
463
431
  }
464
432
  let socket;
465
433
  let observation;
@@ -470,13 +438,13 @@ function validateCustomerEnvironmentGrant(baseUrl, grant) {
470
438
  expectedObservation = new URL(`${baseUrl}/v1/customer-environment/observations/${encodeURIComponent(grant.grant_id)}`);
471
439
  }
472
440
  catch (cause) {
473
- throw new SessionError("Aex returned an invalid customer Hand URL", { cause });
441
+ throw new SessionError("Aex returned an invalid customer Environment URL", { cause });
474
442
  }
475
443
  const secureSocket = socket.protocol === "wss:" ||
476
444
  (socket.protocol === "ws:" && isLoopback(socket.hostname));
477
445
  if (!secureSocket || socket.username !== "" || socket.password !== "" ||
478
446
  socket.search !== "" || socket.hash !== "") {
479
- throw new SessionError("Aex customer Hand sockets require credential-free WSS (or loopback WS for development)");
447
+ throw new SessionError("Aex customer Environment sockets require credential-free WSS (or loopback WS for development)");
480
448
  }
481
449
  if (observation.href !== expectedObservation.href) {
482
450
  throw new SessionError("Aex returned an unsafe customer Environment observation URL");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aexhq/sdk",
3
- "version": "0.58.0",
3
+ "version": "0.59.1",
4
4
  "description": "TypeScript SDK for Aex sessions",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://aex.dev",
@@ -23,10 +23,6 @@
23
23
  "types": "./dist/index.d.ts",
24
24
  "import": "./dist/index.js"
25
25
  },
26
- "./internal": {
27
- "types": "./dist/internal.d.ts",
28
- "import": "./dist/internal.js"
29
- },
30
26
  "./package.json": "./package.json"
31
27
  },
32
28
  "files": [
@@ -38,8 +34,8 @@
38
34
  "test": "tsc -p tsconfig.json && node --test"
39
35
  },
40
36
  "dependencies": {
41
- "@aexhq/session-protocol": "0.3.1",
42
- "@aexhq/environment": "0.1.0"
37
+ "@aexhq/brain": "0.3.2",
38
+ "@aexhq/env-app": "0.2.0"
43
39
  },
44
40
  "peerDependencies": {
45
41
  "zod": "4.4.3"
@@ -1,2 +0,0 @@
1
- export { withPreparedArtifact } from "./tools.js";
2
- export type { PreparedArtifact, Tool } from "./tools.js";
package/dist/internal.js DELETED
@@ -1 +0,0 @@
1
- export { withPreparedArtifact } from "./tools.js";