@craftsamo/whatsapp-tools 0.1.0 → 0.1.2
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/.antigravity-plugin/plugin.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +2 -1
- package/README.md +58 -12
- package/dist/cli.js +212 -146
- package/dist/mcp.js +206 -107
- package/dist/opencode.js +192 -105
- package/package.json +1 -1
- package/plugin.yaml +1 -1
- package/src/hermes/whatsapp_tools_hermes/approval.py +1 -6
- package/src/hermes/whatsapp_tools_hermes/plugin.py +2 -2
- package/src/hermes/whatsapp_tools_hermes/project.py +4 -4
- package/src/hermes/whatsapp_tools_hermes/settings.py +15 -69
package/dist/cli.js
CHANGED
|
@@ -26,6 +26,12 @@ var PROJECT = {
|
|
|
26
26
|
toolsets: ["account", "chats", "contacts", "history", "files", "sends", "actions"],
|
|
27
27
|
/** The toolsets on when a setting names none. */
|
|
28
28
|
defaultToolsets: ["account", "chats", "contacts", "history", "sends"],
|
|
29
|
+
/** The package's own settings, which the tools themselves read: each snake_case name and its type, with bounds when it needs them. */
|
|
30
|
+
options: {
|
|
31
|
+
state_dir: "path",
|
|
32
|
+
download_dir: "path",
|
|
33
|
+
send_dirs: "paths"
|
|
34
|
+
},
|
|
29
35
|
/** The environment variables the tools read besides the settings, which Codex forwards to the server after them. */
|
|
30
36
|
toolVariables: []
|
|
31
37
|
};
|
|
@@ -5100,7 +5106,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
5100
5106
|
var NONE = 0;
|
|
5101
5107
|
var ASSUMED = 1;
|
|
5102
5108
|
var PROVEN = 2;
|
|
5103
|
-
function isRecursive(inst, stack,
|
|
5109
|
+
function isRecursive(inst, stack, resolve6) {
|
|
5104
5110
|
const cached2 = recursive.get(inst);
|
|
5105
5111
|
if (cached2 !== void 0)
|
|
5106
5112
|
return cached2 ? PROVEN : NONE;
|
|
@@ -5110,7 +5116,7 @@ function isRecursive(inst, stack, resolve8) {
|
|
|
5110
5116
|
let result = NONE;
|
|
5111
5117
|
const check2 = (child) => {
|
|
5112
5118
|
if (result !== PROVEN && child?._zod) {
|
|
5113
|
-
const answer = isRecursive(child, stack,
|
|
5119
|
+
const answer = isRecursive(child, stack, resolve6);
|
|
5114
5120
|
if (answer > result)
|
|
5115
5121
|
result = answer;
|
|
5116
5122
|
}
|
|
@@ -5121,7 +5127,7 @@ function isRecursive(inst, stack, resolve8) {
|
|
|
5121
5127
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
5122
5128
|
if (spread && !desc.enumerable)
|
|
5123
5129
|
continue;
|
|
5124
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
5130
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve6) : NONE;
|
|
5125
5131
|
if (child > answer)
|
|
5126
5132
|
answer = child;
|
|
5127
5133
|
}
|
|
@@ -5185,7 +5191,7 @@ function isRecursive(inst, stack, resolve8) {
|
|
|
5185
5191
|
break;
|
|
5186
5192
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
5187
5193
|
case "lazy": {
|
|
5188
|
-
const inner = def._cachedInner ?? (
|
|
5194
|
+
const inner = def._cachedInner ?? (resolve6 ? inst._zod.innerType : void 0);
|
|
5189
5195
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
5190
5196
|
break;
|
|
5191
5197
|
}
|
|
@@ -20147,7 +20153,7 @@ function abortError(signal) {
|
|
|
20147
20153
|
}
|
|
20148
20154
|
function exec(argv, options) {
|
|
20149
20155
|
const { signal } = options;
|
|
20150
|
-
return new Promise((
|
|
20156
|
+
return new Promise((resolve6, reject) => {
|
|
20151
20157
|
if (signal?.aborted) {
|
|
20152
20158
|
reject(abortError(signal));
|
|
20153
20159
|
return;
|
|
@@ -20206,7 +20212,7 @@ function exec(argv, options) {
|
|
|
20206
20212
|
}
|
|
20207
20213
|
const finish = () => settle3(() => {
|
|
20208
20214
|
const { code, killedBy } = exitedWith ?? { code: null, killedBy: null };
|
|
20209
|
-
|
|
20215
|
+
resolve6({
|
|
20210
20216
|
code: code ?? -1,
|
|
20211
20217
|
stdout,
|
|
20212
20218
|
stderr,
|
|
@@ -22709,7 +22715,7 @@ function callService(paths, op, args, { mode, signal, timeoutMs: requestedMs = D
|
|
|
22709
22715
|
if (signal?.aborted) return Promise.reject(abortError(signal));
|
|
22710
22716
|
const timeoutMs = Number.isNaN(requestedMs) ? DEFAULT_TIMEOUT_MS2 : Math.min(Math.max(Math.ceil(requestedMs), 1), MAX_DEADLINE_MS);
|
|
22711
22717
|
const request = encodeLine({ op, args, deadline_ms: timeoutMs });
|
|
22712
|
-
return new Promise((
|
|
22718
|
+
return new Promise((resolve6, reject) => {
|
|
22713
22719
|
const socket = createConnection(paths.socket);
|
|
22714
22720
|
socket.setEncoding("utf8");
|
|
22715
22721
|
let sent = false;
|
|
@@ -22754,7 +22760,7 @@ function callService(paths, op, args, { mode, signal, timeoutMs: requestedMs = D
|
|
|
22754
22760
|
if (end === -1) return;
|
|
22755
22761
|
const response = parseResponse(received.slice(0, end));
|
|
22756
22762
|
if (!response) return unknownOutcome2("The sync service's answer could not be read");
|
|
22757
|
-
if (response.ok) return finish(() =>
|
|
22763
|
+
if (response.ok) return finish(() => resolve6(response.data));
|
|
22758
22764
|
fail(new ToolError(response.error.code, response.error.message));
|
|
22759
22765
|
});
|
|
22760
22766
|
socket.on("error", (error62) => {
|
|
@@ -27798,6 +27804,35 @@ var ALL_TRANSLATIONS = mergeTranslations(
|
|
|
27798
27804
|
FACT_TRANSLATIONS
|
|
27799
27805
|
);
|
|
27800
27806
|
|
|
27807
|
+
// src/entry/directory.ts
|
|
27808
|
+
import { homedir as homedir3 } from "node:os";
|
|
27809
|
+
import { isAbsolute as isAbsolute6, resolve as resolve4 } from "node:path";
|
|
27810
|
+
var DOWNLOADS_DIR = "Downloads";
|
|
27811
|
+
function homeDir(env7) {
|
|
27812
|
+
const envHome = env7.HOME;
|
|
27813
|
+
if (envHome && isAbsolute6(envHome)) return envHome;
|
|
27814
|
+
return homedir3();
|
|
27815
|
+
}
|
|
27816
|
+
function pathOf(value) {
|
|
27817
|
+
return typeof value === "string" ? value : void 0;
|
|
27818
|
+
}
|
|
27819
|
+
function pathsOf(value) {
|
|
27820
|
+
return typeof value === "object" ? value : [];
|
|
27821
|
+
}
|
|
27822
|
+
function directorySettings(options, env7, profile) {
|
|
27823
|
+
const home = homeDir(env7);
|
|
27824
|
+
const xdg = env7.XDG_STATE_HOME;
|
|
27825
|
+
const stateHome = xdg && isAbsolute6(xdg) ? xdg : resolve4(home, ".local", "state");
|
|
27826
|
+
return {
|
|
27827
|
+
state_dir: pathOf(options.state_dir) ?? resolve4(stateHome, profile.name),
|
|
27828
|
+
download_dir: pathOf(options.download_dir) ?? resolve4(home, DOWNLOADS_DIR, profile.name),
|
|
27829
|
+
send_dirs: [...new Set(pathsOf(options.send_dirs))]
|
|
27830
|
+
};
|
|
27831
|
+
}
|
|
27832
|
+
function toolDirectories(settings) {
|
|
27833
|
+
return { stateDir: settings.state_dir, downloadDir: settings.download_dir, sendDirs: settings.send_dirs };
|
|
27834
|
+
}
|
|
27835
|
+
|
|
27801
27836
|
// src/entry/errors.ts
|
|
27802
27837
|
function errorBody(code, message, details) {
|
|
27803
27838
|
return { code, message, ...details !== void 0 && { details } };
|
|
@@ -27903,9 +27938,9 @@ async function timedCallDescription(spec, args, ctx, timeoutMs = DESCRIBE_TIMEOU
|
|
|
27903
27938
|
let timer;
|
|
27904
27939
|
let onAbort;
|
|
27905
27940
|
try {
|
|
27906
|
-
const timedOut = new Promise((
|
|
27941
|
+
const timedOut = new Promise((resolve6) => {
|
|
27907
27942
|
timer = setTimeout(() => {
|
|
27908
|
-
|
|
27943
|
+
resolve6(void 0);
|
|
27909
27944
|
controller.abort();
|
|
27910
27945
|
}, timeoutMs);
|
|
27911
27946
|
});
|
|
@@ -27955,63 +27990,13 @@ async function checkPin(spec, args, ctx, pin, timeoutMs = DESCRIBE_TIMEOUT_MS) {
|
|
|
27955
27990
|
var PROJECT_PROFILE = {
|
|
27956
27991
|
name: PROJECT.name,
|
|
27957
27992
|
envPrefix: PROJECT.envPrefix,
|
|
27958
|
-
toolsets: { names: PROJECT.toolsets, defaults: PROJECT.defaultToolsets }
|
|
27993
|
+
toolsets: { names: PROJECT.toolsets, defaults: PROJECT.defaultToolsets },
|
|
27994
|
+
options: PROJECT.options
|
|
27959
27995
|
};
|
|
27960
27996
|
|
|
27961
|
-
// src/entry/directory.ts
|
|
27962
|
-
import { homedir as homedir3 } from "node:os";
|
|
27963
|
-
import { isAbsolute as isAbsolute6, join as join12, resolve as resolve4, sep as sep4 } from "node:path";
|
|
27964
|
-
function homeDir(env7) {
|
|
27965
|
-
const envHome = env7.HOME;
|
|
27966
|
-
if (envHome && isAbsolute6(envHome)) return envHome;
|
|
27967
|
-
return homedir3();
|
|
27968
|
-
}
|
|
27969
|
-
function expandTilde(text2, home) {
|
|
27970
|
-
if (text2 === "~") return home;
|
|
27971
|
-
if (text2.startsWith("~/") || text2.startsWith(`~${sep4}`)) {
|
|
27972
|
-
return join12(home, text2.slice(2));
|
|
27973
|
-
}
|
|
27974
|
-
return text2;
|
|
27975
|
-
}
|
|
27976
|
-
function resolveGivenDirectory(given, home) {
|
|
27977
|
-
const text2 = given.text.trim();
|
|
27978
|
-
const expanded = expandTilde(text2, home);
|
|
27979
|
-
if (!text2 || !isAbsolute6(expanded)) {
|
|
27980
|
-
throw new ToolError("invalid_argument", `${given.source} must be an absolute path.`);
|
|
27981
|
-
}
|
|
27982
|
-
return resolve4(expanded);
|
|
27983
|
-
}
|
|
27984
|
-
function toolDirectories(settings) {
|
|
27985
|
-
return { stateDir: settings.state_dir, downloadDir: settings.download_dir, sendDirs: settings.send_dirs };
|
|
27986
|
-
}
|
|
27987
|
-
|
|
27988
|
-
// src/entry/download-dir.ts
|
|
27989
|
-
import { resolve as resolve5 } from "node:path";
|
|
27990
|
-
var DOWNLOADS_DIR = "Downloads";
|
|
27991
|
-
function resolveDownloadDir(given, env7, profile) {
|
|
27992
|
-
const home = homeDir(env7);
|
|
27993
|
-
return given !== void 0 ? resolveGivenDirectory(given, home) : resolve5(home, DOWNLOADS_DIR, profile.name);
|
|
27994
|
-
}
|
|
27995
|
-
|
|
27996
|
-
// src/entry/send-dirs.ts
|
|
27997
|
-
function resolveSendDirs(given, env7) {
|
|
27998
|
-
const home = homeDir(env7);
|
|
27999
|
-
return [...new Set(given.map((directory) => resolveGivenDirectory(directory, home)))];
|
|
28000
|
-
}
|
|
28001
|
-
|
|
28002
|
-
// src/entry/state-dir.ts
|
|
28003
|
-
import { isAbsolute as isAbsolute7, resolve as resolve6 } from "node:path";
|
|
28004
|
-
function resolveStateDir(given, env7, profile) {
|
|
28005
|
-
const home = homeDir(env7);
|
|
28006
|
-
if (given !== void 0) return resolveGivenDirectory(given, home);
|
|
28007
|
-
const xdg = env7.XDG_STATE_HOME;
|
|
28008
|
-
if (xdg && isAbsolute7(xdg)) {
|
|
28009
|
-
return resolve6(xdg, profile.name);
|
|
28010
|
-
}
|
|
28011
|
-
return resolve6(home, ".local", "state", profile.name);
|
|
28012
|
-
}
|
|
28013
|
-
|
|
28014
27997
|
// src/entry/settings.ts
|
|
27998
|
+
import { homedir as homedir4 } from "node:os";
|
|
27999
|
+
import { isAbsolute as isAbsolute7, join as join12, resolve as resolvePath, sep as sep4 } from "node:path";
|
|
28015
28000
|
var CONFIRM_MODES = ["harness", "elicitation"];
|
|
28016
28001
|
var ALL_TOOLSETS = "all";
|
|
28017
28002
|
var TRUE_VALUES = ["1", "true"];
|
|
@@ -28021,17 +28006,28 @@ var OPTIONS = {
|
|
|
28021
28006
|
read_only: { flag: "--read-only", envSuffix: "READ_ONLY", boolean: true },
|
|
28022
28007
|
tools: { flag: "--tools", envSuffix: "TOOLS" },
|
|
28023
28008
|
exclude_tools: { flag: "--exclude-tools", envSuffix: "EXCLUDE_TOOLS" },
|
|
28024
|
-
confirm: { flag: "--confirm", envSuffix: "CONFIRM" }
|
|
28025
|
-
state_dir: { flag: "--state-dir", envSuffix: "STATE_DIR" },
|
|
28026
|
-
download_dir: { flag: "--download-dir", envSuffix: "DOWNLOAD_DIR" },
|
|
28027
|
-
send_dirs: { flag: "--send-dirs", envSuffix: "SEND_DIRS" }
|
|
28009
|
+
confirm: { flag: "--confirm", envSuffix: "CONFIRM" }
|
|
28028
28010
|
};
|
|
28011
|
+
function profileOptions(profile) {
|
|
28012
|
+
return profile.options ?? {};
|
|
28013
|
+
}
|
|
28014
|
+
function settingOptions(profile) {
|
|
28015
|
+
const toolOptions = Object.entries(profileOptions(profile)).map(([name, spec]) => [
|
|
28016
|
+
name,
|
|
28017
|
+
{
|
|
28018
|
+
flag: `--${name.replace(/_/g, "-")}`,
|
|
28019
|
+
envSuffix: name.toUpperCase(),
|
|
28020
|
+
...optionType(spec) === "boolean" && { boolean: true }
|
|
28021
|
+
}
|
|
28022
|
+
]);
|
|
28023
|
+
return { ...OPTIONS, ...Object.fromEntries(toolOptions) };
|
|
28024
|
+
}
|
|
28029
28025
|
function envName(name, profile) {
|
|
28030
|
-
return `${profile.envPrefix}_${
|
|
28026
|
+
return `${profile.envPrefix}_${settingOptions(profile)[name].envSuffix}`;
|
|
28031
28027
|
}
|
|
28032
|
-
function readFlags(argv) {
|
|
28028
|
+
function readFlags(argv, profile) {
|
|
28033
28029
|
const byFlag = new Map(
|
|
28034
|
-
Object.
|
|
28030
|
+
Object.entries(settingOptions(profile)).map(([name, option]) => [option.flag, { name, ...option }])
|
|
28035
28031
|
);
|
|
28036
28032
|
const given = {};
|
|
28037
28033
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -28056,9 +28052,6 @@ function readFlags(argv) {
|
|
|
28056
28052
|
function splitList(value) {
|
|
28057
28053
|
return value.split(",").map((item) => item.trim()).filter((item) => item !== "");
|
|
28058
28054
|
}
|
|
28059
|
-
function listedDirectories(given) {
|
|
28060
|
-
return given === void 0 ? [] : splitList(given.text).map((text2) => ({ text: text2, source: given.source }));
|
|
28061
|
-
}
|
|
28062
28055
|
function checkToolsets(names, source, toolsets) {
|
|
28063
28056
|
if (names.includes(ALL_TOOLSETS)) return ALL_TOOLSETS;
|
|
28064
28057
|
const unknown2 = names.find((name) => !toolsets.names.includes(name));
|
|
@@ -28087,20 +28080,108 @@ function parseConfirm(value, source) {
|
|
|
28087
28080
|
}
|
|
28088
28081
|
return mode;
|
|
28089
28082
|
}
|
|
28083
|
+
function parseNumber2(value, source) {
|
|
28084
|
+
const trimmed = value.trim();
|
|
28085
|
+
const parsed = trimmed === "" ? Number.NaN : Number(trimmed);
|
|
28086
|
+
if (!Number.isFinite(parsed)) {
|
|
28087
|
+
throw new ToolError("invalid_argument", `Unknown number "${value}" in ${source}; use a finite number.`);
|
|
28088
|
+
}
|
|
28089
|
+
return parsed;
|
|
28090
|
+
}
|
|
28091
|
+
function absolutePath(text2, source, env7) {
|
|
28092
|
+
const home = env7.HOME !== void 0 && isAbsolute7(env7.HOME) ? env7.HOME : homedir4();
|
|
28093
|
+
const expanded = text2 === "~" || text2.startsWith("~/") || text2.startsWith(`~${sep4}`) ? join12(home, text2.slice(1)) : text2;
|
|
28094
|
+
if (!isAbsolute7(expanded)) throw new ToolError("invalid_argument", `${source} must be an absolute path.`);
|
|
28095
|
+
return resolvePath(expanded);
|
|
28096
|
+
}
|
|
28097
|
+
function absolutePaths(items, source, env7) {
|
|
28098
|
+
return items.length > 0 ? items.map((item) => absolutePath(item, source, env7)) : void 0;
|
|
28099
|
+
}
|
|
28090
28100
|
function envText(name, env7, profile) {
|
|
28091
28101
|
const variable = envName(name, profile);
|
|
28092
28102
|
const text2 = env7[variable];
|
|
28093
28103
|
return text2 === void 0 || text2.trim() === "" ? void 0 : { text: text2, source: variable };
|
|
28094
28104
|
}
|
|
28105
|
+
function optionType(spec) {
|
|
28106
|
+
return typeof spec === "string" ? spec : spec.type;
|
|
28107
|
+
}
|
|
28108
|
+
function itemCount(count) {
|
|
28109
|
+
return count === 1 ? "1 item" : `${count} items`;
|
|
28110
|
+
}
|
|
28111
|
+
function numberBoundsError({ integer: integer2, min, max }, source) {
|
|
28112
|
+
const range = min !== void 0 && max !== void 0 ? ` from ${min} to ${max}` : min !== void 0 ? ` of at least ${min}` : max !== void 0 ? ` of at most ${max}` : "";
|
|
28113
|
+
return new ToolError("invalid_argument", `${source} must be ${integer2 ? "a whole number" : "a number"}${range}.`);
|
|
28114
|
+
}
|
|
28115
|
+
function countBoundsError({ min, max }, source) {
|
|
28116
|
+
const range = min !== void 0 && max !== void 0 ? `from ${min} to ${max} items` : min !== void 0 ? `at least ${itemCount(min)}` : `at most ${itemCount(max)}`;
|
|
28117
|
+
return new ToolError("invalid_argument", `${source} must list ${range}.`);
|
|
28118
|
+
}
|
|
28119
|
+
function withinBounds(spec, value, source) {
|
|
28120
|
+
if (value === void 0 || typeof spec === "string") return value;
|
|
28121
|
+
const bounds = spec;
|
|
28122
|
+
const { integer: integer2, min, max } = bounds;
|
|
28123
|
+
if (typeof value === "number") {
|
|
28124
|
+
if (integer2 && !Number.isInteger(value) || min !== void 0 && value < min || max !== void 0 && value > max) {
|
|
28125
|
+
throw numberBoundsError(bounds, source);
|
|
28126
|
+
}
|
|
28127
|
+
} else if (typeof value === "object" && (min !== void 0 && value.length < min || max !== void 0 && value.length > max)) {
|
|
28128
|
+
throw countBoundsError(bounds, source);
|
|
28129
|
+
}
|
|
28130
|
+
return value;
|
|
28131
|
+
}
|
|
28132
|
+
function parseOptionText(spec, given, env7) {
|
|
28133
|
+
return withinBounds(spec, parseTypedText(optionType(spec), given, env7), given.source);
|
|
28134
|
+
}
|
|
28135
|
+
function parseTypedText(kind, given, env7) {
|
|
28136
|
+
switch (kind) {
|
|
28137
|
+
case "text":
|
|
28138
|
+
return nonBlank(given.text);
|
|
28139
|
+
case "boolean":
|
|
28140
|
+
return parseBoolean(given.text, given.source);
|
|
28141
|
+
case "number":
|
|
28142
|
+
return parseNumber2(given.text, given.source);
|
|
28143
|
+
case "list": {
|
|
28144
|
+
const items = splitList(given.text);
|
|
28145
|
+
return items.length > 0 ? items : void 0;
|
|
28146
|
+
}
|
|
28147
|
+
case "path": {
|
|
28148
|
+
const text2 = nonBlank(given.text);
|
|
28149
|
+
return text2 === void 0 ? void 0 : absolutePath(text2, given.source, env7);
|
|
28150
|
+
}
|
|
28151
|
+
case "paths":
|
|
28152
|
+
return absolutePaths(splitList(given.text), given.source, env7);
|
|
28153
|
+
}
|
|
28154
|
+
}
|
|
28155
|
+
function optionsFrom(flags, env7, profile) {
|
|
28156
|
+
const options = {};
|
|
28157
|
+
for (const [name, spec] of Object.entries(profileOptions(profile))) {
|
|
28158
|
+
if (flags[name] !== void 0) {
|
|
28159
|
+
const parsed = parseOptionText(spec, { text: flags[name], source: settingOptions(profile)[name].flag }, env7);
|
|
28160
|
+
if (parsed !== void 0) options[name] = parsed;
|
|
28161
|
+
continue;
|
|
28162
|
+
}
|
|
28163
|
+
const fromEnv = envText(name, env7, profile);
|
|
28164
|
+
if (fromEnv !== void 0) {
|
|
28165
|
+
const parsed = parseOptionText(spec, fromEnv, env7);
|
|
28166
|
+
if (parsed !== void 0) options[name] = parsed;
|
|
28167
|
+
}
|
|
28168
|
+
}
|
|
28169
|
+
return options;
|
|
28170
|
+
}
|
|
28171
|
+
function parseToolOptions(argv, env7, profile = PROJECT_PROFILE) {
|
|
28172
|
+
const flags = readFlags(argv, profile);
|
|
28173
|
+
const known = profileOptions(profile);
|
|
28174
|
+
const other = Object.keys(flags).find((name) => !(name in known));
|
|
28175
|
+
if (other !== void 0) {
|
|
28176
|
+
throw new ToolError("invalid_argument", `Unknown option "${settingOptions(profile)[other].flag}".`);
|
|
28177
|
+
}
|
|
28178
|
+
return optionsFrom(flags, env7, profile);
|
|
28179
|
+
}
|
|
28095
28180
|
function parseSettings(argv, env7, profile = PROJECT_PROFILE) {
|
|
28096
|
-
const flags = readFlags(argv);
|
|
28181
|
+
const flags = readFlags(argv, profile);
|
|
28097
28182
|
const value = (name) => flags[name] !== void 0 ? { text: flags[name], source: OPTIONS[name].flag } : envText(name, env7, profile);
|
|
28098
|
-
const
|
|
28099
|
-
|
|
28100
|
-
state_dir: resolveStateDir(value("state_dir"), env7, profile),
|
|
28101
|
-
download_dir: resolveDownloadDir(value("download_dir"), env7, profile),
|
|
28102
|
-
send_dirs: resolveSendDirs(listedDirectories(value("send_dirs")), env7)
|
|
28103
|
-
};
|
|
28183
|
+
const options = optionsFrom(flags, env7, profile);
|
|
28184
|
+
const settings = { confirm: "harness", ...directorySettings(options, env7, profile), options };
|
|
28104
28185
|
const toolsets = value("toolsets");
|
|
28105
28186
|
if (toolsets) settings.toolsets = checkToolsets(splitList(toolsets.text), toolsets.source, profile.toolsets);
|
|
28106
28187
|
const readOnly = value("read_only");
|
|
@@ -28125,38 +28206,6 @@ function parseToolSettings(argv, env7, profile = PROJECT_PROFILE) {
|
|
|
28125
28206
|
);
|
|
28126
28207
|
return settings;
|
|
28127
28208
|
}
|
|
28128
|
-
function parseStateDir(argv, env7, profile = PROJECT_PROFILE) {
|
|
28129
|
-
const flags = readFlags(argv);
|
|
28130
|
-
const other = Object.keys(flags).find((name) => name !== "state_dir");
|
|
28131
|
-
if (other !== void 0)
|
|
28132
|
-
throw new ToolError("invalid_argument", `Option ${OPTIONS[other].flag} is not available here.`);
|
|
28133
|
-
const given = flags.state_dir !== void 0 ? { text: flags.state_dir, source: OPTIONS.state_dir.flag } : void 0;
|
|
28134
|
-
return resolveStateDir(given ?? envText("state_dir", env7, profile), env7, profile);
|
|
28135
|
-
}
|
|
28136
|
-
var DIRECTORY_OPTION_NAMES = ["state_dir", "download_dir", "send_dirs"];
|
|
28137
|
-
function parseDirectorySettings(argv, env7, profile = PROJECT_PROFILE) {
|
|
28138
|
-
const flags = readFlags(argv);
|
|
28139
|
-
const other = Object.keys(flags).find((name) => !DIRECTORY_OPTION_NAMES.includes(name));
|
|
28140
|
-
if (other !== void 0)
|
|
28141
|
-
throw new ToolError("invalid_argument", `Option ${OPTIONS[other].flag} is not available here.`);
|
|
28142
|
-
const value = (name) => flags[name] !== void 0 ? { text: flags[name], source: OPTIONS[name].flag } : envText(name, env7, profile);
|
|
28143
|
-
return {
|
|
28144
|
-
state_dir: resolveStateDir(value("state_dir"), env7, profile),
|
|
28145
|
-
download_dir: resolveDownloadDir(value("download_dir"), env7, profile),
|
|
28146
|
-
send_dirs: resolveSendDirs(listedDirectories(value("send_dirs")), env7)
|
|
28147
|
-
};
|
|
28148
|
-
}
|
|
28149
|
-
var TOOL_OPTION_NAMES = [
|
|
28150
|
-
"toolsets",
|
|
28151
|
-
"read_only",
|
|
28152
|
-
"tools",
|
|
28153
|
-
"exclude_tools",
|
|
28154
|
-
"state_dir",
|
|
28155
|
-
"download_dir",
|
|
28156
|
-
"send_dirs"
|
|
28157
|
-
];
|
|
28158
|
-
var LANGUAGE_OPTION = "language";
|
|
28159
|
-
var PLUGIN_OPTION_NAMES = [...TOOL_OPTION_NAMES, LANGUAGE_OPTION];
|
|
28160
28209
|
function languageVariable(profile = PROJECT_PROFILE) {
|
|
28161
28210
|
return `${profile.envPrefix}_LANGUAGE`;
|
|
28162
28211
|
}
|
|
@@ -28183,6 +28232,7 @@ async function defaultReadLine(prompt) {
|
|
|
28183
28232
|
}
|
|
28184
28233
|
|
|
28185
28234
|
// src/cli/command-args.ts
|
|
28235
|
+
var STATE_DIR_OPTION = "state_dir";
|
|
28186
28236
|
function usageError(message) {
|
|
28187
28237
|
return new ToolError("invalid_argument", message);
|
|
28188
28238
|
}
|
|
@@ -28231,7 +28281,10 @@ function parseFlagArgs(argv, spec) {
|
|
|
28231
28281
|
return { values, switches, rest };
|
|
28232
28282
|
}
|
|
28233
28283
|
function parseCommandStateDir(rest, io) {
|
|
28234
|
-
|
|
28284
|
+
const profile = io.profile ?? PROJECT_PROFILE;
|
|
28285
|
+
const options = Object.entries(profile.options ?? {}).filter(([name]) => name === STATE_DIR_OPTION);
|
|
28286
|
+
const stateOnly = { ...profile, options: Object.fromEntries(options) };
|
|
28287
|
+
return directorySettings(parseToolOptions(rest, io.env, stateOnly), io.env, profile).state_dir;
|
|
28235
28288
|
}
|
|
28236
28289
|
|
|
28237
28290
|
// src/core/whatsapp/pairing.ts
|
|
@@ -28283,9 +28336,9 @@ function spawnError(error62) {
|
|
|
28283
28336
|
}
|
|
28284
28337
|
function spawnWacli(program, args, { env: env7, onStdoutLine, onStderrLine, onRawStderrLine, stopGraceMs = DEFAULT_STOP_GRACE_MS }) {
|
|
28285
28338
|
const child = spawn2(program, args, { env: env7, shell: false, stdio: ["ignore", "pipe", "pipe"] });
|
|
28286
|
-
const spawned = new Promise((
|
|
28287
|
-
child.once("spawn", () =>
|
|
28288
|
-
child.once("error", () =>
|
|
28339
|
+
const spawned = new Promise((resolve6) => {
|
|
28340
|
+
child.once("spawn", () => resolve6(true));
|
|
28341
|
+
child.once("error", () => resolve6(false));
|
|
28289
28342
|
});
|
|
28290
28343
|
const stdout = lineSplitter((line) => onStdoutLine?.(line));
|
|
28291
28344
|
const stderr = lineSplitter((line) => {
|
|
@@ -28297,14 +28350,14 @@ function spawnWacli(program, args, { env: env7, onStdoutLine, onStderrLine, onRa
|
|
|
28297
28350
|
let killTimer;
|
|
28298
28351
|
let drainTimer;
|
|
28299
28352
|
let ended2;
|
|
28300
|
-
const exited = new Promise((
|
|
28353
|
+
const exited = new Promise((resolve6, reject) => {
|
|
28301
28354
|
const finish = () => {
|
|
28302
28355
|
clearTimeout(drainTimer);
|
|
28303
28356
|
child.stdout.destroy();
|
|
28304
28357
|
child.stderr.destroy();
|
|
28305
28358
|
stdout.flush();
|
|
28306
28359
|
stderr.flush();
|
|
28307
|
-
|
|
28360
|
+
resolve6(ended2);
|
|
28308
28361
|
};
|
|
28309
28362
|
child.on("error", (error62) => {
|
|
28310
28363
|
clearTimeout(killTimer);
|
|
@@ -28431,9 +28484,9 @@ async function runAuth(program, paths, phone, options) {
|
|
|
28431
28484
|
});
|
|
28432
28485
|
let timer;
|
|
28433
28486
|
let onAbort;
|
|
28434
|
-
const interrupted = new Promise((
|
|
28435
|
-
timer = setTimeout(() =>
|
|
28436
|
-
onAbort = () =>
|
|
28487
|
+
const interrupted = new Promise((resolve6) => {
|
|
28488
|
+
timer = setTimeout(() => resolve6("timeout"), timeoutMs);
|
|
28489
|
+
onAbort = () => resolve6("abort");
|
|
28437
28490
|
if (signal.aborted) onAbort();
|
|
28438
28491
|
else signal.addEventListener("abort", onAbort, { once: true });
|
|
28439
28492
|
});
|
|
@@ -29633,7 +29686,7 @@ import { realpathSync } from "node:fs";
|
|
|
29633
29686
|
|
|
29634
29687
|
// src/cli/service-program.ts
|
|
29635
29688
|
import { access as access2, constants as constants6, realpath as realpath7, stat as stat5 } from "node:fs/promises";
|
|
29636
|
-
import { isAbsolute as isAbsolute8, join as join16, resolve as
|
|
29689
|
+
import { isAbsolute as isAbsolute8, join as join16, resolve as resolve5, sep as sep5 } from "node:path";
|
|
29637
29690
|
var PROBE_TIMEOUT_MS = 1e4;
|
|
29638
29691
|
var PROGRAM_NAME2 = "node";
|
|
29639
29692
|
var PROBE_ARGS = ["-p", "process.execPath"];
|
|
@@ -29666,7 +29719,7 @@ async function resolveRoots(roots) {
|
|
|
29666
29719
|
const resolved = /* @__PURE__ */ new Set();
|
|
29667
29720
|
for (const root of roots) {
|
|
29668
29721
|
if (root === "" || !isAbsolute8(root)) continue;
|
|
29669
|
-
resolved.add(
|
|
29722
|
+
resolved.add(resolve5(root));
|
|
29670
29723
|
try {
|
|
29671
29724
|
resolved.add(await realpath7(root));
|
|
29672
29725
|
} catch {
|
|
@@ -29697,7 +29750,7 @@ async function pickStableProgram(options) {
|
|
|
29697
29750
|
if (dir !== "" && isAbsolute8(dir)) candidates.add(join16(dir, PROGRAM_NAME2));
|
|
29698
29751
|
}
|
|
29699
29752
|
for (const candidate of candidates) {
|
|
29700
|
-
if (pathHoldsVersion(candidate, version2) || isUnder(
|
|
29753
|
+
if (pathHoldsVersion(candidate, version2) || isUnder(resolve5(candidate), volatileRoots)) continue;
|
|
29701
29754
|
if (!await isExecutableFile2(candidate)) continue;
|
|
29702
29755
|
let started;
|
|
29703
29756
|
try {
|
|
@@ -29959,8 +30012,10 @@ import { setTimeout as delay3 } from "node:timers/promises";
|
|
|
29959
30012
|
// src/core/whatsapp/service-socket.ts
|
|
29960
30013
|
import { chmod as chmod5, rm as rm6 } from "node:fs/promises";
|
|
29961
30014
|
import { createServer } from "node:net";
|
|
30015
|
+
import { clearTimeout as clearTimeout2, setTimeout as setTimeout4 } from "node:timers";
|
|
29962
30016
|
var MAX_REQUEST_BYTES = 1048576;
|
|
29963
30017
|
var REQUEST_READ_TIMEOUT_MS = 1e4;
|
|
30018
|
+
var CLOSE_GRACE_MS = 1e3;
|
|
29964
30019
|
var MAX_QUOTED_OP = 40;
|
|
29965
30020
|
var MAX_LOGGED_ERROR = 200;
|
|
29966
30021
|
var SOCKET_MODE = 384;
|
|
@@ -30079,11 +30134,11 @@ async function listenOnServiceSocket(path, options) {
|
|
|
30079
30134
|
});
|
|
30080
30135
|
});
|
|
30081
30136
|
await rm6(path, { force: true });
|
|
30082
|
-
await new Promise((
|
|
30137
|
+
await new Promise((resolve6, reject) => {
|
|
30083
30138
|
server.once("error", reject);
|
|
30084
30139
|
server.listen(path, () => {
|
|
30085
30140
|
server.off("error", reject);
|
|
30086
|
-
|
|
30141
|
+
resolve6();
|
|
30087
30142
|
});
|
|
30088
30143
|
});
|
|
30089
30144
|
try {
|
|
@@ -30097,9 +30152,16 @@ async function listenOnServiceSocket(path, options) {
|
|
|
30097
30152
|
close() {
|
|
30098
30153
|
closing ??= (async () => {
|
|
30099
30154
|
shutdown.abort();
|
|
30100
|
-
const closed = new Promise((
|
|
30155
|
+
const closed = new Promise((resolve6) => server.close(() => resolve6()));
|
|
30101
30156
|
await queue;
|
|
30102
30157
|
for (const socket of sockets) socket.end(() => socket.destroy());
|
|
30158
|
+
let timer;
|
|
30159
|
+
const grace = new Promise((resolve6) => {
|
|
30160
|
+
timer = setTimeout4(resolve6, CLOSE_GRACE_MS).unref();
|
|
30161
|
+
});
|
|
30162
|
+
await Promise.race([closed, grace]);
|
|
30163
|
+
clearTimeout2(timer);
|
|
30164
|
+
for (const socket of sockets) socket.destroy();
|
|
30103
30165
|
await closed;
|
|
30104
30166
|
await rm6(path, { force: true });
|
|
30105
30167
|
})();
|
|
@@ -30127,7 +30189,7 @@ var Ending = class {
|
|
|
30127
30189
|
};
|
|
30128
30190
|
result;
|
|
30129
30191
|
constructor() {
|
|
30130
|
-
this.promise = new Promise((
|
|
30192
|
+
this.promise = new Promise((resolve6) => this.resolve = resolve6);
|
|
30131
30193
|
}
|
|
30132
30194
|
/** Aborts once the run has ended, so waits and operations still going give up. */
|
|
30133
30195
|
get signal() {
|
|
@@ -30186,7 +30248,7 @@ function startSyncChild(options) {
|
|
|
30186
30248
|
let stoppedByService = false;
|
|
30187
30249
|
let markReady = () => {
|
|
30188
30250
|
};
|
|
30189
|
-
const ready = new Promise((
|
|
30251
|
+
const ready = new Promise((resolve6) => markReady = resolve6);
|
|
30190
30252
|
const wacli2 = spawnWacli(program, syncArgv(paths), {
|
|
30191
30253
|
env: wacliEnv(env7, paths),
|
|
30192
30254
|
stopGraceMs,
|
|
@@ -30213,11 +30275,11 @@ function startSyncChild(options) {
|
|
|
30213
30275
|
};
|
|
30214
30276
|
}
|
|
30215
30277
|
function waitUntilReady(child, signal) {
|
|
30216
|
-
return new Promise((
|
|
30217
|
-
if (signal.aborted) return
|
|
30278
|
+
return new Promise((resolve6) => {
|
|
30279
|
+
if (signal.aborted) return resolve6(false);
|
|
30218
30280
|
const finish = (ready) => {
|
|
30219
30281
|
signal.removeEventListener("abort", onAbort);
|
|
30220
|
-
|
|
30282
|
+
resolve6(ready);
|
|
30221
30283
|
};
|
|
30222
30284
|
const onAbort = () => finish(false);
|
|
30223
30285
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
@@ -30526,9 +30588,17 @@ function takeFlag(argv, flag2) {
|
|
|
30526
30588
|
}
|
|
30527
30589
|
function parseCommand(argv, io) {
|
|
30528
30590
|
const profile = io.profile ?? PROJECT_PROFILE;
|
|
30591
|
+
const select = (flags) => {
|
|
30592
|
+
const settings = parseToolSettings(flags, io.env, profile);
|
|
30593
|
+
return {
|
|
30594
|
+
selected: selectTools(io.specs, settings, profile.toolsets),
|
|
30595
|
+
directories: toolDirectories(settings),
|
|
30596
|
+
options: settings.options
|
|
30597
|
+
};
|
|
30598
|
+
};
|
|
30529
30599
|
const [name, ...args] = argv;
|
|
30530
30600
|
if (name === "list") {
|
|
30531
|
-
return { name, selected:
|
|
30601
|
+
return { name, selected: select(args).selected };
|
|
30532
30602
|
}
|
|
30533
30603
|
if (name !== "run" && name !== "target") {
|
|
30534
30604
|
const given = name === void 0 ? "No command given" : `Unknown command "${name}"`;
|
|
@@ -30542,28 +30612,22 @@ function parseCommand(argv, io) {
|
|
|
30542
30612
|
if (cwd === void 0) throw usageError(`Command ${name} needs ${CWD_FLAG} <dir>.`);
|
|
30543
30613
|
if (name === "target") {
|
|
30544
30614
|
const { value: language, rest: afterLanguage } = takeFlag(rest, LANGUAGE_FLAG);
|
|
30545
|
-
const { value: harnessLanguage, rest:
|
|
30615
|
+
const { value: harnessLanguage, rest: targetSettings } = takeFlag(afterLanguage, HARNESS_LANGUAGE_FLAG);
|
|
30616
|
+
const toolOptions = parseToolOptions(targetSettings, io.env, profile);
|
|
30546
30617
|
return {
|
|
30547
30618
|
name,
|
|
30548
30619
|
toolId,
|
|
30549
30620
|
cwd,
|
|
30550
|
-
directories: toolDirectories(
|
|
30551
|
-
language: promptLanguage(language, io.env, harnessLanguage, profile)
|
|
30621
|
+
directories: toolDirectories(directorySettings(toolOptions, io.env, profile)),
|
|
30622
|
+
language: promptLanguage(language, io.env, harnessLanguage, profile),
|
|
30623
|
+
options: toolOptions
|
|
30552
30624
|
};
|
|
30553
30625
|
}
|
|
30554
30626
|
const { value: pin, rest: selection } = takeFlag(rest, PIN_FLAG);
|
|
30555
30627
|
if (pin !== void 0 && !PIN_PATTERN.test(pin)) {
|
|
30556
30628
|
throw usageError(`Option ${PIN_FLAG} needs the 64 lowercase hexadecimal digits \`target\` answered with.`);
|
|
30557
30629
|
}
|
|
30558
|
-
|
|
30559
|
-
return {
|
|
30560
|
-
name,
|
|
30561
|
-
toolId,
|
|
30562
|
-
cwd,
|
|
30563
|
-
pin,
|
|
30564
|
-
selected: selectTools(io.specs, settings, profile.toolsets),
|
|
30565
|
-
directories: toolDirectories(settings)
|
|
30566
|
-
};
|
|
30630
|
+
return { name, toolId, cwd, pin, ...select(selection) };
|
|
30567
30631
|
}
|
|
30568
30632
|
function describeSpec(spec) {
|
|
30569
30633
|
return {
|
|
@@ -30605,6 +30669,7 @@ async function runTool(command, io) {
|
|
|
30605
30669
|
ownDir: io.ownDir,
|
|
30606
30670
|
...command.directories,
|
|
30607
30671
|
programName: PROJECT.name,
|
|
30672
|
+
options: command.options,
|
|
30608
30673
|
signal: io.signal
|
|
30609
30674
|
};
|
|
30610
30675
|
await checkPin(spec, args, ctx, command.pin, io.describeTimeoutMs);
|
|
@@ -30629,6 +30694,7 @@ async function targetOf5(command, io) {
|
|
|
30629
30694
|
ownDir: io.ownDir,
|
|
30630
30695
|
...command.directories,
|
|
30631
30696
|
programName: PROJECT.name,
|
|
30697
|
+
options: command.options,
|
|
30632
30698
|
signal: io.signal
|
|
30633
30699
|
};
|
|
30634
30700
|
const t = promptTranslator(io.translations ?? {}, command.language);
|