@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.
- package/dist/index.bundle.mjs +233 -63
- package/package.json +3 -3
- package/skills/parall-tasks/SKILL.md +43 -7
package/dist/index.bundle.mjs
CHANGED
|
@@ -44537,7 +44537,7 @@ var require_headers = __commonJS({
|
|
|
44537
44537
|
}
|
|
44538
44538
|
}
|
|
44539
44539
|
};
|
|
44540
|
-
var
|
|
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 } =
|
|
44682
|
-
Reflect.deleteProperty(
|
|
44683
|
-
Reflect.deleteProperty(
|
|
44684
|
-
Reflect.deleteProperty(
|
|
44685
|
-
Reflect.deleteProperty(
|
|
44686
|
-
iteratorMixin("Headers",
|
|
44687
|
-
Object.defineProperties(
|
|
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 ===
|
|
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
|
|
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
|
|
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 } =
|
|
44935
|
-
Reflect.deleteProperty(
|
|
44936
|
-
Reflect.deleteProperty(
|
|
44937
|
-
Reflect.deleteProperty(
|
|
44938
|
-
Reflect.deleteProperty(
|
|
44939
|
-
mixinBody(
|
|
44940
|
-
Object.defineProperties(
|
|
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(
|
|
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
|
|
45089
|
+
const response = new Response2(kConstruct);
|
|
45090
45090
|
setResponseState(response, innerResponse);
|
|
45091
|
-
const headers = new
|
|
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(
|
|
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
|
|
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
|
|
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([
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
52943
|
+
res = await sendMultipartRequest({
|
|
52778
52944
|
method,
|
|
52945
|
+
url: `${this.baseUrlFor(path9)}${path9}`,
|
|
52779
52946
|
headers,
|
|
52780
52947
|
body,
|
|
52781
|
-
|
|
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 =
|
|
54090
|
-
|
|
54091
|
-
|
|
54092
|
-
|
|
54093
|
-
|
|
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
|
|
54098
|
-
* author-only).
|
|
54099
|
-
*
|
|
54100
|
-
*
|
|
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 =
|
|
54104
|
-
|
|
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.
|
|
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/
|
|
20
|
-
"@parall/
|
|
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.
|
|
122
|
-
2.
|
|
123
|
-
3.
|
|
124
|
-
4.
|
|
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.
|
|
133
|
-
2.
|
|
134
|
-
3.
|
|
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.
|