@parall/parall 1.56.1 → 1.57.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.
@@ -44537,7 +44537,7 @@ var require_headers = __commonJS({
44537
44537
  }
44538
44538
  }
44539
44539
  };
44540
- var Headers = class _Headers {
44540
+ var Headers2 = class _Headers {
44541
44541
  #guard;
44542
44542
  /**
44543
44543
  * @type {HeadersList}
@@ -44678,13 +44678,13 @@ var require_headers = __commonJS({
44678
44678
  target.#headersList = list;
44679
44679
  }
44680
44680
  };
44681
- var { getHeadersGuard, setHeadersGuard, getHeadersList, setHeadersList } = Headers;
44682
- Reflect.deleteProperty(Headers, "getHeadersGuard");
44683
- Reflect.deleteProperty(Headers, "setHeadersGuard");
44684
- Reflect.deleteProperty(Headers, "getHeadersList");
44685
- Reflect.deleteProperty(Headers, "setHeadersList");
44686
- iteratorMixin("Headers", Headers, headersListSortAndCombine, 0, 1);
44687
- Object.defineProperties(Headers.prototype, {
44681
+ var { getHeadersGuard, setHeadersGuard, getHeadersList, setHeadersList } = Headers2;
44682
+ Reflect.deleteProperty(Headers2, "getHeadersGuard");
44683
+ Reflect.deleteProperty(Headers2, "setHeadersGuard");
44684
+ Reflect.deleteProperty(Headers2, "getHeadersList");
44685
+ Reflect.deleteProperty(Headers2, "setHeadersList");
44686
+ iteratorMixin("Headers", Headers2, headersListSortAndCombine, 0, 1);
44687
+ Object.defineProperties(Headers2.prototype, {
44688
44688
  append: kEnumerableProperty,
44689
44689
  delete: kEnumerableProperty,
44690
44690
  get: kEnumerableProperty,
@@ -44702,7 +44702,7 @@ var require_headers = __commonJS({
44702
44702
  webidl.converters.HeadersInit = function(V, prefix, argument) {
44703
44703
  if (webidl.util.Type(V) === webidl.util.Types.OBJECT) {
44704
44704
  const iterator = Reflect.get(V, Symbol.iterator);
44705
- if (!util.types.isProxy(V) && iterator === Headers.prototype.entries) {
44705
+ if (!util.types.isProxy(V) && iterator === Headers2.prototype.entries) {
44706
44706
  try {
44707
44707
  return getHeadersList(V).entriesList;
44708
44708
  } catch {
@@ -44723,7 +44723,7 @@ var require_headers = __commonJS({
44723
44723
  fill,
44724
44724
  // for test.
44725
44725
  compareHeaderName,
44726
- Headers,
44726
+ Headers: Headers2,
44727
44727
  HeadersList,
44728
44728
  getHeadersGuard,
44729
44729
  setHeadersGuard,
@@ -44737,7 +44737,7 @@ var require_headers = __commonJS({
44737
44737
  var require_response = __commonJS({
44738
44738
  "../node_modules/.pnpm/undici@7.24.8/node_modules/undici/lib/web/fetch/response.js"(exports2, module2) {
44739
44739
  "use strict";
44740
- var { Headers, HeadersList, fill, getHeadersGuard, setHeadersGuard, setHeadersList } = require_headers();
44740
+ var { Headers: Headers2, HeadersList, fill, getHeadersGuard, setHeadersGuard, setHeadersList } = require_headers();
44741
44741
  var { extractBody, cloneBody, mixinBody, streamRegistry, bodyUnusable } = require_body();
44742
44742
  var util = require_util2();
44743
44743
  var nodeUtil = __require("node:util");
@@ -44759,7 +44759,7 @@ var require_response = __commonJS({
44759
44759
  var assert = __require("node:assert");
44760
44760
  var { isomorphicEncode, serializeJavascriptValueToJSONString } = require_infra();
44761
44761
  var textEncoder = new TextEncoder("utf-8");
44762
- var Response = class _Response {
44762
+ var Response2 = class _Response {
44763
44763
  /** @type {Headers} */
44764
44764
  #headers;
44765
44765
  #state;
@@ -44813,7 +44813,7 @@ var require_response = __commonJS({
44813
44813
  }
44814
44814
  init = webidl.converters.ResponseInit(init);
44815
44815
  this.#state = makeResponse({});
44816
- this.#headers = new Headers(kConstruct);
44816
+ this.#headers = new Headers2(kConstruct);
44817
44817
  setHeadersGuard(this.#headers, "response");
44818
44818
  setHeadersList(this.#headers, this.#state.headersList);
44819
44819
  let bodyWithType = null;
@@ -44931,13 +44931,13 @@ var require_response = __commonJS({
44931
44931
  response.#state = newState;
44932
44932
  }
44933
44933
  };
44934
- var { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState } = Response;
44935
- Reflect.deleteProperty(Response, "getResponseHeaders");
44936
- Reflect.deleteProperty(Response, "setResponseHeaders");
44937
- Reflect.deleteProperty(Response, "getResponseState");
44938
- Reflect.deleteProperty(Response, "setResponseState");
44939
- mixinBody(Response, getResponseState);
44940
- Object.defineProperties(Response.prototype, {
44934
+ var { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState } = Response2;
44935
+ Reflect.deleteProperty(Response2, "getResponseHeaders");
44936
+ Reflect.deleteProperty(Response2, "setResponseHeaders");
44937
+ Reflect.deleteProperty(Response2, "getResponseState");
44938
+ Reflect.deleteProperty(Response2, "setResponseState");
44939
+ mixinBody(Response2, getResponseState);
44940
+ Object.defineProperties(Response2.prototype, {
44941
44941
  type: kEnumerableProperty,
44942
44942
  url: kEnumerableProperty,
44943
44943
  status: kEnumerableProperty,
@@ -44953,7 +44953,7 @@ var require_response = __commonJS({
44953
44953
  configurable: true
44954
44954
  }
44955
44955
  });
44956
- Object.defineProperties(Response, {
44956
+ Object.defineProperties(Response2, {
44957
44957
  json: kEnumerableProperty,
44958
44958
  redirect: kEnumerableProperty,
44959
44959
  error: kEnumerableProperty
@@ -45086,9 +45086,9 @@ var require_response = __commonJS({
45086
45086
  }
45087
45087
  }
45088
45088
  function fromInnerResponse(innerResponse, guard) {
45089
- const response = new Response(kConstruct);
45089
+ const response = new Response2(kConstruct);
45090
45090
  setResponseState(response, innerResponse);
45091
- const headers = new Headers(kConstruct);
45091
+ const headers = new Headers2(kConstruct);
45092
45092
  setResponseHeaders(response, headers);
45093
45093
  setHeadersList(headers, innerResponse.headersList);
45094
45094
  setHeadersGuard(headers, guard);
@@ -45140,14 +45140,14 @@ var require_response = __commonJS({
45140
45140
  converter: webidl.converters.HeadersInit
45141
45141
  }
45142
45142
  ]);
45143
- webidl.is.Response = webidl.util.MakeTypeAssertion(Response);
45143
+ webidl.is.Response = webidl.util.MakeTypeAssertion(Response2);
45144
45144
  module2.exports = {
45145
45145
  isNetworkError,
45146
45146
  makeNetworkError,
45147
45147
  makeResponse,
45148
45148
  makeAppropriateNetworkError,
45149
45149
  filterResponse,
45150
- Response,
45150
+ Response: Response2,
45151
45151
  cloneResponse,
45152
45152
  fromInnerResponse,
45153
45153
  getResponseState
@@ -45160,7 +45160,7 @@ var require_request2 = __commonJS({
45160
45160
  "../node_modules/.pnpm/undici@7.24.8/node_modules/undici/lib/web/fetch/request.js"(exports2, module2) {
45161
45161
  "use strict";
45162
45162
  var { extractBody, mixinBody, cloneBody, bodyUnusable } = require_body();
45163
- var { Headers, fill: fillHeaders, HeadersList, setHeadersGuard, getHeadersGuard, setHeadersList, getHeadersList } = require_headers();
45163
+ var { Headers: Headers2, fill: fillHeaders, HeadersList, setHeadersGuard, getHeadersGuard, setHeadersList, getHeadersList } = require_headers();
45164
45164
  var util = require_util2();
45165
45165
  var nodeUtil = __require("node:util");
45166
45166
  var {
@@ -45429,7 +45429,7 @@ var require_request2 = __commonJS({
45429
45429
  requestFinalizer.register(ac, { signal, abort }, abort);
45430
45430
  }
45431
45431
  }
45432
- this.#headers = new Headers(kConstruct);
45432
+ this.#headers = new Headers2(kConstruct);
45433
45433
  setHeadersList(this.#headers, request3.headersList);
45434
45434
  setHeadersGuard(this.#headers, "request");
45435
45435
  if (mode === "no-cors") {
@@ -45770,7 +45770,7 @@ var require_request2 = __commonJS({
45770
45770
  setRequestState(request3, innerRequest);
45771
45771
  setRequestDispatcher(request3, dispatcher);
45772
45772
  setRequestSignal(request3, signal);
45773
- const headers = new Headers(kConstruct);
45773
+ const headers = new Headers2(kConstruct);
45774
45774
  setRequestHeaders(request3, headers);
45775
45775
  setHeadersList(headers, innerRequest.headersList);
45776
45776
  setHeadersGuard(headers, guard);
@@ -48214,8 +48214,8 @@ var require_cookies = __commonJS({
48214
48214
  var { parseSetCookie } = require_parse2();
48215
48215
  var { stringify } = require_util5();
48216
48216
  var { webidl } = require_webidl();
48217
- var { Headers } = require_headers();
48218
- var brandChecks = webidl.brandCheckMultiple([Headers, globalThis.Headers].filter(Boolean));
48217
+ var { Headers: Headers2 } = require_headers();
48218
+ var brandChecks = webidl.brandCheckMultiple([Headers2, globalThis.Headers].filter(Boolean));
48219
48219
  function getCookies(headers) {
48220
48220
  webidl.argumentLengthCheck(arguments, 1, "getCookies");
48221
48221
  brandChecks(headers);
@@ -48956,7 +48956,7 @@ var require_connection = __commonJS({
48956
48956
  var { parseExtensions, isClosed, isClosing, isEstablished, isConnecting, validateCloseCodeAndReason } = require_util6();
48957
48957
  var { makeRequest } = require_request2();
48958
48958
  var { fetching } = require_fetch();
48959
- var { Headers, getHeadersList } = require_headers();
48959
+ var { Headers: Headers2, getHeadersList } = require_headers();
48960
48960
  var { getDecodeSplit } = require_util3();
48961
48961
  var { WebsocketFrameSend } = require_frame();
48962
48962
  var assert = __require("node:assert");
@@ -48978,7 +48978,7 @@ var require_connection = __commonJS({
48978
48978
  useURLCredentials: true
48979
48979
  });
48980
48980
  if (options.headers) {
48981
- const headersList = getHeadersList(new Headers(options.headers));
48981
+ const headersList = getHeadersList(new Headers2(options.headers));
48982
48982
  request3.headersList = headersList;
48983
48983
  }
48984
48984
  const keyValue = crypto3.randomBytes(16).toString("base64");
@@ -51581,7 +51581,10 @@ function buildEventBody(event) {
51581
51581
  } else if (event.type === "channel_message") {
51582
51582
  lines.push(`[Event: channel.message]`);
51583
51583
  const providerLabel = sanitizeMeta(event.channelProvider ?? "external IM");
51584
- const convLabel = event.channelExternalConversationId ? `${sanitizeMeta(event.channelExternalConversationId)} (${sanitizeMeta(event.channelConversationType ?? "conversation")})` : sanitizeMeta(event.channelConversationType ?? "conversation");
51584
+ const convType = sanitizeMeta(event.channelConversationType ?? "conversation");
51585
+ const convId = event.channelExternalConversationId ? sanitizeMeta(event.channelExternalConversationId) : void 0;
51586
+ const convName = event.channelExternalConversationName ? sanitizeMeta(event.channelExternalConversationName) : void 0;
51587
+ const convLabel = convName ? `${convName} (${convId ? `${convId}, ` : ""}${convType})` : convId ? `${convId} (${convType})` : convType;
51585
51588
  lines.push(`[Channel: ${providerLabel} | conversation: ${convLabel}]`);
51586
51589
  lines.push(`[From: ${sanitizeMeta(event.senderName)} (external user, not a Parall member)]`);
51587
51590
  if (event.channelExternalMessageId) {
@@ -51754,6 +51757,8 @@ var ENDPOINTS = {
51754
51757
  // Users
51755
51758
  USERS_ME: `${API_BASE}/users/me`,
51756
51759
  USER_AVATAR: `${API_BASE}/users/me/avatar`,
51760
+ PERSONAL_API_KEYS: `${API_BASE}/users/me/api-keys`,
51761
+ PERSONAL_API_KEY: (keyId) => `${API_BASE}/users/me/api-keys/${keyId}`,
51757
51762
  USER: (id) => `${API_BASE}/users/${id}`,
51758
51763
  // WebSocket ticket
51759
51764
  WS_TICKET: `${API_BASE}/ws/ticket`,
@@ -51768,6 +51773,24 @@ var ENDPOINTS = {
51768
51773
  TEAM_MEMBERS: (orgId, teamId) => `${API_BASE}/orgs/${orgId}/teams/${teamId}/members`,
51769
51774
  TEAM_MEMBER: (orgId, teamId, userId) => `${API_BASE}/orgs/${orgId}/teams/${teamId}/members/${userId}`,
51770
51775
  ORG_MEMBERS_ONLINE: (orgId) => `${API_BASE}/orgs/${orgId}/members/online`,
51776
+ LLM_PROVIDERS: (orgId) => `${API_BASE}/orgs/${orgId}/llm-providers`,
51777
+ LLM_PROVIDER: (orgId, providerId) => `${API_BASE}/orgs/${orgId}/llm-providers/${providerId}`,
51778
+ ORG_LLM_MODELS: (orgId) => `${API_BASE}/orgs/${orgId}/llm-models`,
51779
+ ORG_LLM_MODEL: (orgId, modelRowId) => `${API_BASE}/orgs/${orgId}/llm-models/${modelRowId}`,
51780
+ /**
51781
+ * Platform catalog merged with this org's own model rows. Pass `runtime` to
51782
+ * filter org-added models to the ones that runtime can actually reach —
51783
+ * without it a picker can offer a model the write path rejects.
51784
+ */
51785
+ ORG_MODEL_CATALOG: (orgId, runtime2, includeModel) => {
51786
+ const params = new URLSearchParams();
51787
+ if (runtime2)
51788
+ params.set("runtime", runtime2);
51789
+ if (includeModel)
51790
+ params.set("include_model", includeModel);
51791
+ const qs = params.toString();
51792
+ return `${API_BASE}/orgs/${orgId}/models${qs ? `?${qs}` : ""}`;
51793
+ },
51771
51794
  ORG_MEMBER: (orgId, userId) => `${API_BASE}/orgs/${orgId}/members/${userId}`,
51772
51795
  ORG_MEMBER_CHATS: (orgId, memberId) => `${API_BASE}/orgs/${orgId}/members/${memberId}/chats`,
51773
51796
  ORG_MEMBER_TASKS: (orgId, memberId) => `${API_BASE}/orgs/${orgId}/members/${memberId}/tasks`,
@@ -52521,6 +52544,55 @@ var WechatClient = class extends TaskLabelClient {
52521
52544
  }
52522
52545
  };
52523
52546
 
52547
+ // ../sdk/dist/llm-provider-client.js
52548
+ var LLMProviderClient = class extends WechatClient {
52549
+ async getLLMProviders(orgId) {
52550
+ const response = await this.request("GET", ENDPOINTS.LLM_PROVIDERS(orgId));
52551
+ return response.data;
52552
+ }
52553
+ async createLLMProvider(orgId, data) {
52554
+ return this.request("POST", ENDPOINTS.LLM_PROVIDERS(orgId), data);
52555
+ }
52556
+ /** Omitting `api_key` leaves the stored credential untouched. */
52557
+ async updateLLMProvider(orgId, providerId, data) {
52558
+ return this.request("PATCH", ENDPOINTS.LLM_PROVIDER(orgId, providerId), data);
52559
+ }
52560
+ /** Fails with PROVIDER_IN_USE while model rows still point at it. */
52561
+ async deleteLLMProvider(orgId, providerId) {
52562
+ return this.request("DELETE", ENDPOINTS.LLM_PROVIDER(orgId, providerId));
52563
+ }
52564
+ async getOrgLLMModels(orgId) {
52565
+ const response = await this.request("GET", ENDPOINTS.ORG_LLM_MODELS(orgId));
52566
+ return response.data;
52567
+ }
52568
+ async createOrgLLMModel(orgId, data) {
52569
+ return this.request("POST", ENDPOINTS.ORG_LLM_MODELS(orgId), data);
52570
+ }
52571
+ /**
52572
+ * Patches a model row in place. Repointing a provider or fixing an upstream
52573
+ * name this way avoids the delete-and-recreate window, during which an
52574
+ * org-only model has no upstream at all and its pinned agents fail.
52575
+ */
52576
+ async updateOrgLLMModel(orgId, modelRowId, data) {
52577
+ return this.request("PATCH", ENDPOINTS.ORG_LLM_MODEL(orgId, modelRowId), data);
52578
+ }
52579
+ async deleteOrgLLMModel(orgId, modelRowId) {
52580
+ return this.request("DELETE", ENDPOINTS.ORG_LLM_MODEL(orgId, modelRowId));
52581
+ }
52582
+ /**
52583
+ * The catalog as this org sees it: platform models with the org's rows
52584
+ * merged in. Distinct from the public model catalog, which stays org-agnostic
52585
+ * and cacheable — use this one wherever an org context exists.
52586
+ *
52587
+ * Pass `runtime` on a picker: org-added models are then filtered to what that
52588
+ * runtime's protocol can reach, matching the server-side pin validation.
52589
+ */
52590
+ async getOrgModelCatalog(orgId, runtime2, includeModel) {
52591
+ const response = await this.request("GET", ENDPOINTS.ORG_MODEL_CATALOG(orgId, runtime2, includeModel));
52592
+ return response.data;
52593
+ }
52594
+ };
52595
+
52524
52596
  // ../sdk/dist/attachment-client.js
52525
52597
  var COMPLETION_RETRY_DELAYS_MS = [250, 750];
52526
52598
  function isRetryableCompletionError(error) {
@@ -52529,7 +52601,7 @@ function isRetryableCompletionError(error) {
52529
52601
  const status = error.status;
52530
52602
  return status === 0 || typeof status === "number" && status >= 500;
52531
52603
  }
52532
- var AttachmentClient = class extends WechatClient {
52604
+ var AttachmentClient = class extends LLMProviderClient {
52533
52605
  async getUploadPresignUrl(orgId, req) {
52534
52606
  return this.request("POST", ENDPOINTS.UPLOAD_PRESIGN(orgId), req);
52535
52607
  }
@@ -52557,6 +52629,99 @@ var AttachmentClient = class extends WechatClient {
52557
52629
  }
52558
52630
  };
52559
52631
 
52632
+ // ../sdk/dist/wiki-upload.js
52633
+ function createWikiUploadFormData(params) {
52634
+ const form = new FormData();
52635
+ form.append("path", params.path);
52636
+ form.append("file", params.file);
52637
+ if (params.message)
52638
+ form.append("message", params.message);
52639
+ if (params.uploadId)
52640
+ form.append("upload_id", params.uploadId);
52641
+ if (params.conflict)
52642
+ form.append("conflict", params.conflict);
52643
+ if ("contentRoute" in params && params.contentRoute) {
52644
+ form.append("content_route", params.contentRoute);
52645
+ }
52646
+ return form;
52647
+ }
52648
+ function sendMultipartRequest(options) {
52649
+ if (options.onProgress && typeof XMLHttpRequest !== "undefined") {
52650
+ return multipartXHR(options, options.onProgress);
52651
+ }
52652
+ const timeoutSignal = AbortSignal.timeout(options.timeoutMs);
52653
+ const signal = options.signal ? AbortSignal.any([options.signal, timeoutSignal]) : timeoutSignal;
52654
+ return fetch(options.url, {
52655
+ method: options.method,
52656
+ headers: options.headers,
52657
+ body: options.body,
52658
+ signal
52659
+ });
52660
+ }
52661
+ function multipartXHR(options, onProgress) {
52662
+ return new Promise((resolve3, reject) => {
52663
+ const xhr = new XMLHttpRequest();
52664
+ let settled = false;
52665
+ const finish = (fn) => {
52666
+ if (settled)
52667
+ return;
52668
+ settled = true;
52669
+ options.signal?.removeEventListener("abort", abortFromSignal);
52670
+ fn();
52671
+ };
52672
+ const abortFromSignal = () => xhr.abort();
52673
+ xhr.open(options.method, options.url, true);
52674
+ xhr.timeout = options.timeoutMs;
52675
+ for (const [name, value] of Object.entries(options.headers)) {
52676
+ xhr.setRequestHeader(name, value);
52677
+ }
52678
+ xhr.upload.onprogress = (event) => {
52679
+ try {
52680
+ onProgress(event.loaded, event.lengthComputable ? event.total : 0);
52681
+ } catch {
52682
+ }
52683
+ };
52684
+ xhr.onload = () => finish(() => {
52685
+ const responseHeaders = new Headers();
52686
+ for (const line of xhr.getAllResponseHeaders().trim().split(/[\r\n]+/)) {
52687
+ if (!line)
52688
+ continue;
52689
+ const separator = line.indexOf(":");
52690
+ if (separator > 0) {
52691
+ responseHeaders.append(line.slice(0, separator).trim(), line.slice(separator + 1).trim());
52692
+ }
52693
+ }
52694
+ const responseBody = xhr.status === 204 || xhr.responseText === "" ? null : xhr.responseText;
52695
+ resolve3(new Response(responseBody, {
52696
+ status: xhr.status,
52697
+ statusText: xhr.statusText,
52698
+ headers: responseHeaders
52699
+ }));
52700
+ });
52701
+ xhr.onerror = () => finish(() => reject(new TypeError("Network request failed")));
52702
+ xhr.ontimeout = () => finish(() => reject(new DOMException("Request timed out", "TimeoutError")));
52703
+ xhr.onabort = () => finish(() => reject(new DOMException("Request aborted", "AbortError")));
52704
+ if (options.signal?.aborted) {
52705
+ finish(() => reject(new DOMException("Request aborted", "AbortError")));
52706
+ return;
52707
+ }
52708
+ options.signal?.addEventListener("abort", abortFromSignal, { once: true });
52709
+ xhr.send(options.body);
52710
+ });
52711
+ }
52712
+
52713
+ // ../sdk/dist/wiki-changeset.js
52714
+ function normalizeWikiChangeset(changeset) {
52715
+ return {
52716
+ ...changeset,
52717
+ head_branch: changeset.head_branch ?? null,
52718
+ base_commit: changeset.base_commit ?? null,
52719
+ merge_commit: changeset.merge_commit ?? null,
52720
+ changed_paths: changeset.changed_paths ?? [],
52721
+ file_changes: changeset.file_changes ?? []
52722
+ };
52723
+ }
52724
+
52560
52725
  // ../sdk/dist/client.js
52561
52726
  var ParallClient = class _ParallClient extends AttachmentClient {
52562
52727
  baseUrl;
@@ -52762,23 +52927,27 @@ var ParallClient = class _ParallClient extends AttachmentClient {
52762
52927
  * Multipart upload variant of `request`. Same auth / refresh / error
52763
52928
  * handling, but lets the caller hand us a prepared `FormData` (file +
52764
52929
  * text fields) and skips the JSON content-type. Used by
52765
- * uploadWikiFile / uploadWikiFileToChangeset — wiki binary uploads can
52930
+ * uploadWikiFile / uploadWikiFileToChangeset — wiki file uploads can
52766
52931
  * hit the 100 MiB cap, so a longer 5-minute timeout is used so a
52767
52932
  * 50 MiB blob on a slow connection doesn't get chopped at 15 s.
52768
52933
  */
52769
- async multipartRequest(method, path9, body, retried = false) {
52934
+ async multipartRequest(method, path9, body, retried = false, opts) {
52770
52935
  if (!retried) {
52771
52936
  await this.ensureFreshToken(path9);
52772
52937
  }
52773
52938
  const { "Content-Type": _drop, ...headers } = this.buildHeaders(path9);
52774
52939
  void _drop;
52940
+ const timeoutMs = opts?.timeoutMs ?? 5 * 60 * 1e3;
52775
52941
  let res;
52776
52942
  try {
52777
- res = await fetch(`${this.baseUrlFor(path9)}${path9}`, {
52943
+ res = await sendMultipartRequest({
52778
52944
  method,
52945
+ url: `${this.baseUrlFor(path9)}${path9}`,
52779
52946
  headers,
52780
52947
  body,
52781
- signal: AbortSignal.timeout(5 * 60 * 1e3)
52948
+ timeoutMs,
52949
+ signal: opts?.signal,
52950
+ onProgress: opts?.onProgress
52782
52951
  });
52783
52952
  } catch (err) {
52784
52953
  throw _ParallClient.normalizeFetchError(err);
@@ -52789,7 +52958,7 @@ var ParallClient = class _ParallClient extends AttachmentClient {
52789
52958
  if (!retried && !isAuthPath && this.getRefreshToken) {
52790
52959
  const refreshed = await this.tryRefresh();
52791
52960
  if (refreshed) {
52792
- return this.multipartRequest(method, path9, body, true);
52961
+ return this.multipartRequest(method, path9, body, true, opts);
52793
52962
  }
52794
52963
  }
52795
52964
  if (this.onTokenExpired && !isAuthPath) {
@@ -52868,6 +53037,18 @@ var ParallClient = class _ParallClient extends AttachmentClient {
52868
53037
  async deleteAvatar() {
52869
53038
  return this.request("DELETE", ENDPOINTS.USER_AVATAR);
52870
53039
  }
53040
+ // ---- Personal API keys (org-scoped; JWT session required) ----
53041
+ /** Mints an org-scoped personal API key. The plaintext is returned once and never again. */
53042
+ async createPersonalApiKey(req) {
53043
+ return this.request("POST", ENDPOINTS.PERSONAL_API_KEYS, req);
53044
+ }
53045
+ async listPersonalApiKeys() {
53046
+ const res = await this.request("GET", ENDPOINTS.PERSONAL_API_KEYS);
53047
+ return res.data;
53048
+ }
53049
+ async revokePersonalApiKey(keyId) {
53050
+ return this.request("DELETE", ENDPOINTS.PERSONAL_API_KEY(keyId));
53051
+ }
52871
53052
  async uploadAgentAvatar(orgId, agentId, file) {
52872
53053
  const fd = new FormData();
52873
53054
  fd.append("file", file);
@@ -54086,26 +54267,21 @@ var ParallClient = class _ParallClient extends AttachmentClient {
54086
54267
  * through createWikiChangeset / updateWikiChangeset.
54087
54268
  */
54088
54269
  async uploadWikiFile(orgId, wikiId, params) {
54089
- const fd = new FormData();
54090
- fd.append("path", params.path);
54091
- fd.append("file", params.file);
54092
- if (params.message)
54093
- fd.append("message", params.message);
54094
- return this.multipartRequest("POST", ENDPOINTS.WIKI_UPLOADS(orgId, wikiId), fd);
54270
+ const fd = createWikiUploadFormData(params);
54271
+ return this.multipartRequest("POST", ENDPOINTS.WIKI_UPLOADS(orgId, wikiId), fd, false, {
54272
+ signal: params.signal,
54273
+ onProgress: params.onProgress
54274
+ });
54095
54275
  }
54096
54276
  /**
54097
- * Upload a binary file into a changeset's feature branch (read scope +
54098
- * author-only). Used by reader flow: propose a changeset, attach
54099
- * binary, PATCH markdown that references it. On merge the binary
54100
- * squashes into the default branch.
54277
+ * Upload a file into a changeset's feature branch (read scope +
54278
+ * author-only). The default remains binary-only; contentRoute `auto`
54279
+ * opts into reviewable text for the Web library upload flow. On merge the
54280
+ * branch contents squash into the default branch.
54101
54281
  */
54102
54282
  async uploadWikiFileToChangeset(orgId, wikiId, changesetId, params) {
54103
- const fd = new FormData();
54104
- fd.append("path", params.path);
54105
- fd.append("file", params.file);
54106
- if (params.message)
54107
- fd.append("message", params.message);
54108
- return this.multipartRequest("POST", ENDPOINTS.WIKI_CHANGESET_FILES(orgId, wikiId, changesetId), fd);
54283
+ const fd = createWikiUploadFormData(params);
54284
+ return this.multipartRequest("POST", ENDPOINTS.WIKI_CHANGESET_FILES(orgId, wikiId, changesetId), fd, false, { signal: params.signal, onProgress: params.onProgress });
54109
54285
  }
54110
54286
  /** Remove a binary file from the default branch. Text files must use a
54111
54287
  * changeset delete action. The blob stays reachable via git history. */
@@ -54972,13 +55148,6 @@ var ParallClient = class _ParallClient extends AttachmentClient {
54972
55148
  );
54973
55149
  }
54974
55150
  };
54975
- function normalizeWikiChangeset(changeset) {
54976
- return {
54977
- ...changeset,
54978
- changed_paths: changeset.changed_paths ?? [],
54979
- file_changes: changeset.file_changes ?? []
54980
- };
54981
- }
54982
55151
  var ApiError = class extends Error {
54983
55152
  status;
54984
55153
  code;
@@ -59470,7 +59639,7 @@ var ParallAgentGateway = class {
59470
59639
  const event = {
59471
59640
  type: "channel_message",
59472
59641
  targetId: conv.id,
59473
- targetName: conv.external_user_name || conv.external_conversation_id,
59642
+ targetName: conv.external_conversation_name || conv.external_user_name || conv.external_conversation_id,
59474
59643
  targetType: "channel_conversation",
59475
59644
  senderId: msg.external_user_id || "external",
59476
59645
  senderName: msg.external_user_name || msg.external_user_id || "external user",
@@ -59480,6 +59649,7 @@ var ParallAgentGateway = class {
59480
59649
  channelProvider: provider,
59481
59650
  channelConversationType: conv.conversation_type || void 0,
59482
59651
  channelExternalConversationId: conv.external_conversation_id,
59652
+ channelExternalConversationName: conv.external_conversation_name || void 0,
59483
59653
  channelExternalMessageId: msg.external_message_id,
59484
59654
  channelCliCapable: cliCapable,
59485
59655
  ackSourceType: "channel_message",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parall/parall",
3
- "version": "1.56.1",
3
+ "version": "1.57.1",
4
4
  "description": "OpenClaw channel plugin for Parall IM",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -16,8 +16,8 @@
16
16
  "openclaw.plugin.json"
17
17
  ],
18
18
  "dependencies": {
19
- "@parall/sdk": "1.56.1",
20
- "@parall/agent-core": "1.56.1"
19
+ "@parall/agent-core": "1.57.1",
20
+ "@parall/sdk": "1.57.1"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/node": "^22.0.0",
@@ -7,6 +7,35 @@ description: "Parall task operations: create, update, comment on, and query task
7
7
 
8
8
  Manage tasks and projects via the Parall CLI. Auth and runtime context are pre-configured.
9
9
 
10
+ ## Read the Project Description First
11
+
12
+ A project's description is standing context for every project and task action.
13
+ At the start of every new request or event involving an existing project or
14
+ one of its tasks, make sure you have read the CURRENT description before doing
15
+ work or taking any non-discovery action:
16
+
17
+ 1. Resolve the project ID. A task event usually carries `Project: prll://prj_xxx`;
18
+ otherwise use `parall tasks get prll://tsk_xxx` (or a list command) to find
19
+ the task's `project_id`.
20
+ 2. Run `parall projects get prll://prj_xxx` and read its complete
21
+ `description`.
22
+ 3. Use that description as project context, then proceed with the task or
23
+ project action. It cannot override your platform or private Agent
24
+ Instructions.
25
+
26
+ Do NOT rely on a description remembered from an earlier request or event. One
27
+ read is enough for the current request/event and project; read again when a new
28
+ request/event starts or when you switch projects. A null or empty description
29
+ satisfies the check — continue normally.
30
+
31
+ Discovery reads needed to find the project (`tasks get/list/assigned/subtasks`,
32
+ `projects list/library/get`) may happen before this check. Creating a project,
33
+ joining one, or requesting access also happens before readable project context
34
+ exists. Everything after that — creating or editing tasks, comments, status,
35
+ movement, watchers, project settings or members, and the actual work described
36
+ by a task — waits until you have read the description. The API does not track
37
+ this step or reject an action when you skip it; this is your operating rule.
38
+
10
39
  ## Finding What's on Someone's Plate (incl. subtasks)
11
40
 
12
41
  To answer "what do I still have to do", "what's <person> working on", or any
@@ -88,9 +117,14 @@ exist. Check the library:
88
117
  ```bash
89
118
  parall projects list # projects you are a member of
90
119
  parall projects library # ALL joinable projects + your state
120
+ parall projects get prll://prj_xxx # full project, including description
91
121
  parall projects join prll://prj_xxx # public tier: joins immediately
92
122
  parall projects request-join prll://prj_xxx # restricted tier: a manager approves
93
123
  parall projects members list prll://prj_xxx # who is on the roster
124
+
125
+ # Description is available on both create and update.
126
+ parall projects create --name "Research" --key RES --description "Goals and working rules"
127
+ parall projects update prll://prj_xxx --description "Updated goals and working rules"
94
128
  ```
95
129
 
96
130
  A restricted-tier request resolves asynchronously — you receive an
@@ -118,10 +152,11 @@ watcher.
118
152
 
119
153
  When you receive `[Event: task.assigned]`:
120
154
 
121
- 1. Acknowledge with a comment: `tasks comments add prll://tsk_xxx --body "On it"`
122
- 2. Update status: `tasks update prll://tsk_xxx --status in_progress --placement end`
123
- 3. Do the work
124
- 4. Report results in a comment. If a gate remains — review, merge, deploy,
155
+ 1. Resolve the project and read its current description as described above
156
+ 2. Acknowledge with a comment: `tasks comments add prll://tsk_xxx --body "On it"`
157
+ 3. Update status: `tasks update prll://tsk_xxx --status in_progress --placement end`
158
+ 4. Do the work
159
+ 5. Report results in a comment. If a gate remains — review, merge, deploy,
125
160
  requester acceptance — set `in_review` and name the gate; set `done`
126
161
  only once the work has actually landed
127
162
 
@@ -129,8 +164,9 @@ When you receive `[Event: task.assigned]`:
129
164
 
130
165
  When you receive `[Event: task.comment.created]`, someone commented on a task you are watching. Read the comment body and respond if action is needed:
131
166
 
132
- 1. Review the comment content and task context
133
- 2. Reply via comment: `tasks comments add prll://tsk_xxx --body "Response..."`
134
- 3. If the comment requests status changes, update accordingly
167
+ 1. Resolve the project and read its current description as described above
168
+ 2. Review the comment content and task context
169
+ 3. Reply via comment: `tasks comments add prll://tsk_xxx --body "Response..."`
170
+ 4. If the comment requests status changes, update accordingly
135
171
 
136
172
  CLI success output is JSON; errors print a JSON line plus, on a `PERMISSION_DENIED`, an optional plain-text `Request approval:` line — read both.