@wirecat/bitrix24-cli 0.3.0 → 0.5.0
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/CHANGELOG.md +130 -0
- package/README.md +84 -9
- package/dist/api-keys.d.ts +36 -9
- package/dist/api-keys.d.ts.map +1 -1
- package/dist/api-keys.js +139 -19
- package/dist/api-keys.js.map +1 -1
- package/dist/bin/b24.js +2 -2
- package/dist/bitrix/errors.js +1 -1
- package/dist/bitrix/errors.js.map +1 -1
- package/dist/bitrix/methods.d.ts.map +1 -1
- package/dist/bitrix/methods.js +7 -3
- package/dist/bitrix/methods.js.map +1 -1
- package/dist/bitrix/transport.d.ts +4 -7
- package/dist/bitrix/transport.d.ts.map +1 -1
- package/dist/bitrix/transport.js +29 -19
- package/dist/bitrix/transport.js.map +1 -1
- package/dist/body.d.ts +14 -0
- package/dist/body.d.ts.map +1 -0
- package/dist/body.js +44 -0
- package/dist/body.js.map +1 -0
- package/dist/bundle/{chunk-QIPTIUMJ.js → all-profiles-CANIDIDS.js} +12 -7
- package/dist/bundle/{anthropic-RHRAVHC2.js → anthropic-JUJB4DCF.js} +5 -5
- package/dist/bundle/{app-server-QIT6S7AZ.js → app-server-3V5Z4PTK.js} +68 -54
- package/dist/bundle/b24.js +18 -12
- package/dist/bundle/{bun-H6RSODZ3.js → bun-LKMV5TY7.js} +2 -2
- package/dist/bundle/{bun-sqlite-BO4LTQHX.js → bun-sqlite-S56EF74S.js} +3 -3
- package/dist/bundle/{chunk-D5S6QV6R.js → chunk-2I4KWS3H.js} +6 -6
- package/dist/bundle/chunk-36PO5NWY.js +147 -0
- package/dist/bundle/{chunk-ZIAQPTUS.js → chunk-42F7Q7V6.js} +3 -3
- package/dist/bundle/{chunk-6WY72XVQ.js → chunk-4D3K6GZW.js} +18 -4
- package/dist/bundle/chunk-5D4MJQ6X.js +22 -0
- package/dist/bundle/chunk-5JOPERVF.js +84 -0
- package/dist/bundle/chunk-6A4UPWDC.js +15 -0
- package/dist/bundle/{chunk-P33NDCDI.js → chunk-6MGWIZG4.js} +1 -1
- package/dist/bundle/{chunk-ZDQQCXFG.js → chunk-6YJTNZ7U.js} +13 -13
- package/dist/bundle/{chunk-MBDK4YXG.js → chunk-7FBFJ6B4.js} +4 -2
- package/dist/bundle/chunk-7VCMOTQP.js +55 -0
- package/dist/bundle/{chunk-P364PLIK.js → chunk-A5IMMGYU.js} +36 -34
- package/dist/bundle/{chunk-45AKJVKV.js → chunk-ASEHTBNK.js} +1 -1
- package/dist/bundle/{chunk-HGL63O5V.js → chunk-B6LPJYPQ.js} +2 -2
- package/dist/bundle/{chunk-LSPIOT6Z.js → chunk-BHEE2K6C.js} +7 -7
- package/dist/bundle/chunk-BYZQBE63.js +971 -0
- package/dist/bundle/{program-H3TGGRQ6.js → chunk-COKGNTDQ.js} +15761 -16685
- package/dist/bundle/{chunk-XJXONOB5.js → chunk-DVFYRQGE.js} +1 -1
- package/dist/bundle/{chunk-FLUEXJ4X.js → chunk-DVSIBZ3G.js} +1 -1
- package/dist/bundle/chunk-EJEIXC6Y.js +273 -0
- package/dist/bundle/chunk-EYTGCM44.js +130 -0
- package/dist/bundle/{chunk-IRV2PCQ2.js → chunk-EYYOKT23.js} +26 -26
- package/dist/bundle/{chunk-PH5FZX6E.js → chunk-FCWPIWSR.js} +2 -2
- package/dist/bundle/{chunk-YZ5LHE5Q.js → chunk-FSWRMQWX.js} +2 -2
- package/dist/bundle/{chunk-ADLS6FVG.js → chunk-FXBHOCJK.js} +1 -1
- package/dist/bundle/chunk-G5MW6RCM.js +723 -0
- package/dist/bundle/{chunk-VEWWAGTD.js → chunk-GLTKRLFT.js} +8 -8
- package/dist/bundle/chunk-GUUZQ7NE.js +581 -0
- package/dist/bundle/{chunk-QSNROIJL.js → chunk-H6RIPOOI.js} +42 -9
- package/dist/bundle/{chunk-H2ADPPSH.js → chunk-HGFNC4CR.js} +1819 -597
- package/dist/bundle/{chunk-7GRZAKBB.js → chunk-IERYD2N2.js} +6 -6
- package/dist/bundle/{chunk-N6FLBXZS.js → chunk-IGCLMEMB.js} +3 -3
- package/dist/bundle/{chunk-U5ACMCAQ.js → chunk-J7WCSZ2Q.js} +411 -919
- package/dist/bundle/{chunk-W5YAO5G5.js → chunk-JZYHQ4HB.js} +9 -4
- package/dist/bundle/{chunk-EVYSBZ3I.js → chunk-K4QM3X5F.js} +4 -4
- package/dist/bundle/{chunk-DTXERR44.js → chunk-KFSMY7SZ.js} +2 -2
- package/dist/bundle/{chunk-LRGYKOCP.js → chunk-KPEDH5T4.js} +1 -1
- package/dist/bundle/{chunk-XRFJWHY5.js → chunk-KUY7LII2.js} +4 -4
- package/dist/bundle/{chunk-QC53QBNC.js → chunk-LFXDHLFR.js} +3 -3
- package/dist/bundle/{chunk-CNNEA2M4.js → chunk-LGLT4JB6.js} +3 -3
- package/dist/bundle/{chunk-QGMDQ2PM.js → chunk-LM4OOBAW.js} +3 -3
- package/dist/bundle/chunk-M74BSKMA.js +234 -0
- package/dist/bundle/{chunk-2KCZ7BKW.js → chunk-MMMT6ORT.js} +11 -11
- package/dist/bundle/{chunk-WII44RXN.js → chunk-NGYD6QTE.js} +2 -2
- package/dist/bundle/{chunk-FOTREPNS.js → chunk-NO6QOPVT.js} +10 -19
- package/dist/bundle/chunk-O6XC7DZI.js +804 -0
- package/dist/bundle/chunk-OE3NFB53.js +64 -0
- package/dist/bundle/{chunk-XD4FRDSL.js → chunk-OUMFNB34.js} +13 -149
- package/dist/bundle/{chunk-ZGZT5S6B.js → chunk-P2RQTNVJ.js} +806 -850
- package/dist/bundle/{chunk-RRJNNPR4.js → chunk-PBIBGIZ7.js} +1 -1
- package/dist/bundle/{chunk-EXOOKUEA.js → chunk-Q6VQHTRW.js} +2 -2
- package/dist/bundle/{chunk-TE3FR6MI.js → chunk-QHBCNVUG.js} +5 -5
- package/dist/bundle/{chunk-SGRYYE4X.js → chunk-QNOXAQ6Y.js} +4 -4
- package/dist/bundle/{chunk-QQXH2OPB.js → chunk-R5F2O5GX.js} +15 -272
- package/dist/bundle/{chunk-SFRNX2TI.js → chunk-R5PBSKJL.js} +1 -1
- package/dist/bundle/{chunk-OTD2ZRXD.js → chunk-RS2BARUU.js} +4 -4
- package/dist/bundle/chunk-TG3DSPT5.js +14 -0
- package/dist/bundle/{chunk-BCF7P4FZ.js → chunk-U22JMKUO.js} +6 -125
- package/dist/bundle/chunk-U66Q5TVK.js +106 -0
- package/dist/bundle/{chunk-QMPN6WKD.js → chunk-UCHMQWON.js} +211 -89
- package/dist/bundle/{chunk-POC3V3AO.js → chunk-VMJS7FJZ.js} +526 -467
- package/dist/bundle/{chunk-FZL7F5NR.js → chunk-VMVAQHDC.js} +77 -615
- package/dist/bundle/{chunk-K3UIB6ZF.js → chunk-WWMCJFMT.js} +2 -2
- package/dist/bundle/{chunk-CXL33BFL.js → chunk-XTA5TN3H.js} +1 -1
- package/dist/bundle/{chunk-WTPMJYMD.js → chunk-XUHHBEA7.js} +652 -131
- package/dist/bundle/{chunk-WKRQ44EH.js → chunk-YDZHO4LT.js} +13 -13
- package/dist/bundle/{chunk-2SNUMZ7S.js → chunk-ZKINZFIT.js} +6 -6
- package/dist/bundle/{chunk-HAXNUIGQ.js → chunk-ZSQXSIFQ.js} +89 -39
- package/dist/bundle/{chunk-YYO7D2MO.js → chunk-ZZEHDIEG.js} +58 -54
- package/dist/bundle/command-contract-OQV6H7SR.js +36 -0
- package/dist/bundle/{decode-5ZPLTYV6.js → decode-QSTBX4MG.js} +3 -3
- package/dist/bundle/{echarts-J6LAPIX7.js → echarts-JZELFH2N.js} +2 -2
- package/dist/bundle/{embed-YG5LDHME.js → embed-4RIW2LVH.js} +4 -4
- package/dist/bundle/{embedder-7FNUA5OZ.js → embedder-SW7DTWSL.js} +7 -7
- package/dist/bundle/{first-run-JPZNWIJN.js → first-run-7AISOSOM.js} +8 -8
- package/dist/bundle/first-screen-NMHNFZ2B.js +34 -0
- package/dist/bundle/{instructions-AXWTQHMR.js → instructions-BZE5YUGG.js} +1 -1
- package/dist/bundle/{mcp-7F46P6AM.js → mcp-SDWHDJTY.js} +2 -2
- package/dist/bundle/{node-P4E63KXA.js → node-KM3CUABH.js} +9 -9
- package/dist/bundle/{node-CWKAIOEM.js → node-LTKZIO4U.js} +2 -2
- package/dist/bundle/{node-sqlite-LSEKVRDA.js → node-sqlite-HQ5PN2RH.js} +4 -4
- package/dist/bundle/{oauth-THYNLRLD.js → oauth-UH6FOZQL.js} +5 -5
- package/dist/bundle/{open-E47QYKFC.js → open-TSUP3XGL.js} +3 -3
- package/dist/bundle/{openai-EWSGC3BC.js → openai-GVEE52E3.js} +14 -14
- package/dist/bundle/{process-WKTEA3WE.js → process-AGXY76ZE.js} +1 -1
- package/dist/bundle/program-BI4A4HFJ.js +2247 -0
- package/dist/bundle/{prompt-CAQ7QR3U.js → prompt-NRSUY7FA.js} +3 -3
- package/dist/bundle/{recognize-6KGHNZC3.js → recognize-NPDPQ6PJ.js} +2 -2
- package/dist/bundle/{remote-3UO2WDC3.js → remote-HFASMVLB.js} +5 -5
- package/dist/bundle/{rerank-2JVDPZBX.js → rerank-TL6Z6F7K.js} +5 -5
- package/dist/bundle/{chunk-VL6SPMZV.js → serve-VB4DHDZQ.js} +8 -6
- package/dist/bundle/server-T5EDRPJI.js +68 -0
- package/dist/bundle/{chunk-ZEW4P6AH.js → server-Z6MW6C37.js} +50 -14
- package/dist/bundle/source-4IGO5J7E.js +237 -0
- package/dist/bundle/sqlite-runtime-YS4POY3W.js +17 -0
- package/dist/bundle/{state-7NH5G4XJ.js → state-ISZVVZGR.js} +4 -4
- package/dist/bundle/store-IZJBAKJV.js +58 -0
- package/dist/bundle/{store-7O4JQD2Z.js → store-L76MSQC3.js} +17 -12
- package/dist/bundle/store-PBTIB7BD.js +207 -0
- package/dist/bundle/store-maintenance-command-YFKII7TF.js +58 -0
- package/dist/bundle/writer-3O5EYMFE.js +214 -0
- package/dist/commands/api.d.ts.map +1 -1
- package/dist/commands/api.js +81 -30
- package/dist/commands/api.js.map +1 -1
- package/dist/commands/crm-shared.d.ts +4 -0
- package/dist/commands/crm-shared.d.ts.map +1 -0
- package/dist/commands/crm-shared.js +94 -0
- package/dist/commands/crm-shared.js.map +1 -0
- package/dist/commands/crm-writes.d.ts +0 -1
- package/dist/commands/crm-writes.d.ts.map +1 -1
- package/dist/commands/crm-writes.js +43 -88
- package/dist/commands/crm-writes.js.map +1 -1
- package/dist/commands/crm.d.ts.map +1 -1
- package/dist/commands/crm.js +30 -48
- package/dist/commands/crm.js.map +1 -1
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +1 -0
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/write.d.ts +6 -6
- package/dist/commands/write.d.ts.map +1 -1
- package/dist/commands/write.js +11 -18
- package/dist/commands/write.js.map +1 -1
- package/dist/config.d.ts +0 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -8
- package/dist/config.js.map +1 -1
- package/dist/crm/capabilities.d.ts +7 -0
- package/dist/crm/capabilities.d.ts.map +1 -0
- package/dist/crm/capabilities.js +7 -0
- package/dist/crm/capabilities.js.map +1 -0
- package/dist/crm/conditions.d.ts +1 -1
- package/dist/crm/conditions.d.ts.map +1 -1
- package/dist/crm/conditions.js +4 -6
- package/dist/crm/conditions.js.map +1 -1
- package/dist/crm/custom-query.d.ts +19 -0
- package/dist/crm/custom-query.d.ts.map +1 -0
- package/dist/crm/custom-query.js +79 -0
- package/dist/crm/custom-query.js.map +1 -0
- package/dist/crm/deal.d.ts +4 -27
- package/dist/crm/deal.d.ts.map +1 -1
- package/dist/crm/deal.js +15 -48
- package/dist/crm/deal.js.map +1 -1
- package/dist/crm/fields.d.ts +20 -0
- package/dist/crm/fields.d.ts.map +1 -0
- package/dist/crm/fields.js +78 -0
- package/dist/crm/fields.js.map +1 -0
- package/dist/crm/items.d.ts +7 -1
- package/dist/crm/items.d.ts.map +1 -1
- package/dist/crm/items.js +21 -18
- package/dist/crm/items.js.map +1 -1
- package/dist/crm/lead.d.ts +5 -36
- package/dist/crm/lead.d.ts.map +1 -1
- package/dist/crm/lead.js +15 -61
- package/dist/crm/lead.js.map +1 -1
- package/dist/crm/organization.d.ts +1 -0
- package/dist/crm/organization.d.ts.map +1 -1
- package/dist/crm/person.d.ts +1 -0
- package/dist/crm/person.d.ts.map +1 -1
- package/dist/crm/pipelines.d.ts +5 -0
- package/dist/crm/pipelines.d.ts.map +1 -0
- package/dist/crm/pipelines.js +54 -0
- package/dist/crm/pipelines.js.map +1 -0
- package/dist/crm/product.d.ts.map +1 -1
- package/dist/crm/product.js +2 -2
- package/dist/crm/product.js.map +1 -1
- package/dist/crm/rest3-fields.d.ts +3 -0
- package/dist/crm/rest3-fields.d.ts.map +1 -0
- package/dist/crm/rest3-fields.js +38 -0
- package/dist/crm/rest3-fields.js.map +1 -0
- package/dist/crm/source.d.ts +15 -0
- package/dist/crm/source.d.ts.map +1 -0
- package/dist/crm/source.js +122 -0
- package/dist/crm/source.js.map +1 -0
- package/dist/crm/user.d.ts.map +1 -1
- package/dist/crm/user.js +2 -2
- package/dist/crm/user.js.map +1 -1
- package/dist/crm/values.d.ts +26 -5
- package/dist/crm/values.d.ts.map +1 -1
- package/dist/crm/values.js +40 -5
- package/dist/crm/values.js.map +1 -1
- package/dist/crm/writer.d.ts +9 -0
- package/dist/crm/writer.d.ts.map +1 -0
- package/dist/crm/writer.js +119 -0
- package/dist/crm/writer.js.map +1 -0
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +53 -5
- package/dist/program.js.map +1 -1
- package/dist/reasons.d.ts.map +1 -1
- package/dist/reasons.js +6 -1
- package/dist/reasons.js.map +1 -1
- package/dist/store.d.ts +15 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +33 -0
- package/dist/store.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -6
- package/skills/bitrix24-cli/SKILL.md +16 -10
- package/dist/bundle/all-profiles-QJ444GSX.js +0 -24
- package/dist/bundle/chunk-XNHSPHUN.js +0 -48
- package/dist/bundle/command-contract-OKQOE6G4.js +0 -30
- package/dist/bundle/first-screen-VQM4MTS7.js +0 -28
- package/dist/bundle/mcp-5RSWNTHS.js +0 -160
- package/dist/bundle/mcp-J5R5A65I.js +0 -87
- package/dist/bundle/serve-ES7AG5IK.js +0 -19
- package/dist/bundle/server-5LE5LNUQ.js +0 -45
- package/dist/bundle/server-BU4VBM6S.js +0 -58
- package/dist/bundle/store-maintenance-command-UDVGEY2D.js +0 -47
- package/dist/commands/doctor.d.ts +0 -77
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js +0 -74
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/mcp.d.ts +0 -3
- package/dist/commands/mcp.d.ts.map +0 -1
- package/dist/commands/mcp.js +0 -97
- package/dist/commands/mcp.js.map +0 -1
- package/dist/crm/pipeline.d.ts +0 -17
- package/dist/crm/pipeline.d.ts.map +0 -1
- package/dist/crm/pipeline.js +0 -42
- package/dist/crm/pipeline.js.map +0 -1
- package/dist/crm/stage.d.ts +0 -20
- package/dist/crm/stage.d.ts.map +0 -1
- package/dist/crm/stage.js +0 -65
- package/dist/crm/stage.js.map +0 -1
- package/dist/mcp.d.ts +0 -29
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js +0 -99
- package/dist/mcp.js.map +0 -1
- /package/dist/bundle/{chunk-4PDYYS5K.js → chunk-ZQ3GWKDQ.js} +0 -0
|
@@ -2,12 +2,12 @@ import { createRequire as __bundleRequire } from "node:module";
|
|
|
2
2
|
const require = __bundleRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
CliError
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-EYYOKT23.js";
|
|
6
6
|
import {
|
|
7
7
|
__name
|
|
8
8
|
} from "./chunk-ZVVMGPBJ.js";
|
|
9
9
|
|
|
10
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
10
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/search/languages.js
|
|
11
11
|
var LANGUAGES = [
|
|
12
12
|
{ name: "russian", code: "ru", label: "Russian", script: "cyrillic", dictionary: "dictionary-ru" },
|
|
13
13
|
{ name: "english", code: "en", label: "English", script: "latin", dictionary: "dictionary-en" },
|
|
@@ -15,12 +15,12 @@ var LANGUAGES = [
|
|
|
15
15
|
];
|
|
16
16
|
var languagesOf = /* @__PURE__ */ __name((script) => LANGUAGES.filter((one) => one.script === script).map(({ name }) => name), "languagesOf");
|
|
17
17
|
|
|
18
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
18
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/store/normalize.js
|
|
19
19
|
var NORMALIZER_VERSION = 1;
|
|
20
20
|
var fold = /* @__PURE__ */ __name((text) => text.normalize("NFKD").replace(new RegExp("\\p{M}+", "gu"), "").normalize("NFC").toLowerCase(), "fold");
|
|
21
21
|
var normalize = /* @__PURE__ */ __name((text) => fold(text).replace(new RegExp("\\p{Cc}", "gu"), " ").replace(/\s+/gu, " ").trim(), "normalize");
|
|
22
22
|
|
|
23
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
23
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/search/snowball/base-stemmer.js
|
|
24
24
|
var BaseStemmer = class {
|
|
25
25
|
static {
|
|
26
26
|
__name(this, "BaseStemmer");
|
|
@@ -395,7 +395,7 @@ var BaseStemmer = class {
|
|
|
395
395
|
}
|
|
396
396
|
};
|
|
397
397
|
|
|
398
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
398
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/search/snowball/english-stemmer.js
|
|
399
399
|
var a_0 = [
|
|
400
400
|
["arsen", -1],
|
|
401
401
|
["commun", -1],
|
|
@@ -1096,7 +1096,7 @@ var english_stemmer_default = class extends BaseStemmer {
|
|
|
1096
1096
|
stemWord = this.stem;
|
|
1097
1097
|
};
|
|
1098
1098
|
|
|
1099
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
1099
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/search/snowball/russian-stemmer.js
|
|
1100
1100
|
var a_02 = [
|
|
1101
1101
|
["\u0432", 1],
|
|
1102
1102
|
["\u0438\u0432", 2, 1],
|
|
@@ -1519,7 +1519,7 @@ var russian_stemmer_default = class extends BaseStemmer {
|
|
|
1519
1519
|
stemWord = this.stem;
|
|
1520
1520
|
};
|
|
1521
1521
|
|
|
1522
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
1522
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/search/snowball/spanish-stemmer.js
|
|
1523
1523
|
var a_03 = [
|
|
1524
1524
|
["", 6],
|
|
1525
1525
|
["\xE1", 1, 1],
|
|
@@ -2195,7 +2195,7 @@ var spanish_stemmer_default = class extends BaseStemmer {
|
|
|
2195
2195
|
stemWord = this.stem;
|
|
2196
2196
|
};
|
|
2197
2197
|
|
|
2198
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
2198
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/search/stem.js
|
|
2199
2199
|
var SNOWBALL_VERSION = "3.1.1";
|
|
2200
2200
|
var CYRILLIC_STEMMERS = [...languagesOf("cyrillic"), "none"];
|
|
2201
2201
|
var LATIN_STEMMERS = [...languagesOf("latin"), "none"];
|
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
import { createRequire as __bundleRequire } from "node:module";
|
|
2
|
+
const require = __bundleRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
LOG_ATTRIBUTES,
|
|
5
|
+
MESSENGER_CHANGE_REFUSAL,
|
|
6
|
+
currentRun,
|
|
7
|
+
fromLogAttributes,
|
|
8
|
+
logAttributes,
|
|
9
|
+
readOnlyRefusal
|
|
10
|
+
} from "./chunk-G5MW6RCM.js";
|
|
11
|
+
import {
|
|
12
|
+
CEILING_KEY,
|
|
13
|
+
keyForWrite,
|
|
14
|
+
levelFor,
|
|
15
|
+
skipFlagFor
|
|
16
|
+
} from "./chunk-OUMFNB34.js";
|
|
17
|
+
import {
|
|
18
|
+
CliError,
|
|
19
|
+
logRecordOf,
|
|
20
|
+
realSleep,
|
|
21
|
+
resolvePaths,
|
|
22
|
+
writeSecurely
|
|
23
|
+
} from "./chunk-EYYOKT23.js";
|
|
24
|
+
import {
|
|
25
|
+
__name
|
|
26
|
+
} from "./chunk-ZVVMGPBJ.js";
|
|
27
|
+
|
|
28
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/sends/guard.js
|
|
29
|
+
import { randomUUID } from "node:crypto";
|
|
30
|
+
|
|
31
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/sends/flood.js
|
|
32
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
33
|
+
import { dirname, join } from "node:path";
|
|
34
|
+
var MOST_DEADLINES = 50;
|
|
35
|
+
var LIMITED_HOLD_MS = 60 * 60 * 1e3;
|
|
36
|
+
var FROZEN_HOLD_MS = 24 * 60 * 60 * 1e3;
|
|
37
|
+
var NO_END = "9999-12-31T23:59:59.999Z";
|
|
38
|
+
var holdEnd = /* @__PURE__ */ __name((block, show = (iso) => iso) => block.until === null ? "until lifted" : `until ${show(block.until)}`, "holdEnd");
|
|
39
|
+
var floodPathFor = /* @__PURE__ */ __name((app, profile, env = process.env) => join(resolvePaths({ appName: app.appName, prefix: app.envPrefix, env }).state, "flood", `${profile}.json`), "floodPathFor");
|
|
40
|
+
var FloodMemory = class {
|
|
41
|
+
static {
|
|
42
|
+
__name(this, "FloodMemory");
|
|
43
|
+
}
|
|
44
|
+
path;
|
|
45
|
+
now;
|
|
46
|
+
constructor(path, now = Date.now) {
|
|
47
|
+
this.path = path;
|
|
48
|
+
this.now = now;
|
|
49
|
+
}
|
|
50
|
+
/** What is still in force; anything expired is left out. */
|
|
51
|
+
read() {
|
|
52
|
+
const now = this.now();
|
|
53
|
+
let raw;
|
|
54
|
+
try {
|
|
55
|
+
raw = JSON.parse(readFileSync(this.path, "utf8"));
|
|
56
|
+
} catch {
|
|
57
|
+
return { deadlines: [] };
|
|
58
|
+
}
|
|
59
|
+
const alive = /* @__PURE__ */ __name((until) => typeof until === "string" && Date.parse(until) > now, "alive");
|
|
60
|
+
const deadlines = Array.isArray(raw.deadlines) ? raw.deadlines.filter((one) => typeof one?.operation === "string" && alive(one.until)) : [];
|
|
61
|
+
const block = raw.sendBlock && (raw.sendBlock.until === NO_END ? { ...raw.sendBlock, until: null } : raw.sendBlock);
|
|
62
|
+
const held = block && (block.until === null || alive(block.until));
|
|
63
|
+
return { deadlines, ...held ? { sendBlock: block } : {} };
|
|
64
|
+
}
|
|
65
|
+
/** The deadline this call is still under: one for its chat, or one for the call in every chat. */
|
|
66
|
+
owed(operation, chatId) {
|
|
67
|
+
return this.read().deadlines.filter((one) => one.operation === operation && (one.chatId === void 0 || one.chatId === chatId)).sort((a, b) => b.until.localeCompare(a.until))[0];
|
|
68
|
+
}
|
|
69
|
+
remember(deadline) {
|
|
70
|
+
const { waitMs, ...rest } = deadline;
|
|
71
|
+
const kept = { ...rest, until: new Date(this.now() + waitMs).toISOString() };
|
|
72
|
+
const state = this.read();
|
|
73
|
+
const others = state.deadlines.filter((one) => one.operation !== kept.operation || one.chatId !== kept.chatId);
|
|
74
|
+
const deadlines = [...others, kept].sort((a, b) => b.until.localeCompare(a.until)).slice(0, MOST_DEADLINES);
|
|
75
|
+
this.#write({ ...state, deadlines });
|
|
76
|
+
return kept;
|
|
77
|
+
}
|
|
78
|
+
sendBlock() {
|
|
79
|
+
return this.read().sendBlock;
|
|
80
|
+
}
|
|
81
|
+
/** A ban the messenger gave no end for holds until lifted; a spam limit or a freeze without one, for a while. */
|
|
82
|
+
block(block) {
|
|
83
|
+
const now = this.now();
|
|
84
|
+
const holdMs = { limited: LIMITED_HOLD_MS, frozen: FROZEN_HOLD_MS, banned: void 0 }[block.state];
|
|
85
|
+
const kept = {
|
|
86
|
+
...block,
|
|
87
|
+
since: new Date(now).toISOString(),
|
|
88
|
+
until: block.until ?? (holdMs === void 0 ? null : new Date(now + holdMs).toISOString())
|
|
89
|
+
};
|
|
90
|
+
this.#write({ ...this.read(), sendBlock: kept });
|
|
91
|
+
return kept;
|
|
92
|
+
}
|
|
93
|
+
/** Lifts only a block of this state: an account found not frozen may still be limited for spam. */
|
|
94
|
+
unblock(state) {
|
|
95
|
+
const { sendBlock, ...rest } = this.read();
|
|
96
|
+
if (sendBlock?.state === state)
|
|
97
|
+
this.#write(rest);
|
|
98
|
+
}
|
|
99
|
+
/** Forgets every wait and lifts the hold, and answers with what was still in force. */
|
|
100
|
+
clear() {
|
|
101
|
+
const cleared = this.read();
|
|
102
|
+
this.#write({ deadlines: [] });
|
|
103
|
+
return cleared;
|
|
104
|
+
}
|
|
105
|
+
#write({ sendBlock, ...rest }) {
|
|
106
|
+
const state = sendBlock ? { ...rest, sendBlock: { ...sendBlock, until: sendBlock.until ?? NO_END } } : rest;
|
|
107
|
+
mkdirSync(dirname(this.path), { recursive: true, mode: 448 });
|
|
108
|
+
const temporary = `${this.path}.${process.pid}.tmp`;
|
|
109
|
+
writeFileSync(temporary, `${JSON.stringify(state)}
|
|
110
|
+
`, { mode: 384 });
|
|
111
|
+
renameSync(temporary, this.path);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/sends/journal.js
|
|
116
|
+
import { appendFileSync, mkdirSync as mkdirSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
117
|
+
import { dirname as dirname3, join as join2 } from "node:path";
|
|
118
|
+
|
|
119
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/sends/file-lock.js
|
|
120
|
+
import { closeSync, mkdirSync as mkdirSync2, openSync, statSync, unlinkSync } from "node:fs";
|
|
121
|
+
import { dirname as dirname2 } from "node:path";
|
|
122
|
+
var LOCK_WAIT_MS = 5e3;
|
|
123
|
+
var LOCK_STALE_MS = 3e4;
|
|
124
|
+
var RETRY_MS = 20;
|
|
125
|
+
var pause = new Int32Array(new SharedArrayBuffer(4));
|
|
126
|
+
var withFileLock = /* @__PURE__ */ __name((path, what, body, waitMs = LOCK_WAIT_MS) => {
|
|
127
|
+
const lock = lockFor(path);
|
|
128
|
+
const deadline = Date.now() + waitMs;
|
|
129
|
+
while (!taken(lock)) {
|
|
130
|
+
if (Date.now() >= deadline)
|
|
131
|
+
throw lockTimeout(what, waitMs, lock);
|
|
132
|
+
Atomics.wait(pause, 0, 0, RETRY_MS);
|
|
133
|
+
}
|
|
134
|
+
return holding(lock, body);
|
|
135
|
+
}, "withFileLock");
|
|
136
|
+
var withFileLockAsync = /* @__PURE__ */ __name(async (path, what, body, waitMs = LOCK_WAIT_MS, sleep = realSleep) => {
|
|
137
|
+
const lock = lockFor(path);
|
|
138
|
+
const deadline = Date.now() + waitMs;
|
|
139
|
+
while (!taken(lock)) {
|
|
140
|
+
if (Date.now() >= deadline)
|
|
141
|
+
throw lockTimeout(what, waitMs, lock);
|
|
142
|
+
await sleep(RETRY_MS);
|
|
143
|
+
}
|
|
144
|
+
return holding(lock, body);
|
|
145
|
+
}, "withFileLockAsync");
|
|
146
|
+
var lockFor = /* @__PURE__ */ __name((path) => {
|
|
147
|
+
mkdirSync2(dirname2(path), { recursive: true, mode: 448 });
|
|
148
|
+
return `${path}.lock`;
|
|
149
|
+
}, "lockFor");
|
|
150
|
+
var taken = /* @__PURE__ */ __name((lock) => {
|
|
151
|
+
for (; ; ) {
|
|
152
|
+
try {
|
|
153
|
+
closeSync(openSync(lock, "wx", 384));
|
|
154
|
+
return true;
|
|
155
|
+
} catch (error) {
|
|
156
|
+
if (error.code !== "EEXIST")
|
|
157
|
+
throw error;
|
|
158
|
+
if (Date.now() - lockTime(lock) <= LOCK_STALE_MS)
|
|
159
|
+
return false;
|
|
160
|
+
try {
|
|
161
|
+
unlinkSync(lock);
|
|
162
|
+
} catch {
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}, "taken");
|
|
167
|
+
var holding = /* @__PURE__ */ __name((lock, body) => {
|
|
168
|
+
try {
|
|
169
|
+
return body();
|
|
170
|
+
} finally {
|
|
171
|
+
try {
|
|
172
|
+
unlinkSync(lock);
|
|
173
|
+
} catch {
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}, "holding");
|
|
177
|
+
var lockTimeout = /* @__PURE__ */ __name((what, waitMs, lock) => new CliError("timeout", `${what} stayed locked for ${waitMs / 1e3}s (${lock})`), "lockTimeout");
|
|
178
|
+
var lockTime = /* @__PURE__ */ __name((lock) => {
|
|
179
|
+
try {
|
|
180
|
+
return statSync(lock).mtimeMs;
|
|
181
|
+
} catch {
|
|
182
|
+
return Date.now();
|
|
183
|
+
}
|
|
184
|
+
}, "lockTime");
|
|
185
|
+
|
|
186
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/sends/journal.js
|
|
187
|
+
var sendsPathFor = /* @__PURE__ */ __name((app, profile, env = process.env) => join2(resolvePaths({ appName: app.appName, prefix: app.envPrefix, env }).state, "sends", `${profile}.jsonl`), "sendsPathFor");
|
|
188
|
+
var SendJournal = class {
|
|
189
|
+
static {
|
|
190
|
+
__name(this, "SendJournal");
|
|
191
|
+
}
|
|
192
|
+
path;
|
|
193
|
+
resource;
|
|
194
|
+
constructor(path, resource = { service: "unknown", version: "unknown" }) {
|
|
195
|
+
this.path = path;
|
|
196
|
+
this.resource = resource;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Runs `body` with the journal to itself, across processes: two sends at the limit must not both
|
|
200
|
+
* read "one left". A lock file opened with `wx`, because `flock` is not there on Windows.
|
|
201
|
+
*/
|
|
202
|
+
locked(body) {
|
|
203
|
+
return withFileLock(this.path, "the send journal", body);
|
|
204
|
+
}
|
|
205
|
+
/** `locked` without blocking the thread while another process holds the journal: what `serve` uses. */
|
|
206
|
+
lockedAsync(body) {
|
|
207
|
+
return withFileLockAsync(this.path, "the send journal", body);
|
|
208
|
+
}
|
|
209
|
+
append(entry) {
|
|
210
|
+
const { at, ...attributes } = entry;
|
|
211
|
+
const { runId, command, traceId } = currentRun();
|
|
212
|
+
const record = logRecordOf({
|
|
213
|
+
severity: entry.outcome === "sent" || entry.outcome === "reserved" ? "info" : "warn",
|
|
214
|
+
event: logAttributes({ event: "send.recorded", ...attributes }),
|
|
215
|
+
time: at,
|
|
216
|
+
runId,
|
|
217
|
+
...traceId === void 0 ? {} : { traceId },
|
|
218
|
+
command,
|
|
219
|
+
resource: this.resource,
|
|
220
|
+
allow: LOG_ATTRIBUTES
|
|
221
|
+
});
|
|
222
|
+
mkdirSync3(dirname3(this.path), { recursive: true, mode: 448 });
|
|
223
|
+
appendFileSync(this.path, `${JSON.stringify(record)}
|
|
224
|
+
`, { mode: 384 });
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Oldest first, each reservation folded into its outcome; one with no outcome yet is in flight,
|
|
228
|
+
* or its process died. A line that does not parse is skipped: a torn last write must not block sending.
|
|
229
|
+
*/
|
|
230
|
+
entries(filter) {
|
|
231
|
+
const lines = this.#lines();
|
|
232
|
+
const settled = new Set(lines.filter((entry) => entry.outcome !== "reserved").map((entry) => entry.reservation));
|
|
233
|
+
const entries = lines.filter((entry) => entry.outcome !== "reserved" || !settled.has(entry.reservation)).map(({ reservation, ...entry }) => entry.outcome === "reserved" ? { ...entry, reservation } : entry).map(withSendId);
|
|
234
|
+
return filter === void 0 ? entries : entries.filter((entry) => (filter.outcome === void 0 || entry.outcome === filter.outcome) && (filter.chatId === void 0 || entry.chatId === filter.chatId) && (filter.operationId === void 0 || entry.operationId === filter.operationId) && (filter.errorCode === void 0 || entry.errorCode === filter.errorCode) && (filter.key === void 0 || entry.key === filter.key));
|
|
235
|
+
}
|
|
236
|
+
#lines() {
|
|
237
|
+
let text;
|
|
238
|
+
try {
|
|
239
|
+
text = readFileSync2(this.path, "utf8");
|
|
240
|
+
} catch {
|
|
241
|
+
return [];
|
|
242
|
+
}
|
|
243
|
+
return text.split("\n").filter((line) => line.trim() !== "").flatMap((line) => {
|
|
244
|
+
try {
|
|
245
|
+
return [entryOf(JSON.parse(line))];
|
|
246
|
+
} catch {
|
|
247
|
+
return [];
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
var entryOf = /* @__PURE__ */ __name((line) => {
|
|
253
|
+
if (!("attributes" in line))
|
|
254
|
+
return line;
|
|
255
|
+
const { event: _, ...attributes } = line.attributes;
|
|
256
|
+
return { at: line.time, ...fromLogAttributes(attributes) };
|
|
257
|
+
}, "entryOf");
|
|
258
|
+
var withSendId = /* @__PURE__ */ __name((entry) => {
|
|
259
|
+
const { cid, ...rest } = entry;
|
|
260
|
+
return cid === void 0 || rest.sendId !== void 0 ? rest : { ...rest, sendId: String(cid) };
|
|
261
|
+
}, "withSendId");
|
|
262
|
+
|
|
263
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/sends/recipients.js
|
|
264
|
+
import { existsSync, readFileSync as readFileSync3, rmSync } from "node:fs";
|
|
265
|
+
import { join as join3 } from "node:path";
|
|
266
|
+
var recipientsPathFor = /* @__PURE__ */ __name((app, profile, env = process.env) => join3(resolvePaths({ appName: app.appName, prefix: app.envPrefix, env }).state, "profiles", `${profile}.recipients.json`), "recipientsPathFor");
|
|
267
|
+
var RecipientList = class {
|
|
268
|
+
static {
|
|
269
|
+
__name(this, "RecipientList");
|
|
270
|
+
}
|
|
271
|
+
path;
|
|
272
|
+
command;
|
|
273
|
+
lockWaitMs;
|
|
274
|
+
/** `command` names the program in the hint that turns the list off. */
|
|
275
|
+
constructor(path, command, lockWaitMs) {
|
|
276
|
+
this.path = path;
|
|
277
|
+
this.command = command;
|
|
278
|
+
this.lockWaitMs = lockWaitMs;
|
|
279
|
+
}
|
|
280
|
+
/** `undefined` when the list is off. A file that cannot be read refuses rather than opening up. */
|
|
281
|
+
read() {
|
|
282
|
+
if (!existsSync(this.path))
|
|
283
|
+
return void 0;
|
|
284
|
+
try {
|
|
285
|
+
const parsed = JSON.parse(readFileSync3(this.path, "utf8"));
|
|
286
|
+
if (!Array.isArray(parsed.chats))
|
|
287
|
+
throw new Error("no `chats` array");
|
|
288
|
+
return parsed.chats;
|
|
289
|
+
} catch (error) {
|
|
290
|
+
throw new CliError("configuration_error", `the recipient list ${this.path} cannot be read (${error instanceof Error ? error.message : String(error)}) \u2014 fix the file or turn the list off with \`${this.command} recipients clear\``);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
list(filter = {}) {
|
|
294
|
+
const chats = this.read();
|
|
295
|
+
return {
|
|
296
|
+
state: chats === void 0 ? "off" : chats.length === 0 ? "empty" : "on",
|
|
297
|
+
items: (chats ?? []).filter((chat) => (filter.id === void 0 || chat.id === filter.id) && (filter.title === void 0 || chat.title?.toLocaleLowerCase() === filter.title.toLocaleLowerCase()))
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
/** Whether it was new. Adding one again fills in a partner an older entry was stored without. */
|
|
301
|
+
add(recipient) {
|
|
302
|
+
return this.#locked(() => this.#added(recipient));
|
|
303
|
+
}
|
|
304
|
+
/** `add` waiting for the lock on timers: `recipients add` connects, so it runs inside `serve` when one holds the account. */
|
|
305
|
+
addAsync(recipient) {
|
|
306
|
+
return withFileLockAsync(this.path, "the recipient list", () => this.#added(recipient), this.lockWaitMs);
|
|
307
|
+
}
|
|
308
|
+
#added(recipient) {
|
|
309
|
+
const chats = this.read() ?? [];
|
|
310
|
+
const known = chats.find((chat) => chat.id === recipient.id);
|
|
311
|
+
if (known) {
|
|
312
|
+
if (recipient.partnerId && !known.partnerId) {
|
|
313
|
+
this.#write(chats.map((chat) => chat === known ? { ...known, partnerId: recipient.partnerId } : chat));
|
|
314
|
+
}
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
this.#write([...chats, recipient]);
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
/** The id or the title as it was stored; `undefined` when neither matched. */
|
|
321
|
+
remove(reference) {
|
|
322
|
+
return this.#locked(() => {
|
|
323
|
+
const chats = this.read() ?? [];
|
|
324
|
+
const wanted = reference.trim();
|
|
325
|
+
const gone = chats.find((chat) => chat.id === wanted) ?? chats.find((chat) => chat.title?.toLocaleLowerCase() === wanted.toLocaleLowerCase());
|
|
326
|
+
if (gone)
|
|
327
|
+
this.#write(chats.filter((chat) => chat !== gone));
|
|
328
|
+
return gone;
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* The chat the messenger now names `to`: its entry, and a partner of that id, follow it. Only an entry already there
|
|
333
|
+
* changes, and no list is created, so the list never opens up. Whether anything changed.
|
|
334
|
+
*/
|
|
335
|
+
async rekey(from, to) {
|
|
336
|
+
if (from === to)
|
|
337
|
+
return false;
|
|
338
|
+
return withFileLockAsync(this.path, "the recipient list", () => {
|
|
339
|
+
const chats = this.read();
|
|
340
|
+
if (!chats?.some((chat) => chat.id === from || chat.partnerId === from))
|
|
341
|
+
return false;
|
|
342
|
+
const held = chats.some((chat) => chat.id === to);
|
|
343
|
+
this.#write(chats.filter((chat) => !(held && chat.id === from)).map((chat) => ({
|
|
344
|
+
...chat,
|
|
345
|
+
...chat.id === from ? { id: to } : {},
|
|
346
|
+
...chat.partnerId === from ? { partnerId: to } : {}
|
|
347
|
+
})));
|
|
348
|
+
return true;
|
|
349
|
+
}, this.lockWaitMs);
|
|
350
|
+
}
|
|
351
|
+
/** Whether there was a list to turn off. */
|
|
352
|
+
off() {
|
|
353
|
+
return this.#locked(() => {
|
|
354
|
+
if (!existsSync(this.path))
|
|
355
|
+
return false;
|
|
356
|
+
rmSync(this.path);
|
|
357
|
+
return true;
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Every change reads and writes under one lock: a `serve` re-keying while the owner removes a chat must not write
|
|
362
|
+
* the removed chat back. A lock held too long refuses the change and leaves the list as it was. Blocks the thread
|
|
363
|
+
* while it waits: for callers that cannot be async, and `recipients remove` and `clear`, which never
|
|
364
|
+
* connect and so never run inside `serve`.
|
|
365
|
+
*/
|
|
366
|
+
#locked(body) {
|
|
367
|
+
return withFileLock(this.path, "the recipient list", body, this.lockWaitMs);
|
|
368
|
+
}
|
|
369
|
+
#write(chats) {
|
|
370
|
+
writeSecurely(this.path, `${JSON.stringify({ chats }, null, 2)}
|
|
371
|
+
`, 384);
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.601.0_@wirecat+cli-base@0.80.9_commander@15.0.0_esbuild@0.28.2_type_4fddd50439ae4e4f952967ea26554e7b/node_modules/@wirecat/cli-core/dist/sends/guard.js
|
|
376
|
+
var HOUR_MS = 60 * 60 * 1e3;
|
|
377
|
+
var READS_UNDER_HOLD = /* @__PURE__ */ new Set([
|
|
378
|
+
"attachments.extract",
|
|
379
|
+
"conversations.embeddings",
|
|
380
|
+
"conversations.links",
|
|
381
|
+
"messages.server-search",
|
|
382
|
+
"messages.sync-first",
|
|
383
|
+
"stats.contacts.top.sync-first",
|
|
384
|
+
"stats.messages.counters.sync",
|
|
385
|
+
"stats.messages.show.sync-first",
|
|
386
|
+
"stats.messages.top.sync-first",
|
|
387
|
+
"store.gaps.repair"
|
|
388
|
+
]);
|
|
389
|
+
var countsTowardLimit = /* @__PURE__ */ __name(({ kind = "message", action, notify }) => kind === "message" || kind === "forward" || kind === "edit" || kind === "delete" || kind === "pin" && notify === true || action === "create" || action === "members.add" || action === "requests.accept" || action === "join" || action === "contact-import", "countsTowardLimit");
|
|
390
|
+
var weightOf = /* @__PURE__ */ __name(({ kind = "message", action, count, people }) => kind === "delete" || kind === "message" && action === void 0 ? Math.max(1, count ?? 1) : action === "create" || action === "members.add" || action === "requests.accept" || action === "contact-import" ? Math.max(1, people ?? count ?? 1) : 1, "weightOf");
|
|
391
|
+
var timeOf = /* @__PURE__ */ __name((entry) => Date.parse(entry.scheduledFor ?? entry.at), "timeOf");
|
|
392
|
+
var ceilingRefusal = /* @__PURE__ */ __name((key, command) => new CliError("permission_error", `${key} is not allowed: setup's answer keeps every WireCat tool read-only; the owner changes it at a terminal with \`${command} setup\``, { permission: key }), "ceilingRefusal");
|
|
393
|
+
var levelRefusal = /* @__PURE__ */ __name((refused, fix = `${refused.command} ${refused.profile} config set permissions.${refused.key} allow`) => refused.named === CEILING_KEY ? ceilingRefusal(refused.key, refused.command) : new CliError("permission_error", `profile ${refused.profile} does not let ${refused.key} write (permissions.${refused.named} is ${refused.level}, from the ${refused.permissionSources[refused.named ?? ""] ?? "default"}); to allow it: ${fix}`, { permission: refused.key }), "levelRefusal");
|
|
394
|
+
var sendGuard = /* @__PURE__ */ __name(({ profile, recipients, command = recipients.command, readOnlyLock, permissions, permissionSources = {}, permissionDefaults, permissionFix, ask = refuseToAsk, sendsPerHour, journal, flood, warn, now = /* @__PURE__ */ __name(() => /* @__PURE__ */ new Date(), "now") }) => {
|
|
395
|
+
const currentPermissions = /* @__PURE__ */ __name(() => typeof permissions === "function" ? permissions() : permissions, "currentPermissions");
|
|
396
|
+
let reservation;
|
|
397
|
+
const answered = /* @__PURE__ */ new WeakSet();
|
|
398
|
+
const refuseReadOnly = /* @__PURE__ */ __name(() => {
|
|
399
|
+
if (readOnlyLock)
|
|
400
|
+
throw readOnlyRefusal(readOnlyLock, MESSENGER_CHANGE_REFUSAL);
|
|
401
|
+
}, "refuseReadOnly");
|
|
402
|
+
const refuseHeld = /* @__PURE__ */ __name(({ key }) => {
|
|
403
|
+
if (key !== void 0 && READS_UNDER_HOLD.has(key))
|
|
404
|
+
return;
|
|
405
|
+
const block = flood?.sendBlock();
|
|
406
|
+
if (!block)
|
|
407
|
+
return;
|
|
408
|
+
throw new CliError("permission_error", `profile ${profile} holds its writes ${holdEnd(block)}: ${block.hint} \u2014 reads still work; do not retry: the owner checks the account with \`${command} ${profile} doctor --online\`, and lifts the hold with \`${command} ${profile} flood clear\` once it is over`, { sendBlock: block, standing: { state: block.state, hint: block.hint } });
|
|
409
|
+
}, "refuseHeld");
|
|
410
|
+
const permitted = /* @__PURE__ */ __name((request) => {
|
|
411
|
+
const { chatId, kind = "message", action, personIds } = request;
|
|
412
|
+
refuseReadOnly();
|
|
413
|
+
const levels = currentPermissions();
|
|
414
|
+
if (levels !== void 0) {
|
|
415
|
+
const key = request.key ?? keyForWrite(kind, action);
|
|
416
|
+
const { level, key: named } = levelFor(levels, key, permissionDefaults);
|
|
417
|
+
if (level === "deny" || level === "readonly")
|
|
418
|
+
throw levelRefusal({ profile, command, key, level, named, permissionSources }, permissionFix?.(request, key));
|
|
419
|
+
if (level === "ask" && !answered.has(request)) {
|
|
420
|
+
throw new CliError("confirmation_required", `${key} asks before it acts, and it was not asked`);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
const allowed = recipients.read();
|
|
424
|
+
if (chatId !== null && allowed && !allowed.some((chat) => chat.id === chatId)) {
|
|
425
|
+
throw new CliError("confirmation_required", `chat ${chatId} is not on the recipient list of profile ${profile} \u2014 the owner adds it with \`${command} ${profile} recipients add ${chatId}\``, { chat_id: chatId });
|
|
426
|
+
}
|
|
427
|
+
const strangers = allowed ? (personIds ?? []).filter((id) => !allowed.some((chat) => chat.partnerId === id)) : [];
|
|
428
|
+
if (strangers.length > 0) {
|
|
429
|
+
throw new CliError("confirmation_required", `${strangers.join(", ")} ${strangers.length === 1 ? "is" : "are"} not on the recipient list of profile ${profile} \u2014 the owner adds the one-to-one chat with each person (\`${command} ${profile} recipients add <chat>\`); a chat added to the list earlier is added again to be recognised`, { person_ids: strangers });
|
|
430
|
+
}
|
|
431
|
+
}, "permitted");
|
|
432
|
+
const withinLimit = /* @__PURE__ */ __name((request, entries) => {
|
|
433
|
+
const { chatId, sendId } = request;
|
|
434
|
+
const asked = { ...request, people: request.personIds?.length ?? request.count };
|
|
435
|
+
const count = weightOf(asked);
|
|
436
|
+
if (count > sendsPerHour) {
|
|
437
|
+
throw new CliError("rate_limited", `${count} at once is more than the hourly limit of profile ${profile} (sendsPerHour ${sendsPerHour}) \u2014 do fewer at a time`);
|
|
438
|
+
}
|
|
439
|
+
const at = request.scheduledFor ? Date.parse(request.scheduledFor) : now().getTime();
|
|
440
|
+
const counted = entries.filter(countsTowardLimit).filter((entry) => entry.outcome === "sent" || entry.outcome === "outcome_unknown" || entry.outcome === "reserved").filter((entry) => Math.abs(timeOf(entry) - at) < HOUR_MS);
|
|
441
|
+
const unsure = /* @__PURE__ */ __name((entry) => entry.outcome === "outcome_unknown", "unsure");
|
|
442
|
+
const same = /* @__PURE__ */ __name((a, b) => a.sendId !== void 0 && a.sendId === b.sendId && a.chatId === b.chatId, "same");
|
|
443
|
+
const last = [...counted].reverse().find((entry) => same(entry, { chatId, sendId }));
|
|
444
|
+
if (sendId !== void 0 && last && unsure(last)) {
|
|
445
|
+
if (last.sendAs !== request.sendAs) {
|
|
446
|
+
throw new CliError("validation_error", "this send id was tried under another identity; repeat it with the same --send-as, or it may post twice", { operation_id: sendId, retryable: false });
|
|
447
|
+
}
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
const recent = counted.filter((entry, index) => !(unsure(entry) && counted.slice(index + 1).some((later) => same(later, entry)))).map((entry) => ({ time: timeOf(entry), weight: weightOf(entry) })).sort((a, b) => a.time - b.time);
|
|
451
|
+
const used = recent.reduce((sum, { weight }) => sum + weight, 0);
|
|
452
|
+
if (used + count > sendsPerHour) {
|
|
453
|
+
let freed = 0;
|
|
454
|
+
const opening = recent.find(({ weight }) => {
|
|
455
|
+
freed += weight;
|
|
456
|
+
return used - freed + count <= sendsPerHour;
|
|
457
|
+
});
|
|
458
|
+
const nextMs = (opening?.time ?? 0) + HOUR_MS;
|
|
459
|
+
const next = new Date(nextMs).toISOString();
|
|
460
|
+
throw new CliError("rate_limited", `profile ${profile} has sent ${used} messages in the hour around ${new Date(at).toISOString()}, and its limit is ${sendsPerHour} (sendsPerHour) \u2014 the next send is possible at ${next}`, { retry_after_ms: nextMs - now().getTime(), retry_at: next });
|
|
461
|
+
}
|
|
462
|
+
return true;
|
|
463
|
+
}, "withinLimit");
|
|
464
|
+
const counting = /* @__PURE__ */ __name((request) => {
|
|
465
|
+
permitted(request);
|
|
466
|
+
refuseHeld(request);
|
|
467
|
+
const asked = { ...request, people: request.personIds?.length ?? request.count };
|
|
468
|
+
const creatingTopic = request.kind === "chat" && request.action === "topic-create";
|
|
469
|
+
if (!countsTowardLimit(asked) && !creatingTopic)
|
|
470
|
+
return void 0;
|
|
471
|
+
const checked = /* @__PURE__ */ __name((entries) => {
|
|
472
|
+
if (!creatingTopic)
|
|
473
|
+
return withinLimit(request, entries);
|
|
474
|
+
if (request.sendId === void 0)
|
|
475
|
+
throw new CliError("validation_error", "a topic creation needs an attempt id");
|
|
476
|
+
if (entries.some((entry) => entry.action === "topic-create" && entry.sendId === request.sendId && ["sent", "outcome_unknown", "reserved"].includes(entry.outcome))) {
|
|
477
|
+
throw new CliError("validation_error", "this topic creation was already attempted; check topics list and do not repeat an unknown creation", { operation_id: request.sendId, retryable: false });
|
|
478
|
+
}
|
|
479
|
+
return true;
|
|
480
|
+
}, "checked");
|
|
481
|
+
const reserving = /* @__PURE__ */ __name(() => {
|
|
482
|
+
if (!checked(journal.entries()))
|
|
483
|
+
return;
|
|
484
|
+
const id = randomUUID();
|
|
485
|
+
const { chatId, kind, action, sendId, operationId, scheduledFor, notify } = request;
|
|
486
|
+
journal.append({
|
|
487
|
+
at: now().toISOString(),
|
|
488
|
+
profile,
|
|
489
|
+
chatId,
|
|
490
|
+
outcome: "reserved",
|
|
491
|
+
reservation: id,
|
|
492
|
+
...kind ? { kind } : {},
|
|
493
|
+
...action ? { action } : {},
|
|
494
|
+
...asked.people === void 0 ? {} : kind === "delete" || kind === "message" || kind === void 0 ? { count: asked.people } : { people: asked.people },
|
|
495
|
+
...sendId === void 0 ? {} : { sendId },
|
|
496
|
+
...operationId === void 0 ? {} : { operationId },
|
|
497
|
+
...scheduledFor ? { scheduledFor } : {},
|
|
498
|
+
...notify === void 0 ? {} : { notify }
|
|
499
|
+
});
|
|
500
|
+
reservation = id;
|
|
501
|
+
}, "reserving");
|
|
502
|
+
return { checked, reserving };
|
|
503
|
+
}, "counting");
|
|
504
|
+
return {
|
|
505
|
+
ask: /* @__PURE__ */ __name(async (request) => {
|
|
506
|
+
refuseReadOnly();
|
|
507
|
+
const levels = currentPermissions();
|
|
508
|
+
if (levels === void 0)
|
|
509
|
+
return;
|
|
510
|
+
const key = request.key ?? keyForWrite(request.kind ?? "message", request.action);
|
|
511
|
+
if (levelFor(levels, key, permissionDefaults).level !== "ask")
|
|
512
|
+
return;
|
|
513
|
+
refuseHeld(request);
|
|
514
|
+
await ask(key, request);
|
|
515
|
+
answered.add(request);
|
|
516
|
+
}, "ask"),
|
|
517
|
+
check: /* @__PURE__ */ __name((request, { reserve = true } = {}) => {
|
|
518
|
+
const counted = counting(request);
|
|
519
|
+
if (!counted)
|
|
520
|
+
return;
|
|
521
|
+
if (reserve)
|
|
522
|
+
journal.locked(counted.reserving);
|
|
523
|
+
else
|
|
524
|
+
counted.checked(journal.entries());
|
|
525
|
+
}, "check"),
|
|
526
|
+
reserve: /* @__PURE__ */ __name(async (request) => {
|
|
527
|
+
const counted = counting(request);
|
|
528
|
+
if (counted)
|
|
529
|
+
await journal.lockedAsync(counted.reserving);
|
|
530
|
+
}, "reserve"),
|
|
531
|
+
// After a send, a failure to write here must not become the command's answer: the message is
|
|
532
|
+
// already with a person, and an error would invite the caller to send it again.
|
|
533
|
+
record: /* @__PURE__ */ __name((entry) => {
|
|
534
|
+
const { personIds: _, ...kept } = entry;
|
|
535
|
+
const settles = entry.outcome === "refused" ? void 0 : reservation;
|
|
536
|
+
reservation = void 0;
|
|
537
|
+
try {
|
|
538
|
+
journal.append({ at: now().toISOString(), profile, ...kept, ...settles ? { reservation: settles } : {} });
|
|
539
|
+
} catch (error) {
|
|
540
|
+
warn(`this send is not in the send journal: ${journalFailure(error)}`, {
|
|
541
|
+
event: "warning",
|
|
542
|
+
code: "send_not_journaled",
|
|
543
|
+
operation: "sends.journal"
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
}, "record")
|
|
547
|
+
};
|
|
548
|
+
}, "sendGuard");
|
|
549
|
+
var refuseToAsk = /* @__PURE__ */ __name(async (key) => {
|
|
550
|
+
throw new CliError("confirmation_required", `${key} asks before it acts (its permission level is ask), and nobody is here to answer \u2014 add ${skipFlagFor(key)} to go ahead`);
|
|
551
|
+
}, "refuseToAsk");
|
|
552
|
+
var guardFor = /* @__PURE__ */ __name((app, settings, warn, env = process.env, ask) => sendGuard({
|
|
553
|
+
profile: settings.profile,
|
|
554
|
+
command: app.command,
|
|
555
|
+
...settings.readOnlyLock ? { readOnlyLock: settings.readOnlyLock } : {},
|
|
556
|
+
permissions: /* @__PURE__ */ __name(() => settings.permissions, "permissions"),
|
|
557
|
+
permissionSources: settings.permissionSources,
|
|
558
|
+
...settings.permissionDefaults ? { permissionDefaults: settings.permissionDefaults } : {},
|
|
559
|
+
...ask ? { ask } : {},
|
|
560
|
+
sendsPerHour: settings.sendsPerHour,
|
|
561
|
+
journal: new SendJournal(sendsPathFor(app, settings.profile, env), { service: app.command, version: app.version }),
|
|
562
|
+
recipients: new RecipientList(recipientsPathFor(app, settings.profile, env), app.command),
|
|
563
|
+
flood: new FloodMemory(floodPathFor(app, settings.profile, env)),
|
|
564
|
+
warn
|
|
565
|
+
}), "guardFor");
|
|
566
|
+
var journalFailure = /* @__PURE__ */ __name((error) => error?.code ?? (error instanceof Error ? error.name : "error"), "journalFailure");
|
|
567
|
+
|
|
568
|
+
export {
|
|
569
|
+
holdEnd,
|
|
570
|
+
floodPathFor,
|
|
571
|
+
FloodMemory,
|
|
572
|
+
withFileLockAsync,
|
|
573
|
+
sendsPathFor,
|
|
574
|
+
SendJournal,
|
|
575
|
+
recipientsPathFor,
|
|
576
|
+
RecipientList,
|
|
577
|
+
ceilingRefusal,
|
|
578
|
+
levelRefusal,
|
|
579
|
+
sendGuard,
|
|
580
|
+
guardFor
|
|
581
|
+
};
|