@pmate/cli 0.29.6 → 0.29.7

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/index.d.ts CHANGED
@@ -743,6 +743,8 @@ type CallCommandArgs = {
743
743
  name: string;
744
744
  payload?: Record<string, unknown>;
745
745
  filePath?: string;
746
+ binaryFilePath?: string;
747
+ contentType?: string;
746
748
  hubBaseUrl?: string;
747
749
  timeoutMs?: number;
748
750
  json: boolean;
package/dist/index.js CHANGED
@@ -8249,26 +8249,51 @@ var init_src3 = __esm({
8249
8249
  }
8250
8250
  });
8251
8251
 
8252
- // node_modules/.pnpm/@pmate+hub-sdk@0.3.2/node_modules/@pmate/hub-sdk/dist/AgentClient.js
8252
+ // node_modules/.pnpm/@pmate+hub-sdk@0.4.1/node_modules/@pmate/hub-sdk/dist/AgentClient.js
8253
8253
  var init_AgentClient = __esm({
8254
- "node_modules/.pnpm/@pmate+hub-sdk@0.3.2/node_modules/@pmate/hub-sdk/dist/AgentClient.js"() {
8254
+ "node_modules/.pnpm/@pmate+hub-sdk@0.4.1/node_modules/@pmate/hub-sdk/dist/AgentClient.js"() {
8255
8255
  "use strict";
8256
8256
  init_src();
8257
8257
  init_src3();
8258
8258
  }
8259
8259
  });
8260
8260
 
8261
- // node_modules/.pnpm/@pmate+hub-sdk@0.3.2/node_modules/@pmate/hub-sdk/dist/FunctionService.js
8261
+ // node_modules/.pnpm/@pmate+hub-sdk@0.4.1/node_modules/@pmate/hub-sdk/dist/FunctionService.js
8262
8262
  var init_FunctionService = __esm({
8263
- "node_modules/.pnpm/@pmate+hub-sdk@0.3.2/node_modules/@pmate/hub-sdk/dist/FunctionService.js"() {
8263
+ "node_modules/.pnpm/@pmate+hub-sdk@0.4.1/node_modules/@pmate/hub-sdk/dist/FunctionService.js"() {
8264
8264
  "use strict";
8265
8265
  }
8266
8266
  });
8267
8267
 
8268
- // node_modules/.pnpm/@pmate+hub-sdk@0.3.2/node_modules/@pmate/hub-sdk/dist/HubClient.js
8268
+ // node_modules/.pnpm/@pmate+hub-sdk@0.4.1/node_modules/@pmate/hub-sdk/dist/HubClient.js
8269
8269
  function createCallId(functionId) {
8270
8270
  return uniqHash(`${functionId}-${Date.now()}-${Math.random()}`, "task-v1" /* Task */);
8271
8271
  }
8272
+ function defaultTransportFactory(url) {
8273
+ return new WebsocketClientV2(url);
8274
+ }
8275
+ function streamContentType(value) {
8276
+ if (typeof Blob !== "undefined" && value instanceof Blob) {
8277
+ return value.type || "application/octet-stream";
8278
+ }
8279
+ if (value instanceof Uint8Array || value instanceof ArrayBuffer) {
8280
+ return "application/octet-stream";
8281
+ }
8282
+ if (typeof value === "string")
8283
+ return "text";
8284
+ return "application/json";
8285
+ }
8286
+ async function streamInputForWire(value) {
8287
+ if (typeof Blob !== "undefined" && value instanceof Blob) {
8288
+ return new Uint8Array(await value.arrayBuffer());
8289
+ }
8290
+ return value;
8291
+ }
8292
+ function abortError(reason) {
8293
+ if (reason instanceof Error)
8294
+ return reason;
8295
+ return new Error(typeof reason === "string" ? reason : "Function stream aborted");
8296
+ }
8272
8297
  function ensureWsProtocol(baseUrl) {
8273
8298
  if (/^wss?:\/\//i.test(baseUrl))
8274
8299
  return baseUrl;
@@ -8299,13 +8324,14 @@ function withTimeout(promise, timeoutMs, message) {
8299
8324
  });
8300
8325
  });
8301
8326
  }
8302
- var DEFAULT_TIMEOUT_MS, HubClient, AsyncCallQueue;
8327
+ var DEFAULT_TIMEOUT_MS, DEFAULT_STREAM_TIMEOUT_MS, HubClient, AsyncCallQueue;
8303
8328
  var init_HubClient = __esm({
8304
- "node_modules/.pnpm/@pmate+hub-sdk@0.3.2/node_modules/@pmate/hub-sdk/dist/HubClient.js"() {
8329
+ "node_modules/.pnpm/@pmate+hub-sdk@0.4.1/node_modules/@pmate/hub-sdk/dist/HubClient.js"() {
8305
8330
  "use strict";
8306
8331
  init_src();
8307
8332
  init_src3();
8308
8333
  DEFAULT_TIMEOUT_MS = 4e4;
8334
+ DEFAULT_STREAM_TIMEOUT_MS = 12e4;
8309
8335
  HubClient = class {
8310
8336
  options;
8311
8337
  ws;
@@ -8313,7 +8339,10 @@ var init_HubClient = __esm({
8313
8339
  token;
8314
8340
  authenticated = false;
8315
8341
  calls = /* @__PURE__ */ new Map();
8342
+ streamInputs = /* @__PURE__ */ new Map();
8316
8343
  timeoutMs;
8344
+ streamTimeoutMs;
8345
+ minChunkSizeBytes;
8317
8346
  connectWaiter;
8318
8347
  authWaiter;
8319
8348
  reconnectEnabled = false;
@@ -8321,6 +8350,8 @@ var init_HubClient = __esm({
8321
8350
  constructor(options) {
8322
8351
  this.options = options;
8323
8352
  this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
8353
+ this.streamTimeoutMs = options.streamTimeoutMs ?? DEFAULT_STREAM_TIMEOUT_MS;
8354
+ this.minChunkSizeBytes = options.minChunkSizeBytes ?? 0;
8324
8355
  }
8325
8356
  isConnected() {
8326
8357
  return this.authenticated;
@@ -8331,7 +8362,7 @@ var init_HubClient = __esm({
8331
8362
  this.token = options.token;
8332
8363
  this.connectWaiter = deferred();
8333
8364
  this.authWaiter = deferred();
8334
- const ws = new WebsocketClientV2(ensureWsProtocol(this.options.baseUrl));
8365
+ const ws = (this.options.transportFactory ?? defaultTransportFactory)(ensureWsProtocol(this.options.baseUrl));
8335
8366
  this.ws = ws;
8336
8367
  const stream = ws.getStream();
8337
8368
  void this.consume(stream);
@@ -8392,6 +8423,39 @@ var init_HubClient = __esm({
8392
8423
  this.cancelPendingCall(callId);
8393
8424
  }
8394
8425
  }
8426
+ stream(request2) {
8427
+ this.ensureAuthenticated();
8428
+ const callId = createCallId(request2.functionId);
8429
+ const timeoutMs = request2.timeoutMs ?? this.streamTimeoutMs;
8430
+ const result = new Promise((resolve, reject) => {
8431
+ const timer = setTimeout(() => {
8432
+ void this.abortFunctionStream(callId, new Error(`Function stream timed out: ${request2.functionId}`));
8433
+ }, timeoutMs);
8434
+ this.calls.set(callId, {
8435
+ resolve,
8436
+ reject,
8437
+ timer,
8438
+ abort: (error) => this.sendFunctionStreamCancel(callId, request2.functionId, error)
8439
+ });
8440
+ });
8441
+ void result.catch(() => {
8442
+ });
8443
+ const onAbort = () => {
8444
+ void this.abortFunctionStream(callId, abortError(request2.signal?.reason));
8445
+ };
8446
+ request2.signal?.addEventListener("abort", onAbort, { once: true });
8447
+ if (request2.signal?.aborted)
8448
+ onAbort();
8449
+ void this.sendFunctionStream(callId, request2).catch((error) => {
8450
+ void this.abortFunctionStream(callId, error instanceof Error ? error : new Error(String(error)));
8451
+ });
8452
+ void result.finally(() => request2.signal?.removeEventListener("abort", onAbort)).catch(() => {
8453
+ });
8454
+ return {
8455
+ finish: () => result,
8456
+ cancel: (reason) => this.abortFunctionStream(callId, new Error(reason ?? "Function stream cancelled"))
8457
+ };
8458
+ }
8395
8459
  close() {
8396
8460
  this.reconnectEnabled = false;
8397
8461
  this.reauthenticating = void 0;
@@ -8484,7 +8548,13 @@ var init_HubClient = __esm({
8484
8548
  return;
8485
8549
  clearTimeout(call.timer);
8486
8550
  this.calls.delete(callId);
8487
- call.reject(error);
8551
+ const input = this.streamInputs.get(callId);
8552
+ this.streamInputs.delete(callId);
8553
+ void input?.return?.();
8554
+ if (call.abort)
8555
+ void call.abort(error).then(() => call.reject(error), () => call.reject(error));
8556
+ else
8557
+ call.reject(error);
8488
8558
  }
8489
8559
  handleConnectionLoss(error) {
8490
8560
  this.authenticated = false;
@@ -8498,6 +8568,72 @@ var init_HubClient = __esm({
8498
8568
  profileId
8499
8569
  }, 0 /* PIPELINE */));
8500
8570
  }
8571
+ async sendFunctionStream(callId, request2) {
8572
+ this.ensureAuthenticated();
8573
+ const ws = this.ws;
8574
+ const profileId = this.profileId;
8575
+ const auth = { token: this.token, profileId };
8576
+ const send = (op, contentType, input2) => ws.sendMsg(Msg.create(profileId, "@hub", 6 /* CALL */, {
8577
+ kind: "request",
8578
+ callId,
8579
+ functionId: request2.functionId,
8580
+ op,
8581
+ auth,
8582
+ contentType,
8583
+ ...input2 !== void 0 ? { input: input2 } : {}
8584
+ }, 0 /* PIPELINE */));
8585
+ await send(0 /* Start */, "application/json", request2.params);
8586
+ const minChunkSizeBytes = request2.minChunkSizeBytes ?? this.minChunkSizeBytes;
8587
+ const input = minChunkSizeBytes > 0 ? AsyncStream.chunkBlob(request2.stream, { minBytes: minChunkSizeBytes }) : request2.stream;
8588
+ const iterator = input[Symbol.asyncIterator]();
8589
+ this.streamInputs.set(callId, iterator);
8590
+ try {
8591
+ while (this.calls.has(callId)) {
8592
+ const next = await iterator.next();
8593
+ if (next.done)
8594
+ break;
8595
+ await send(1 /* Data */, streamContentType(next.value), await streamInputForWire(next.value));
8596
+ }
8597
+ if (!this.calls.has(callId))
8598
+ return;
8599
+ await send(2 /* End */, "application/json");
8600
+ } finally {
8601
+ this.streamInputs.delete(callId);
8602
+ }
8603
+ }
8604
+ async abortFunctionStream(callId, error) {
8605
+ const call = this.calls.get(callId);
8606
+ if (!call)
8607
+ return;
8608
+ clearTimeout(call.timer);
8609
+ this.calls.delete(callId);
8610
+ const input = this.streamInputs.get(callId);
8611
+ this.streamInputs.delete(callId);
8612
+ await input?.return?.();
8613
+ try {
8614
+ await call.abort?.(error);
8615
+ } finally {
8616
+ call.reject(error);
8617
+ }
8618
+ }
8619
+ async sendFunctionStreamCancel(callId, functionId, error) {
8620
+ if (!this.ws || !this.profileId || !this.token || !this.authenticated)
8621
+ return;
8622
+ const body = {
8623
+ kind: "request",
8624
+ callId,
8625
+ functionId,
8626
+ op: 3 /* Cancel */,
8627
+ input: { reason: error.message },
8628
+ auth: { token: this.token, profileId: this.profileId }
8629
+ };
8630
+ await this.ws.sendMsg(Msg.create(this.profileId, "@hub", 6 /* CALL */, body, 0 /* PIPELINE */));
8631
+ }
8632
+ ensureAuthenticated() {
8633
+ if (!this.ws || !this.profileId || !this.token || !this.authenticated) {
8634
+ throw new Error("HubClient is not logged in");
8635
+ }
8636
+ }
8501
8637
  reauthenticate() {
8502
8638
  if (this.reauthenticating)
8503
8639
  return this.reauthenticating;
@@ -8610,9 +8746,9 @@ var init_HubClient = __esm({
8610
8746
  }
8611
8747
  });
8612
8748
 
8613
- // node_modules/.pnpm/@pmate+hub-sdk@0.3.2/node_modules/@pmate/hub-sdk/dist/index.js
8749
+ // node_modules/.pnpm/@pmate+hub-sdk@0.4.1/node_modules/@pmate/hub-sdk/dist/index.js
8614
8750
  var init_dist2 = __esm({
8615
- "node_modules/.pnpm/@pmate+hub-sdk@0.3.2/node_modules/@pmate/hub-sdk/dist/index.js"() {
8751
+ "node_modules/.pnpm/@pmate+hub-sdk@0.4.1/node_modules/@pmate/hub-sdk/dist/index.js"() {
8616
8752
  "use strict";
8617
8753
  init_AgentClient();
8618
8754
  init_FunctionService();
@@ -16742,11 +16878,8 @@ var CallCommandHandler = class {
16742
16878
  const input = args.filePath ? readJson2(args.filePath) : args.payload;
16743
16879
  try {
16744
16880
  await hub.login({ token: session.token, profileId: session.profileId, timeoutMs: args.timeoutMs });
16745
- const output = await hub.call({
16746
- functionId: `${args.namespace}:${args.name}`,
16747
- input,
16748
- timeoutMs: args.timeoutMs
16749
- });
16881
+ const functionId = `${args.namespace}:${args.name}`;
16882
+ const output = args.binaryFilePath ? await callWithBinaryFile(hub, functionId, args.binaryFilePath, args.contentType, args.timeoutMs) : await hub.call({ functionId, input, timeoutMs: args.timeoutMs });
16750
16883
  if (args.json || typeof output !== "string") ui.plain(JSON.stringify(output ?? null, null, 2));
16751
16884
  else ui.plain(output);
16752
16885
  } finally {
@@ -16754,6 +16887,35 @@ var CallCommandHandler = class {
16754
16887
  }
16755
16888
  }
16756
16889
  };
16890
+ async function callWithBinaryFile(hub, functionId, filePath, contentType, timeoutMs) {
16891
+ const absolutePath = import_node_path20.default.resolve(process.cwd(), filePath);
16892
+ if (!(0, import_node_fs15.existsSync)(absolutePath)) throw new Error(`Binary file not found: ${absolutePath}`);
16893
+ const mimeType = contentType || inferContentType(absolutePath);
16894
+ const result = hub.stream({
16895
+ functionId,
16896
+ stream: streamFile(absolutePath, mimeType),
16897
+ timeoutMs
16898
+ });
16899
+ return result.finish();
16900
+ }
16901
+ async function* streamFile(filePath, contentType) {
16902
+ for await (const chunk of (0, import_node_fs15.createReadStream)(filePath)) {
16903
+ yield new Blob([chunk], { type: contentType });
16904
+ }
16905
+ }
16906
+ function inferContentType(filePath) {
16907
+ const contentTypes = {
16908
+ ".aac": "audio/aac",
16909
+ ".flac": "audio/flac",
16910
+ ".m4a": "audio/mp4",
16911
+ ".mp3": "audio/mpeg",
16912
+ ".ogg": "audio/ogg",
16913
+ ".opus": "audio/opus",
16914
+ ".wav": "audio/wav",
16915
+ ".webm": "audio/webm"
16916
+ };
16917
+ return contentTypes[import_node_path20.default.extname(filePath).toLowerCase()] || "application/octet-stream";
16918
+ }
16757
16919
  function readJson2(filePath) {
16758
16920
  const absolutePath = import_node_path20.default.resolve(process.cwd(), filePath);
16759
16921
  if (!(0, import_node_fs15.existsSync)(absolutePath)) throw new Error(`JSON file not found: ${absolutePath}`);
@@ -22739,10 +22901,12 @@ init_namespacedRef();
22739
22901
  function parseCallArgs(tokens) {
22740
22902
  const rest = [...tokens];
22741
22903
  const ref = rest.shift();
22742
- if (!ref) throw new Error("Usage: call <namespace:functionId> [--payload <json>|--file <path>]");
22904
+ if (!ref) throw new Error("Usage: call <namespace:functionId> [--payload <json>|--file <path>|--binary-file <path>]");
22743
22905
  const parsed = parseNamespacedRef(ref, { entityLabel: "function ref" });
22744
22906
  let payload;
22745
22907
  let filePath;
22908
+ let binaryFilePath;
22909
+ let contentType;
22746
22910
  let hubBaseUrl;
22747
22911
  let timeoutMs;
22748
22912
  let json = false;
@@ -22760,12 +22924,17 @@ function parseCallArgs(tokens) {
22760
22924
  }
22761
22925
  payload = decoded;
22762
22926
  } else if (option === "--file") filePath = value();
22927
+ else if (option === "--binary-file") binaryFilePath = value();
22928
+ else if (option === "--content-type") contentType = value();
22763
22929
  else if (option === "--hub-base-url") hubBaseUrl = value();
22764
22930
  else if (option === "--timeout-ms") timeoutMs = Number.parseInt(value(), 10);
22765
22931
  else if (option === "--json") json = true;
22766
22932
  else throw new Error(`Unknown call option: ${option}`);
22767
22933
  }
22768
- if (payload && filePath) throw new Error("Provide only one of --payload or --file");
22934
+ if ([payload, filePath, binaryFilePath].filter(Boolean).length > 1) {
22935
+ throw new Error("Provide only one of --payload, --file or --binary-file");
22936
+ }
22937
+ if (contentType && !binaryFilePath) throw new Error("--content-type requires --binary-file");
22769
22938
  if (timeoutMs !== void 0 && (!Number.isInteger(timeoutMs) || timeoutMs < 1)) {
22770
22939
  throw new Error("--timeout-ms must be a positive integer");
22771
22940
  }
@@ -22775,6 +22944,8 @@ function parseCallArgs(tokens) {
22775
22944
  name: parsed.objectId,
22776
22945
  payload,
22777
22946
  filePath,
22947
+ binaryFilePath,
22948
+ contentType,
22778
22949
  hubBaseUrl,
22779
22950
  timeoutMs,
22780
22951
  json
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pmate/cli",
3
- "version": "0.29.6",
3
+ "version": "0.29.7",
4
4
  "description": "CLI utilities for the pMate project",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -31,7 +31,7 @@
31
31
  "@alicloud/sts20150401": "^1.2.0",
32
32
  "@linear/sdk": "^70.0.0",
33
33
  "@pmate/chat-sdk": "^0.2.0",
34
- "@pmate/hub-sdk": "^0.3.2",
34
+ "@pmate/hub-sdk": "^0.4.1",
35
35
  "@types/ali-oss": "^6.16.13",
36
36
  "ajv": "^8.17.1",
37
37
  "ali-oss": "^6.23.0",