@axon-assistant/core 2026.8.23 → 2026.8.25

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/README.md CHANGED
@@ -14,10 +14,19 @@ Node 22.5+. Нативных модулей нет, компилятор не н
14
14
 
15
15
  ```bash
16
16
  npm install -g @axon-assistant/core
17
- axon start # слушает 127.0.0.1:8787
17
+ axon start # слушает 127.0.0.1:8787, фоном
18
18
  axon start --host 0.0.0.0 # ещё и для устройств из сети
19
19
  ```
20
20
 
21
+ `--host` — интерфейс, который ядро слушает, а не список разрешённых гостей: по
22
+ умолчанию оно видно только на своей машине, а `0.0.0.0` пускает всех. Адреса, по
23
+ которым ядро видно с других машин, оно печатает само.
24
+
25
+ Ядро уходит в фон само: печатает адрес и код, отдаёт терминал и работает
26
+ дальше — закрытая сессия SSH его не убьёт. Вывод уходит в `axon.log` рядом с
27
+ данными. Под systemd нужен `--foreground`: там фоном процесс держит система.
28
+ Готовый юнит — в [README проекта](https://github.com/bigtaed-sys/axon#установка-ядра).
29
+
21
30
  При первом запуске ядро печатает код для подключения первого устройства и
22
31
  кладёт его в `bootstrap.code` рядом с данными — код сгорает после первого
23
32
  использования.
package/dist/Daemon.d.ts CHANGED
@@ -11,7 +11,17 @@ export interface DaemonOptions {
11
11
  export interface DaemonAddress {
12
12
  host: string;
13
13
  port: number;
14
+ /**
15
+ * Адрес, по которому к ядру действительно можно обратиться.
16
+ *
17
+ * Не то же самое, что `host`: при `--host 0.0.0.0` ядро слушает все
18
+ * интерфейсы, но `http://0.0.0.0:8787` — не адрес, а маска. Обратиться по
19
+ * ней нельзя, а её печатали и складывали в `core.json`, откуда её брали и
20
+ * `axon status`, и десктоп.
21
+ */
14
22
  url: string;
23
+ /** Куда стучаться с других устройств. Пусто, если слушаем только себя. */
24
+ reachable: string[];
15
25
  }
16
26
  /**
17
27
  * Демон: тонкая обвязка вокруг ядра.
@@ -1 +1 @@
1
- {"version":3,"file":"Daemon.d.ts","sourceRoot":"","sources":["../src/Daemon.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAKtD,OAAO,EAML,OAAO,EAER,MAAM,gBAAgB,CAAC;AAKxB,eAAO,MAAM,cAAc,QAC4C,CAAC;AAIxE,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,IAAI,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;GAUG;AACH,qBAAa,MAAM;IAyBL,OAAO,CAAC,QAAQ,CAAC,OAAO;IAxBpC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,QAAQ,CAAgC;IAChD,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,uEAAuE;IACvE,OAAO,CAAC,IAAI,CAA4B;IACxC;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAuC;IACvE,sEAAsE;IACtE,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAqB;gBAEnB,OAAO,GAAE,aAAkB;IAsClD,KAAK,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,aAAa,CAAC;QAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IA+ChF;;;;;;;OAOG;YACW,YAAY;IAmC1B;;;;;OAKG;YACW,WAAW;IAkBzB;;;;;OAKG;IACG,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,EAAE,KAAK,EAAE,MAAM;;;;;;;;;;;;;;;;;IAoC3E,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrC,cAAc;;;;IAOd;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ;IAkBhB,OAAO,CAAC,QAAQ;IAIV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B,IAAI,GAAG,IAAI,MAAM,CAGhB;IAED,4EAA4E;IAC5E,OAAO,CAAC,WAAW;YAWL,SAAS;IAsDvB,OAAO,CAAC,QAAQ;IAiBhB,OAAO,CAAC,SAAS;CA+BlB"}
1
+ {"version":3,"file":"Daemon.d.ts","sourceRoot":"","sources":["../src/Daemon.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAKtD,OAAO,EAML,OAAO,EAER,MAAM,gBAAgB,CAAC;AAKxB,eAAO,MAAM,cAAc,QAC4C,CAAC;AAIxE,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,IAAI,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;OAOG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAoCD;;;;;;;;;;GAUG;AACH,qBAAa,MAAM;IAyBL,OAAO,CAAC,QAAQ,CAAC,OAAO;IAxBpC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,QAAQ,CAAgC;IAChD,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,uEAAuE;IACvE,OAAO,CAAC,IAAI,CAA4B;IACxC;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAuC;IACvE,sEAAsE;IACtE,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAqB;gBAEnB,OAAO,GAAE,aAAkB;IAsClD,KAAK,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,aAAa,CAAC;QAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAoDhF;;;;;;;OAOG;YACW,YAAY;IAmC1B;;;;;OAKG;YACW,WAAW;IAkBzB;;;;;OAKG;IACG,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,EAAE,KAAK,EAAE,MAAM;;;;;;;;;;;;;;;;;IAoC3E,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrC,cAAc;;;;IAOd;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ;IAmBhB,OAAO,CAAC,QAAQ;IAIV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B,IAAI,GAAG,IAAI,MAAM,CAGhB;IAED,4EAA4E;IAC5E,OAAO,CAAC,WAAW;YAWL,SAAS;IAsDvB,OAAO,CAAC,QAAQ;IAiBhB,OAAO,CAAC,SAAS;CA+BlB"}
package/dist/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
+ import { spawn as spawn3 } from "node:child_process";
4
5
  import fs19 from "node:fs";
5
6
  import path19 from "node:path";
6
7
 
@@ -4881,6 +4882,10 @@ var DEFAULT_CATALOG_URL = "https://raw.githubusercontent.com/bigtaed-sys/axon-ca
4881
4882
  var FRESH_FOR_MS = 6 * 60 * 60 * 1e3;
4882
4883
  var TIMEOUT_MS = 8e3;
4883
4884
  var MAX_BYTES = 2 * 1024 * 1024;
4885
+ function catalogUrl(store) {
4886
+ const custom = store.settings.get(CATALOG_URL_SETTING);
4887
+ return custom?.trim() || DEFAULT_CATALOG_URL;
4888
+ }
4884
4889
  var CatalogSource = class {
4885
4890
  store;
4886
4891
  dataDir;
@@ -4918,12 +4923,8 @@ var CatalogSource = class {
4918
4923
  this.memory = result;
4919
4924
  this.fetchedAtMs = Date.now();
4920
4925
  }
4921
- url() {
4922
- const custom = this.store.settings.get(CATALOG_URL_SETTING);
4923
- return custom?.trim() || DEFAULT_CATALOG_URL;
4924
- }
4925
4926
  async download() {
4926
- const url = this.url();
4927
+ const url = catalogUrl(this.store);
4927
4928
  const abort = new AbortController();
4928
4929
  const timer = setTimeout(() => abort.abort(), TIMEOUT_MS);
4929
4930
  try {
@@ -10101,6 +10102,7 @@ axon plugin logs ${id}
10101
10102
  // src/Daemon.ts
10102
10103
  import http from "node:http";
10103
10104
  import fs18 from "node:fs";
10105
+ import os7 from "node:os";
10104
10106
  import path18 from "node:path";
10105
10107
  import { WebSocketServer } from "ws";
10106
10108
 
@@ -11687,8 +11689,26 @@ var WsSession = class {
11687
11689
  };
11688
11690
 
11689
11691
  // src/Daemon.ts
11690
- var DAEMON_VERSION = true ? "2026.8.23-dirty" : "0.0.0-dev";
11692
+ var DAEMON_VERSION = true ? "2026.8.25" : "0.0.0-dev";
11691
11693
  var MAX_UPLOAD_BYTES = 64 * 1024 * 1024;
11694
+ function isWildcard(host) {
11695
+ return host === "0.0.0.0" || host === "::" || host === "";
11696
+ }
11697
+ function asAuthority(host, port) {
11698
+ return host.includes(":") ? `http://[${host}]:${port}` : `http://${host}:${port}`;
11699
+ }
11700
+ function reachableUrls(port) {
11701
+ const found = [];
11702
+ for (const addresses of Object.values(os7.networkInterfaces())) {
11703
+ for (const item of addresses ?? []) {
11704
+ if (item.internal) continue;
11705
+ if (item.address.startsWith("fe80") || item.address.startsWith("169.254.")) continue;
11706
+ found.push({ address: item.address, v4: item.family === "IPv4" });
11707
+ }
11708
+ }
11709
+ found.sort((a, b) => Number(b.v4) - Number(a.v4));
11710
+ return found.map((item) => asAuthority(item.address, port));
11711
+ }
11692
11712
  var Daemon = class {
11693
11713
  constructor(options = {}) {
11694
11714
  this.options = options;
@@ -11758,7 +11778,12 @@ var Daemon = class {
11758
11778
  });
11759
11779
  const actual = this.server.address();
11760
11780
  const boundPort = typeof actual === "object" && actual ? actual.port : port;
11761
- this.address = { host, port: boundPort, url: `http://${host}:${boundPort}` };
11781
+ this.address = {
11782
+ host,
11783
+ port: boundPort,
11784
+ url: isWildcard(host) ? `http://127.0.0.1:${boundPort}` : asAuthority(host, boundPort),
11785
+ reachable: isWildcard(host) ? reachableUrls(boundPort) : []
11786
+ };
11762
11787
  const bootstrapCode = this.pairing.ensureBootstrapCode();
11763
11788
  this.announce();
11764
11789
  logger.info({ url: this.address.url, coreId: this.runtime.coreId }, "\u0434\u0435\u043C\u043E\u043D \u0441\u043B\u0443\u0448\u0430\u0435\u0442");
@@ -11885,6 +11910,7 @@ var Daemon = class {
11885
11910
  JSON.stringify(
11886
11911
  {
11887
11912
  url: this.address.url,
11913
+ reachable: this.address.reachable,
11888
11914
  pid: process.pid,
11889
11915
  coreId: this.runtime.coreId,
11890
11916
  mode: this.options.mode ?? "standalone",
@@ -12073,6 +12099,12 @@ async function main() {
12073
12099
  case "--help":
12074
12100
  case "-h":
12075
12101
  return usage();
12102
+ // Первое, что набирают после установки, — и первое, что спрашивают, когда
12103
+ // что-то не работает. Отвечать на это списком команд невежливо.
12104
+ case "version":
12105
+ case "--version":
12106
+ case "-v":
12107
+ return console.log(DAEMON_VERSION);
12076
12108
  default:
12077
12109
  console.error(`\u041D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u0430\u044F \u043A\u043E\u043C\u0430\u043D\u0434\u0430: ${command}
12078
12110
  `);
@@ -12085,12 +12117,38 @@ async function start(args) {
12085
12117
  const host = valueOf(args, "--host") ?? process.env["AXON_HOST"] ?? "127.0.0.1";
12086
12118
  const asJson = args.includes("--json");
12087
12119
  const mode = valueOf(args, "--mode") === "embedded" ? "embedded" : "standalone";
12120
+ const running2 = readRecord();
12121
+ if (running2 && await alive(running2.url)) {
12122
+ return fail(`\u042F\u0434\u0440\u043E \u0443\u0436\u0435 \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442: ${running2.url}, pid ${running2.pid}.
12123
+ \u041E\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C: axon stop`);
12124
+ }
12125
+ const foreground = args.includes("--foreground") || args.includes("-f") || mode === "embedded";
12126
+ if (!foreground) return await detach(args);
12088
12127
  const daemon = new Daemon({ host, port, mode });
12089
- const { address, bootstrapCode } = await daemon.start();
12128
+ let started;
12129
+ try {
12130
+ started = await daemon.start();
12131
+ } catch (error) {
12132
+ const code2 = error.code;
12133
+ if (code2 === "EADDRINUSE") {
12134
+ return fail(`\u041F\u043E\u0440\u0442 ${port} \u0437\u0430\u043D\u044F\u0442. \u041C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C, \u044F\u0434\u0440\u043E \u0443\u0436\u0435 \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442: axon status`);
12135
+ }
12136
+ if (code2 === "EADDRNOTAVAIL") {
12137
+ return fail(
12138
+ `\u0410\u0434\u0440\u0435\u0441 ${host} \u043D\u0435 \u043F\u0440\u0438\u043D\u0430\u0434\u043B\u0435\u0436\u0438\u0442 \u044D\u0442\u043E\u0439 \u043C\u0430\u0448\u0438\u043D\u0435.
12139
+ \u0427\u0442\u043E\u0431\u044B \u043F\u0443\u0441\u043A\u0430\u0442\u044C \u0434\u0440\u0443\u0433\u0438\u0435 \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432\u0430, \u0441\u043B\u0443\u0448\u0430\u044E\u0442 \u0432\u0441\u0435 \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044B: axon start --host 0.0.0.0`
12140
+ );
12141
+ }
12142
+ throw error;
12143
+ }
12144
+ const { address, bootstrapCode } = started;
12090
12145
  if (asJson) {
12091
- console.log(JSON.stringify({ ready: true, url: address.url, bootstrapCode }));
12146
+ console.log(
12147
+ JSON.stringify({ ready: true, url: address.url, reachable: address.reachable, bootstrapCode })
12148
+ );
12092
12149
  } else {
12093
12150
  console.log(`Axon \u0441\u043B\u0443\u0448\u0430\u0435\u0442 ${address.url}`);
12151
+ describeReach(address.host, address.reachable);
12094
12152
  }
12095
12153
  if (bootstrapCode && !asJson) {
12096
12154
  console.log("");
@@ -12106,6 +12164,63 @@ async function start(args) {
12106
12164
  process.on("SIGINT", stop2);
12107
12165
  process.on("SIGTERM", stop2);
12108
12166
  }
12167
+ function logPath() {
12168
+ return path19.join(resolveConfig().dataDir, "axon.log");
12169
+ }
12170
+ async function detach(args) {
12171
+ const config = resolveConfig();
12172
+ fs19.mkdirSync(config.dataDir, { recursive: true });
12173
+ const file = logPath();
12174
+ const out = fs19.openSync(file, "a");
12175
+ const since = Date.now();
12176
+ const child = spawn3(process.execPath, [process.argv[1] ?? "", "start", ...args, "--foreground"], {
12177
+ detached: true,
12178
+ stdio: ["ignore", out, out],
12179
+ windowsHide: true
12180
+ });
12181
+ child.unref();
12182
+ fs19.closeSync(out);
12183
+ const record = await waitReady(since);
12184
+ if (!record) {
12185
+ return fail(`\u042F\u0434\u0440\u043E \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u043B\u043E \u0437\u0430 20 \u0441\u0435\u043A\u0443\u043D\u0434. \u0427\u0442\u043E \u043E\u043D\u043E \u043D\u0430\u043F\u0438\u0441\u0430\u043B\u043E \u2014 \u0432 ${file}`);
12186
+ }
12187
+ console.log(`Axon \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u0444\u043E\u043D\u043E\u043C, pid ${record.pid}`);
12188
+ console.log(` ${record.url}`);
12189
+ describeReach("", record.reachable ?? []);
12190
+ console.log(` \u0432\u044B\u0432\u043E\u0434: ${file}`);
12191
+ console.log(" \u043E\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C: axon stop");
12192
+ const codeFile = path19.join(config.dataDir, "bootstrap.code");
12193
+ const code2 = fs19.existsSync(codeFile) ? fs19.readFileSync(codeFile, "utf8").trim() : "";
12194
+ if (code2) {
12195
+ console.log("");
12196
+ console.log(" \u0423\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432 \u043F\u043E\u043A\u0430 \u043D\u0435\u0442. \u041A\u043E\u0434 \u0434\u043B\u044F \u043F\u0435\u0440\u0432\u043E\u0433\u043E \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F:");
12197
+ console.log(` ${code2}`);
12198
+ console.log("");
12199
+ }
12200
+ }
12201
+ async function alive(url) {
12202
+ return await fetch(`${url}/health`).then((r) => r.ok).catch(() => false);
12203
+ }
12204
+ async function waitReady(since) {
12205
+ const deadline = Date.now() + 2e4;
12206
+ while (Date.now() < deadline) {
12207
+ const record = readRecord();
12208
+ if (record && Date.parse(record.startedAt) >= since && await alive(record.url)) {
12209
+ return record;
12210
+ }
12211
+ await new Promise((resolve) => setTimeout(resolve, 300));
12212
+ }
12213
+ return null;
12214
+ }
12215
+ function describeReach(host, reachable) {
12216
+ if (reachable.length > 0) {
12217
+ console.log(` \u0441 \u0434\u0440\u0443\u0433\u0438\u0445 \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432: ${reachable.join(", ")}`);
12218
+ return;
12219
+ }
12220
+ if (host === "127.0.0.1" || host === "localhost") {
12221
+ console.log(" \u0432\u0438\u0434\u043D\u043E \u0442\u043E\u043B\u044C\u043A\u043E \u043D\u0430 \u044D\u0442\u043E\u0439 \u043C\u0430\u0448\u0438\u043D\u0435; \u0434\u043B\u044F \u0434\u0440\u0443\u0433\u0438\u0445 \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432: --host 0.0.0.0");
12222
+ }
12223
+ }
12109
12224
  async function secret(args) {
12110
12225
  const [action, key, value] = args;
12111
12226
  const runtime = createRuntime();
@@ -12142,13 +12257,13 @@ async function secret(args) {
12142
12257
  async function status() {
12143
12258
  const record = readRecord();
12144
12259
  if (!record) return console.log("\u042F\u0434\u0440\u043E \u043D\u0435 \u0437\u0430\u043F\u0443\u0449\u0435\u043D\u043E");
12145
- const alive = await fetch(`${record.url}/health`).then((r) => r.ok).catch(() => false);
12146
- if (!alive) {
12260
+ if (!await alive(record.url)) {
12147
12261
  console.log(`\u042F\u0434\u0440\u043E \u043D\u0435 \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043F\u043E ${record.url} (\u0437\u0430\u043F\u0438\u0441\u044C \u0443\u0441\u0442\u0430\u0440\u0435\u043B\u0430)`);
12148
12262
  return;
12149
12263
  }
12150
12264
  console.log(`\u042F\u0434\u0440\u043E \u043D\u0430 \u0441\u0432\u044F\u0437\u0438: ${record.url}`);
12151
12265
  console.log(` pid ${record.pid}, \u0437\u0430\u043F\u0443\u0449\u0435\u043D\u043E ${new Date(record.startedAt).toLocaleString("ru")}`);
12266
+ describeReach("", record.reachable ?? []);
12152
12267
  }
12153
12268
  function stop() {
12154
12269
  const record = readRecord();
@@ -12341,8 +12456,9 @@ function running(dataDir) {
12341
12456
  function usage() {
12342
12457
  console.log(`Axon \u2014 \u043F\u0435\u0440\u0441\u043E\u043D\u0430\u043B\u044C\u043D\u044B\u0439 AI-\u0430\u0433\u0435\u043D\u0442
12343
12458
 
12344
- axon start [--host 127.0.0.1] [--port 8787] \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u044F\u0434\u0440\u043E
12459
+ axon start [--host 127.0.0.1] [--port 8787] \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u044F\u0434\u0440\u043E (\u0444\u043E\u043D\u043E\u043C)
12345
12460
  --host 0.0.0.0 \u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0434\u043B\u044F \u0434\u0440\u0443\u0433\u0438\u0445 \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432
12461
+ --foreground, -f \u043D\u0435 \u0443\u0445\u043E\u0434\u0438\u0442\u044C \u0432 \u0444\u043E\u043D (systemd, docker)
12346
12462
  axon status \u0437\u0430\u043F\u0443\u0449\u0435\u043D\u043E \u043B\u0438 \u044F\u0434\u0440\u043E \u0438 \u0433\u0434\u0435
12347
12463
  axon stop \u043E\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u044F\u0434\u0440\u043E
12348
12464
  axon secret list \u043A\u0430\u043A\u0438\u0435 \u0441\u0435\u043A\u0440\u0435\u0442\u044B \u0437\u0430\u0434\u0430\u043D\u044B
@@ -12363,6 +12479,8 @@ function usage() {
12363
12479
  axon plugin remove <id> \u0443\u0434\u0430\u043B\u0438\u0442\u044C
12364
12480
  axon plugin logs <id> \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0435 \u0441\u0442\u0440\u043E\u043A\u0438 \u0432\u044B\u0432\u043E\u0434\u0430 \u043F\u043B\u0430\u0433\u0438\u043D\u0430
12365
12481
 
12482
+ axon version \u0432\u0435\u0440\u0441\u0438\u044F \u044F\u0434\u0440\u0430
12483
+
12366
12484
  \u041F\u0430\u043F\u043A\u0430 \u0434\u0430\u043D\u043D\u044B\u0445 \u0437\u0430\u0434\u0430\u0451\u0442\u0441\u044F \u043F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u043E\u0439 AXON_DATA_DIR.`);
12367
12485
  }
12368
12486
  function valueOf(args, flag) {
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // src/Daemon.ts
2
2
  import http from "node:http";
3
3
  import fs16 from "node:fs";
4
+ import os7 from "node:os";
4
5
  import path16 from "node:path";
5
6
  import { WebSocketServer } from "ws";
6
7
 
@@ -4672,6 +4673,10 @@ var DEFAULT_CATALOG_URL = "https://raw.githubusercontent.com/bigtaed-sys/axon-ca
4672
4673
  var FRESH_FOR_MS = 6 * 60 * 60 * 1e3;
4673
4674
  var TIMEOUT_MS = 8e3;
4674
4675
  var MAX_BYTES = 2 * 1024 * 1024;
4676
+ function catalogUrl(store) {
4677
+ const custom = store.settings.get(CATALOG_URL_SETTING);
4678
+ return custom?.trim() || DEFAULT_CATALOG_URL;
4679
+ }
4675
4680
  var CatalogSource = class {
4676
4681
  store;
4677
4682
  dataDir;
@@ -4709,12 +4714,8 @@ var CatalogSource = class {
4709
4714
  this.memory = result;
4710
4715
  this.fetchedAtMs = Date.now();
4711
4716
  }
4712
- url() {
4713
- const custom = this.store.settings.get(CATALOG_URL_SETTING);
4714
- return custom?.trim() || DEFAULT_CATALOG_URL;
4715
- }
4716
4717
  async download() {
4717
- const url = this.url();
4718
+ const url = catalogUrl(this.store);
4718
4719
  const abort = new AbortController();
4719
4720
  const timer = setTimeout(() => abort.abort(), TIMEOUT_MS);
4720
4721
  try {
@@ -11351,8 +11352,26 @@ var WsSession = class {
11351
11352
  };
11352
11353
 
11353
11354
  // src/Daemon.ts
11354
- var DAEMON_VERSION = true ? "2026.8.23-dirty" : "0.0.0-dev";
11355
+ var DAEMON_VERSION = true ? "2026.8.25" : "0.0.0-dev";
11355
11356
  var MAX_UPLOAD_BYTES = 64 * 1024 * 1024;
11357
+ function isWildcard(host) {
11358
+ return host === "0.0.0.0" || host === "::" || host === "";
11359
+ }
11360
+ function asAuthority(host, port) {
11361
+ return host.includes(":") ? `http://[${host}]:${port}` : `http://${host}:${port}`;
11362
+ }
11363
+ function reachableUrls(port) {
11364
+ const found = [];
11365
+ for (const addresses of Object.values(os7.networkInterfaces())) {
11366
+ for (const item of addresses ?? []) {
11367
+ if (item.internal) continue;
11368
+ if (item.address.startsWith("fe80") || item.address.startsWith("169.254.")) continue;
11369
+ found.push({ address: item.address, v4: item.family === "IPv4" });
11370
+ }
11371
+ }
11372
+ found.sort((a, b) => Number(b.v4) - Number(a.v4));
11373
+ return found.map((item) => asAuthority(item.address, port));
11374
+ }
11356
11375
  var Daemon = class {
11357
11376
  constructor(options = {}) {
11358
11377
  this.options = options;
@@ -11422,7 +11441,12 @@ var Daemon = class {
11422
11441
  });
11423
11442
  const actual = this.server.address();
11424
11443
  const boundPort = typeof actual === "object" && actual ? actual.port : port;
11425
- this.address = { host, port: boundPort, url: `http://${host}:${boundPort}` };
11444
+ this.address = {
11445
+ host,
11446
+ port: boundPort,
11447
+ url: isWildcard(host) ? `http://127.0.0.1:${boundPort}` : asAuthority(host, boundPort),
11448
+ reachable: isWildcard(host) ? reachableUrls(boundPort) : []
11449
+ };
11426
11450
  const bootstrapCode = this.pairing.ensureBootstrapCode();
11427
11451
  this.announce();
11428
11452
  logger.info({ url: this.address.url, coreId: this.runtime.coreId }, "\u0434\u0435\u043C\u043E\u043D \u0441\u043B\u0443\u0448\u0430\u0435\u0442");
@@ -11549,6 +11573,7 @@ var Daemon = class {
11549
11573
  JSON.stringify(
11550
11574
  {
11551
11575
  url: this.address.url,
11576
+ reachable: this.address.reachable,
11552
11577
  pid: process.pid,
11553
11578
  coreId: this.runtime.coreId,
11554
11579
  mode: this.options.mode ?? "standalone",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axon-assistant/core",
3
- "version": "2026.8.23",
3
+ "version": "2026.8.25",
4
4
  "comment:version": "Заглушка. Настоящий номер проставляется из git-тега при публикации: см. scripts/release-npm.mjs. Версия, которую правят руками, рано или поздно расходится с тем, что опубликовано.",
5
5
  "description": "Ядро Axon: персональный AI-агент, который живёт на вашей машине",
6
6
  "keywords": [