@agentxm/registry-client 0.28.4 → 0.28.6

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.
@@ -50,6 +50,11 @@ export interface GetExtensionsByOwnerArgs {
50
50
  * - `name`: extension name
51
51
  * - `version`: specific version to fetch, or `None` for latest
52
52
  */
53
+ /** Bytes received so far and the declared total when the transport reports one. */
54
+ export interface ArchiveDownloadProgress {
55
+ readonly done: number;
56
+ readonly total?: number | undefined;
57
+ }
53
58
  export interface GetExtensionPackageArgs {
54
59
  readonly owner: Handle;
55
60
  readonly type: ExtensionType;
@@ -57,6 +62,11 @@ export interface GetExtensionPackageArgs {
57
62
  readonly version: Option.Option<Version | VersionRange>;
58
63
  /** Marks an archive read used only to verify compatibility before selection. */
59
64
  readonly usagePurpose?: "verification";
65
+ /**
66
+ * Observes archive bytes as they arrive. Called once per received chunk;
67
+ * callers throttle before publishing. Never called for a cache hit.
68
+ */
69
+ readonly onProgress?: (progress: ArchiveDownloadProgress) => Effect.Effect<void>;
60
70
  }
61
71
  /**
62
72
  * Options for fetching extension index metadata from a registry.
@@ -9,7 +9,7 @@
9
9
  * @experimental This API is unstable and may change without notice.
10
10
  * @packageDocumentation
11
11
  */
12
- export type { RegistryClient, RegistryExtensionManifest, DiscoverPackageInput, DiscoverPackagesArgs, GetExtensionsByOwnerArgs, GetExtensionsByOwnerResponse, GetExtensionIndexArgs, GetExactExtensionVersionArgs, ExactExtensionVersion, GetExtensionVisibilityArgs, GetExtensionPackageArgs, GetExtensionPackageResponse, PublishExtensionArgs, PublishExtensionResponse, RegistryPublishWarning, PreviewExtensionPublishesArgs, PublishPreviewResult, PublishPreviewTarget, OwnerExistsResponse, ExtensionExistsArgs, ExtensionExistsResponse, ExtensionVisibility, UpdateExtensionVisibilityArgs, } from "./client.js";
12
+ export type { RegistryClient, RegistryExtensionManifest, DiscoverPackageInput, DiscoverPackagesArgs, GetExtensionsByOwnerArgs, GetExtensionsByOwnerResponse, GetExtensionIndexArgs, GetExactExtensionVersionArgs, ExactExtensionVersion, GetExtensionVisibilityArgs, ArchiveDownloadProgress, GetExtensionPackageArgs, GetExtensionPackageResponse, PublishExtensionArgs, PublishExtensionResponse, RegistryPublishWarning, PreviewExtensionPublishesArgs, PublishPreviewResult, PublishPreviewTarget, OwnerExistsResponse, ExtensionExistsArgs, ExtensionExistsResponse, ExtensionVisibility, UpdateExtensionVisibilityArgs, } from "./client.js";
13
13
  export { createRegistryClient } from "./client.js";
14
14
  export { createLocalRegistryClient } from "./local-client.js";
15
15
  export { createRemoteRegistryClient } from "./remote-client.js";
@@ -9,8 +9,11 @@
9
9
  * @experimental This API is unstable and may change without notice.
10
10
  * @packageDocumentation
11
11
  */
12
+ import * as Headers from "effect/unstable/http/Headers";
12
13
  import * as HttpClient from "effect/unstable/http/HttpClient";
13
14
  import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
15
+ import * as MutableRef from "effect/MutableRef";
16
+ import * as Stream from "effect/Stream";
14
17
  import * as Effect from "effect/Effect";
15
18
  import * as Option from "effect/Option";
16
19
  import * as Schema from "effect/Schema";
@@ -197,6 +200,35 @@ const extensionDeclarationToDiscoveryRef = (value) => {
197
200
  : { versionRange: value.versionRange }),
198
201
  };
199
202
  };
203
+ const contentLength = (response) => Option.match(Headers.get(response.headers, "content-length"), {
204
+ onNone: () => undefined,
205
+ onSome: (value) => {
206
+ const parsed = Number(value);
207
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined;
208
+ },
209
+ });
210
+ /**
211
+ * Stream one archive body into memory, reporting received bytes per chunk.
212
+ * Non-2xx statuses fail as `HttpClientError` so the caller's mapping keeps
213
+ * the response evidence.
214
+ */
215
+ const downloadArchive = (http, path, onProgress) => Effect.gen(function* () {
216
+ const response = yield* HttpClient.filterStatusOk(http).execute(HttpClientRequest.get(path));
217
+ const total = contentLength(response);
218
+ const received = MutableRef.make(0);
219
+ const report = onProgress ?? (() => Effect.void);
220
+ const chunks = yield* response.stream.pipe(Stream.tap((chunk) => report({
221
+ done: MutableRef.updateAndGet(received, (done) => done + chunk.byteLength),
222
+ ...(total === undefined ? {} : { total }),
223
+ })), Stream.runCollect);
224
+ const archive = new Uint8Array(MutableRef.get(received));
225
+ let offset = 0;
226
+ for (const chunk of chunks) {
227
+ archive.set(chunk, offset);
228
+ offset += chunk.byteLength;
229
+ }
230
+ return archive;
231
+ });
200
232
  const registryRequestMetadata = (method, url) => ({
201
233
  service: "registry",
202
234
  method,
@@ -216,9 +248,7 @@ const registryRequestMetadata = (method, url) => ({
216
248
  export const createRemoteRegistryClient = (baseUrl, httpClient, archiveCache, requestPolicy) => {
217
249
  const remoteHttpClient = captureRegistryErrorResponseBodies(httpClient.pipe(HttpClient.mapRequest(HttpClientRequest.prependUrl(baseUrl))));
218
250
  const client = GeneratedRegistryClient.make(remoteHttpClient);
219
- const verificationArchiveClient = GeneratedRegistryClient.make(remoteHttpClient, {
220
- transformClient: (baseClient) => Effect.succeed(baseClient.pipe(HttpClient.mapRequest(HttpClientRequest.setHeader("x-agentxm-usage-purpose", "verification")))),
221
- });
251
+ const verificationHttpClient = remoteHttpClient.pipe(HttpClient.mapRequest(HttpClientRequest.setHeader("x-agentxm-usage-purpose", "verification")));
222
252
  const executeRemoteRequest = (effect, args) => executeRegistryRequest(effect, {
223
253
  operation: args.operation,
224
254
  request: registryRequestMetadata(args.method, new URL(args.path, baseUrl).href),
@@ -457,12 +487,13 @@ export const createRemoteRegistryClient = (baseUrl, httpClient, archiveCache, re
457
487
  };
458
488
  }
459
489
  }
460
- // Step 3: Download archive
461
- const archiveClient = args.usagePurpose === "verification" ? verificationArchiveClient : client;
462
- const archive = yield* executeRemoteRequest(archiveClient.ExtensionsDownloadArchive(args.owner, pluralizeType(args.type), args.name, resolvedEntry.value.version, undefined), {
490
+ // Step 3: Download archive, streaming the body so the caller observes
491
+ // progress as bytes arrive; the transport never decides how often.
492
+ const archivePath = `/v1/extensions/${args.owner}/${pluralizeType(args.type)}/${args.name}/${resolvedEntry.value.version}/archive`;
493
+ const archive = yield* executeRemoteRequest(downloadArchive(args.usagePurpose === "verification" ? verificationHttpClient : remoteHttpClient, archivePath, args.onProgress), {
463
494
  operation: "download package archive",
464
495
  method: "GET",
465
- path: `/v1/extensions/${args.owner}/${pluralizeType(args.type)}/${args.name}/${resolvedEntry.value.version}/archive`,
496
+ path: archivePath,
466
497
  replaySafety: safe,
467
498
  mapError: mapArchiveFetchError,
468
499
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentxm/registry-client",
3
- "version": "0.28.4",
3
+ "version": "0.28.6",
4
4
  "description": "AXM registry integration: local and remote registry clients over the generated OpenAPI transport, request policy and retries, typed registry failures, archive cache, and lifecycle administration for the axm CLI. Unstable and unsupported — use the axm.sh CLI.",
5
5
  "type": "module",
6
6
  "license": "FSL-1.1-MIT",
@@ -18,6 +18,7 @@
18
18
  "exports": {
19
19
  ".": {
20
20
  "types": "./dist/src/index.d.ts",
21
+ "axm-source": "./src/index.ts",
21
22
  "default": "./dist/src/index.js"
22
23
  }
23
24
  },
@@ -38,8 +39,8 @@
38
39
  "effect": "4.0.0-rc.112",
39
40
  "fflate": "^0.8.3",
40
41
  "semver": "^7.8.5",
41
- "@agentxm/extension-model": "^0.28.4",
42
- "@agentxm/registry-protocol": "^0.28.4"
42
+ "@agentxm/extension-model": "^0.28.6",
43
+ "@agentxm/registry-protocol": "^0.28.6"
43
44
  },
44
45
  "devDependencies": {
45
46
  "@effect/openapi-generator": "4.0.0-rc.112",