@thesashadev/girl-agent 0.1.4 → 0.1.6

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cli.js +128 -26
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.6 — --new flag
4
+
5
+ Дата: 2026-05-06
6
+
7
+ - Добавлен флаг `--new` для принудительного открытия визарда при создании нового профиля (даже если уже есть существующие).
8
+
9
+ ## 0.1.5 — owner TG credentials proxy
10
+
11
+ Дата: 2026-05-06
12
+
13
+ - Добавлен TG auth proxy для пользователей без доступа к my.telegram.org (виртуальные номера, новые аккаунты, VPN с IP датацентра).
14
+ - Новый шаг визарда: выбор между своими api_id/api_hash или использованием от владельца.
15
+ - Весь процесс авторизации через MTProto идёт через прокси-сервер — креды владельца не отображаются.
16
+ - Добавлен модуль `src/telegram/remote-auth.ts` — HTTP-клиент для прокси.
17
+ - Proxy URL настраивается через `GIRL_AGENT_AUTH_PROXY` env var (по умолчанию `https://tgproxy.girl-agent.com`).
18
+
3
19
  ## 0.1.4 — npm publish automation
4
20
 
5
21
  Дата: 2026-05-06
package/dist/cli.js CHANGED
@@ -1353,6 +1353,35 @@ function fallbackBusySchedule(name, age) {
1353
1353
  // src/wizard/index.tsx
1354
1354
  init_userbot();
1355
1355
 
1356
+ // src/telegram/remote-auth.ts
1357
+ init_esm_shims();
1358
+ var DEFAULT_PROXY = "https://tgproxy.girl-agent.com";
1359
+ function proxyUrl() {
1360
+ return process.env.GIRL_AGENT_AUTH_PROXY ?? DEFAULT_PROXY;
1361
+ }
1362
+ async function post(path5, body) {
1363
+ const res = await fetch(`${proxyUrl()}${path5}`, {
1364
+ method: "POST",
1365
+ headers: { "Content-Type": "application/json" },
1366
+ body: JSON.stringify(body)
1367
+ });
1368
+ const data = await res.json();
1369
+ if (!res.ok) throw new Error(data.error ?? `proxy ${path5} failed (${res.status})`);
1370
+ return data;
1371
+ }
1372
+ function remoteSendCode(phone) {
1373
+ return post("/send-code", { phone });
1374
+ }
1375
+ function remoteVerifyCode(loginToken, code) {
1376
+ return post("/verify-code", { loginToken, code });
1377
+ }
1378
+ function remoteVerifyPassword(loginToken, password) {
1379
+ return post("/verify-password", { loginToken, password });
1380
+ }
1381
+ function isNeeds2FA(r) {
1382
+ return "needs2fa" in r && r.needs2fa === true;
1383
+ }
1384
+
1356
1385
  // src/data/names.ts
1357
1386
  init_esm_shims();
1358
1387
  var NAMES_RU = [
@@ -1577,6 +1606,8 @@ function Wizard({ initial, onDone }) {
1577
1606
  const [code, setCode] = useState("");
1578
1607
  const [pass2fa, setPass2fa] = useState("");
1579
1608
  const [sessionString, setSessionString] = useState(initial?.telegram?.sessionString ?? "");
1609
+ const [useOwnerCreds, setUseOwnerCreds] = useState(false);
1610
+ const [loginToken, setLoginToken] = useState("");
1580
1611
  const [llmPresetId, setLlmPresetId] = useState(initial?.llm?.presetId ?? "openai");
1581
1612
  const [llmProto, setLlmProto] = useState(initial?.llm?.proto ?? "openai");
1582
1613
  const [llmBaseURL, setLlmBaseURL] = useState(initial?.llm?.baseURL ?? "");
@@ -1681,7 +1712,7 @@ function Wizard({ initial, onDone }) {
1681
1712
  onSelect: (it) => {
1682
1713
  const m = it.value;
1683
1714
  setMode(m);
1684
- setStep(m === "bot" ? "tg-bot-token" : "tg-userbot-api");
1715
+ setStep(m === "bot" ? "tg-bot-token" : "tg-userbot-source");
1685
1716
  }
1686
1717
  }
1687
1718
  )));
@@ -1696,39 +1727,108 @@ function Wizard({ initial, onDone }) {
1696
1727
  setStep("api-preset");
1697
1728
  } })), error && /* @__PURE__ */ React.createElement(Text, { color: "red" }, error));
1698
1729
  }
1730
+ if (step === "tg-userbot-source") {
1731
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "\u0443 \u0442\u0435\u0431\u044F \u0435\u0441\u0442\u044C \u0441\u0432\u043E\u0438 API credentials?" }), /* @__PURE__ */ React.createElement(Bar, { step: 1, total: 9 }), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(
1732
+ SelectInput,
1733
+ {
1734
+ items: [
1735
+ { label: "\u0414\u0430, \u0443 \u043C\u0435\u043D\u044F \u0435\u0441\u0442\u044C api_id \u0438 api_hash (my.telegram.org)", value: "own" },
1736
+ { label: "\u041D\u0435\u0442 \u2014 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u043E\u0442 \u0432\u043B\u0430\u0434\u0435\u043B\u044C\u0446\u0430 \u0431\u043E\u0442\u0430", value: "owner" }
1737
+ ],
1738
+ onSelect: (it) => {
1739
+ if (it.value === "own") {
1740
+ setUseOwnerCreds(false);
1741
+ setStep("tg-userbot-api");
1742
+ } else {
1743
+ setUseOwnerCreds(true);
1744
+ setStep("tg-userbot-phone");
1745
+ }
1746
+ }
1747
+ }
1748
+ )), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "\u0435\u0441\u043B\u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0448\u044C \u0441\u043E\u0437\u0434\u0430\u0442\u044C \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0435 \u043D\u0430 my.telegram.org \u2014 \u0432\u044B\u0431\u0435\u0440\u0438 \u0432\u0442\u043E\u0440\u043E\u0439 \u0432\u0430\u0440\u0438\u0430\u043D\u0442")));
1749
+ }
1699
1750
  if (step === "tg-userbot-api") {
1700
1751
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "userbot \xB7 my.telegram.org \u2192 API_ID \u0438 API_HASH" }), /* @__PURE__ */ React.createElement(Bar, { step: 1, total: 9 }), focusedInput === "apiId" ? /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, "API_ID: "), /* @__PURE__ */ React.createElement(TextInput, { value: apiId, onChange: setApiId, onSubmit: () => setFocusedInput("apiHash") })) : /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, "API_ID: "), /* @__PURE__ */ React.createElement(Text, { color: focusedInput === "apiHash" ? "dimColor" : "white" }, apiId || "(\u043F\u0443\u0441\u0442\u043E)")), focusedInput === "apiHash" ? /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, null, "API_HASH: "), /* @__PURE__ */ React.createElement(TextInput, { value: apiHash, onChange: setApiHash, mask: "\u2022", onSubmit: () => apiId && setStep("tg-userbot-phone") })) : /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, null, "API_HASH: "), /* @__PURE__ */ React.createElement(Text, { color: focusedInput === "apiId" ? "dimColor" : "white" }, apiHash ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : "(\u043F\u0443\u0441\u0442\u043E)")), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "Tab / \u0441\u0442\u0440\u0435\u043B\u043A\u0438 \u0447\u0442\u043E\u0431\u044B \u043F\u0435\u0440\u0435\u043A\u043B\u044E\u0447\u0438\u0442\u044C\u0441\u044F \u043C\u0435\u0436\u0434\u0443 \u043F\u043E\u043B\u044F\u043C\u0438")));
1701
1752
  }
1702
1753
  if (step === "tg-userbot-phone") {
1703
1754
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "\u0442\u0435\u043B\u0435\u0444\u043E\u043D \u0432 \u043C\u0435\u0436\u0434\u0443\u043D\u0430\u0440\u043E\u0434\u043D\u043E\u043C \u0444\u043E\u0440\u043C\u0430\u0442\u0435 (+7\u2026)" }), /* @__PURE__ */ React.createElement(Bar, { step: 1, total: 9 }), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, "Phone: "), /* @__PURE__ */ React.createElement(TextInput, { value: phone, onChange: setPhone, onSubmit: async () => {
1704
- setStep("tg-userbot-code");
1705
- setGenStatus("\u043E\u0442\u043F\u0440\u0430\u0432\u043B\u044F\u0435\u043C \u043A\u043E\u0434\u2026");
1706
- try {
1707
- const sess = await userbotLogin({
1708
- apiId: Number(apiId),
1709
- apiHash,
1710
- phone,
1711
- promptCode: () => new Promise((res) => setCodeResolver(() => res)),
1712
- promptPassword: () => new Promise((res) => setPassResolver(() => res))
1713
- });
1714
- setSessionString(sess);
1715
- setStep("api-preset");
1716
- } catch (e) {
1717
- setError(e.message);
1718
- setStep("tg-userbot-phone");
1755
+ setError(null);
1756
+ if (useOwnerCreds) {
1757
+ setGenStatus("\u043E\u0442\u043F\u0440\u0430\u0432\u043B\u044F\u0435\u043C \u043A\u043E\u0434 \u0447\u0435\u0440\u0435\u0437 \u043F\u0440\u043E\u043A\u0441\u0438\u2026");
1758
+ setStep("tg-userbot-code");
1759
+ try {
1760
+ const result = await remoteSendCode(phone);
1761
+ setLoginToken(result.loginToken);
1762
+ } catch (e) {
1763
+ setError(e.message);
1764
+ setStep("tg-userbot-phone");
1765
+ }
1766
+ } else {
1767
+ setStep("tg-userbot-code");
1768
+ setGenStatus("\u043E\u0442\u043F\u0440\u0430\u0432\u043B\u044F\u0435\u043C \u043A\u043E\u0434\u2026");
1769
+ try {
1770
+ const sess = await userbotLogin({
1771
+ apiId: Number(apiId),
1772
+ apiHash,
1773
+ phone,
1774
+ promptCode: () => new Promise((res) => setCodeResolver(() => res)),
1775
+ promptPassword: () => new Promise((res) => setPassResolver(() => res))
1776
+ });
1777
+ setSessionString(sess);
1778
+ setStep("api-preset");
1779
+ } catch (e) {
1780
+ setError(e.message);
1781
+ setStep("tg-userbot-phone");
1782
+ }
1719
1783
  }
1720
1784
  } })), error && /* @__PURE__ */ React.createElement(Text, { color: "red" }, error));
1721
1785
  }
1722
1786
  if (step === "tg-userbot-code") {
1723
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "\u043A\u043E\u0434 \u0438\u0437 Telegram" }), /* @__PURE__ */ React.createElement(Bar, { step: 1, total: 9 }), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, "Code: "), /* @__PURE__ */ React.createElement(TextInput, { value: code, onChange: setCode, onSubmit: () => {
1724
- codeResolver?.(code);
1725
- setStep("tg-userbot-pass");
1726
- } })));
1787
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "\u043A\u043E\u0434 \u0438\u0437 Telegram" }), /* @__PURE__ */ React.createElement(Bar, { step: 1, total: 9 }), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, "Code: "), /* @__PURE__ */ React.createElement(TextInput, { value: code, onChange: setCode, onSubmit: async () => {
1788
+ if (useOwnerCreds) {
1789
+ if (!loginToken) {
1790
+ setError("\u0435\u0449\u0451 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u044F\u0435\u043C \u043A\u043E\u0434, \u043F\u043E\u0434\u043E\u0436\u0434\u0438\u2026");
1791
+ return;
1792
+ }
1793
+ setError(null);
1794
+ try {
1795
+ const result = await remoteVerifyCode(loginToken, code);
1796
+ if (isNeeds2FA(result)) {
1797
+ setStep("tg-userbot-pass");
1798
+ } else {
1799
+ setApiId(String(result.apiId));
1800
+ setApiHash(result.apiHash);
1801
+ setSessionString(result.sessionString);
1802
+ setStep("api-preset");
1803
+ }
1804
+ } catch (e) {
1805
+ setError(e.message);
1806
+ setStep("tg-userbot-phone");
1807
+ }
1808
+ } else {
1809
+ codeResolver?.(code);
1810
+ setStep("tg-userbot-pass");
1811
+ }
1812
+ } })), error && /* @__PURE__ */ React.createElement(Text, { color: "red" }, error));
1727
1813
  }
1728
1814
  if (step === "tg-userbot-pass") {
1729
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "2FA \u043F\u0430\u0440\u043E\u043B\u044C (\u0435\u0441\u043B\u0438 \u0435\u0441\u0442\u044C, \u0438\u043D\u0430\u0447\u0435 Enter)" }), /* @__PURE__ */ React.createElement(Bar, { step: 1, total: 9 }), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, "2FA: "), /* @__PURE__ */ React.createElement(TextInput, { value: pass2fa, onChange: setPass2fa, mask: "\u2022", onSubmit: () => {
1730
- passResolver?.(pass2fa);
1731
- } })), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "\u0432\u0445\u043E\u0434\u0438\u043C \u0432 \u0430\u043A\u043A\u0430\u0443\u043D\u0442\u2026"));
1815
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "2FA \u043F\u0430\u0440\u043E\u043B\u044C (\u0435\u0441\u043B\u0438 \u0435\u0441\u0442\u044C, \u0438\u043D\u0430\u0447\u0435 Enter)" }), /* @__PURE__ */ React.createElement(Bar, { step: 1, total: 9 }), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, "2FA: "), /* @__PURE__ */ React.createElement(TextInput, { value: pass2fa, onChange: setPass2fa, mask: "\u2022", onSubmit: async () => {
1816
+ if (useOwnerCreds) {
1817
+ setError(null);
1818
+ try {
1819
+ const result = await remoteVerifyPassword(loginToken, pass2fa);
1820
+ setApiId(String(result.apiId));
1821
+ setApiHash(result.apiHash);
1822
+ setSessionString(result.sessionString);
1823
+ setStep("api-preset");
1824
+ } catch (e) {
1825
+ setError(e.message);
1826
+ setStep("tg-userbot-phone");
1827
+ }
1828
+ } else {
1829
+ passResolver?.(pass2fa);
1830
+ }
1831
+ } })), error && /* @__PURE__ */ React.createElement(Text, { color: "red" }, error), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "\u0432\u0445\u043E\u0434\u0438\u043C \u0432 \u0430\u043A\u043A\u0430\u0443\u043D\u0442\u2026"));
1732
1832
  }
1733
1833
  if (step === "api-preset") {
1734
1834
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React.createElement(Header, { sub: "\u0432\u044B\u0431\u0435\u0440\u0438 API \u043F\u0440\u043E\u0432\u0430\u0439\u0434\u0435\u0440\u0430" }), /* @__PURE__ */ React.createElement(Bar, { step: 2, total: 9 }), /* @__PURE__ */ React.createElement(Box, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React.createElement(
@@ -5457,7 +5557,8 @@ var HELP = `
5457
5557
  girl-agent \u2014 AI girl for Telegram
5458
5558
 
5459
5559
  usage:
5460
- npx girl-agent # \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C TUI \u0432\u0438\u0437\u0430\u0440\u0434
5560
+ npx girl-agent # \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C TUI \u0432\u0438\u0437\u0430\u0440\u0434 (\u0438\u043B\u0438 \u0430\u0432\u0442\u043E\u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0435\u0441\u043B\u0438 1 \u043F\u0440\u043E\u0444\u0438\u043B\u044C)
5561
+ npx girl-agent --new # \u043F\u0440\u0438\u043D\u0443\u0434\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0432\u0438\u0437\u0430\u0440\u0434 \u0434\u043B\u044F \u043D\u043E\u0432\u043E\u0433\u043E \u043F\u0440\u043E\u0444\u0438\u043B\u044F
5461
5562
  npx girl-agent --profile=<slug> # \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u0433\u043E\u0442\u043E\u0432\u044B\u0439 \u043F\u0440\u043E\u0444\u0438\u043B\u044C
5462
5563
  npx girl-agent --reset --profile=<slug>
5463
5564
  npx girl-agent <flags> # \u043F\u0440\u043E\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u0432\u0438\u0437\u0430\u0440\u0434 \u0441 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u0430\u043C\u0438
@@ -5485,6 +5586,7 @@ required flags \u0434\u043B\u044F headless setup (--name --age --stage --api-pre
5485
5586
  --tz=<value> IANA "Europe/Moscow" / "GMT+3" / "+3" / "\u041A\u0438\u0435\u0432" \u2014 \u043F\u043E\u0438\u0441\u043A
5486
5587
  --stage=<id> met-irl-got-tg|tg-given-cold|tg-given-warming|convinced|first-date-done|dating-early|dating-stable|long-term
5487
5588
  --mcp=exa:KEY \u043C\u043E\u0436\u043D\u043E \u043D\u0435\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0440\u0430\u0437
5589
+ --new \u043F\u0440\u0438\u043D\u0443\u0434\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0432\u0438\u0437\u0430\u0440\u0434 \u0434\u043B\u044F \u043D\u043E\u0432\u043E\u0433\u043E \u043F\u0440\u043E\u0444\u0438\u043B\u044F
5488
5590
  --list \u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u0440\u043E\u0444\u0438\u043B\u0438
5489
5591
  --help
5490
5592
 
@@ -5518,7 +5620,7 @@ async function main() {
5518
5620
  "life-sharing",
5519
5621
  "privacy"
5520
5622
  ],
5521
- boolean: ["help", "list", "reset"],
5623
+ boolean: ["help", "list", "reset", "new"],
5522
5624
  alias: { h: "help" }
5523
5625
  });
5524
5626
  if (argv.help) {
@@ -5571,7 +5673,7 @@ ${profiles.join("\n")}
5571
5673
  await runRuntime(cfg);
5572
5674
  return;
5573
5675
  }
5574
- if (!argv.profile && !haveEnoughForFlags) {
5676
+ if (!argv.new && !argv.profile && !haveEnoughForFlags) {
5575
5677
  const profiles = await listProfiles();
5576
5678
  if (profiles.length === 1) {
5577
5679
  const cfg = await readConfig(profiles[0]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thesashadev/girl-agent",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Telegram AI persona engine with memory, schedule, relationship state and MTProto userbot mode.",
5
5
  "type": "module",
6
6
  "bin": {