Обновить
64K+

TypeScript *

Cтрого типизированная надстройка для JavaScript

31,9
Рейтинг
Сначала показывать
Порог рейтинга

В команде DeepSeek выпустили dsh‑superagent — прототип суперагента для работы с GitHub. Решение запускает множество ИИ‑агентов для работы с площадкой, GitHub Issues, пул‑реквестами и другими задачами:

  • минимум внимания пользователя и максимум автономности. Агенты действуют по заранее заданным правилам и скриптам, не отвлекая пользователя без реальной необходимости.

  • ИИ умеют следить за событиями GitHub и сообщениями в Feishu.

  • решение создаёт отдельную рабочую сессию и каталог для каждый новой задачи.

  • работает с кодом и открывает пул‑реквесты.

  • принимает задачи от авторизованных участников команды.

  • в веб‑панели можно отслеживать задачи, которые требуют участия человека.

Теги:
+2
Комментарии0

Таймер работы и отдыха кажется простой задачей, пока не начинаешь хранить его состояние. Я сделал для себя Android-приложение на React Native + Expo и TypeScript. Оно делит рабочий день, например с 9:00 до 18:00, на отрезки работы и отдыха и напоминает о перерывах. Режимов пять: настройка, ожидание начала дня, работа, отдых и окончание дня. На его примере покажу три способа описания состояния, их сильные и слабые стороны. Полный код — на GitHub.

1. Флаги

const [isRunning, setIsRunning] = useState(false);
const [isResting, setIsResting] = useState(false);
const [isFinished, setIsFinished] = useState(false);
  • Три флага дают 8 комбинаций, половина из которых не имеет смысла. Что значит isRunning и isResting одновременно?

  • Правила переходов размазаны по обработчикам: уходя на отдых, нужно не забыть сбросить isRunning.

  • Экран выбирается цепочкой if, и спорную комбинацию решает порядок проверок.

2. Конечный автомат на поле status

type TState = {
  status: 'setup' | 'pending' | 'work' | 'rest' | 'finished';
  dayEndsAt?: number;
  restStartedAt?: number;
  restType?: 'short' | 'long';
};

function reduce(state: TState, event: TEvent): TState {
  switch (state.status) {
    // case 'setup': ... case 'finished': ...
    default: {
      const _exhaustive: never = state.status;
      return state;
    }
  }
}
  • Все режимы перечислены в типе: опечатку 'wrok' или режим, которого нет в списке, компилятор не пропустит.

  • Проверка never в default: если добавить в тип новый режим и забыть обработать его в редьюсере, проект не соберётся.

  • Переходы собраны в одном месте, а всё состояние — один объект, который легко сохранить и восстановить после выгрузки приложения.

Но данные всех режимов лежат в этом объекте необязательными полями.

  • Внутри case 'rest' вид отдыха всё равно может быть undefined, хотя у отдыха он обязан быть всегда, и код обрастает ! и ?..

  • Компилятор пропустит { status: 'work', restType: 'long' }, хотя у работы нет вида отдыха: данные никак не привязаны к режиму.

3. Конечный автомат + размеченное объединение

type TSetup = { state: 'setup' };

type TWork = {
  state: 'work';
  dayEndsAt: number;
  workStartedAt: number;
};

type TRest = {
  state: 'rest';
  dayEndsAt: number;
  restStartedAt: number;
  restType: 'short' | 'long';
};

// TPending и TFinished — аналогично
type TSnapshot = TSetup | TPending | TWork | TRest | TFinished;

Каждый режим описан своим типом со своими полями и общей меткой state. В настройке нет ни конца дня, ни отдыха, а restType и restStartedAt есть только у отдыха.

  • После проверки state TypeScript точно знает, какие поля доступны, и ! с ?. не нужны.

  • «Отдых без времени начала» невозможно даже собрать.

  • Если при переходе забыть перенести поле, это будет ошибка компиляции, а не undefined в рантайме.

  • Цена — многословность: каждый переход заново собирает объект со всеми полями нового режима.

Способы применения

  • Флаги подходят, когда они независимы, например, звук и полноэкранный режим в плеере друг другу не мешают.

  • Поля status без объединения хватит, когда у режимов нет собственных данных.

  • Размеченное объединение нужно, когда у каждого режима свои поля.

XState или свой редьюсер

Для пяти плоских режимов хватает своего редьюсера без зависимостей. Если появятся вложенные или параллельные состояния, отложенные переходы или понадобится визуализация, стоит смотреть на XState.

Технически в приложении расширенный конечный автомат (EFSM). Кроме режимов, он хранит переменные: границы дня, начало текущего отрезка и счётчик рабочих отрезков. На переходах у него есть условия (начать работу можно, только если день ещё не закончился), а сами переходы обновляют переменные. Без переменных пришлось бы плодить состояния WORK_1, WORK_2…

Подробнее:

Теги:
+1
Комментарии0

Представлен открытый проект ascii sharks (сделан с помощью ИИ) для построения ASCII-анимации, который позволяет создавать красивые визуальные эффекты для сайтов, отчетов, статей и презентаций:

  • на выбор 10 стилей и 14 пресетов;

  • можно выбрать цветовую палитру, фон, яркость и еще несколько параметров;

  • готовые анимации можно экспортировать в JPEG, WebP или MP4 в качестве 720р, 1080р или 4К;

  • работает полностью локально и прямо в браузере.

Теги:
+4
Комментарии0

🏦 Портфель альткоины/золото с автоматической балансировкой

Идея следующая: когда растет Bitcoin, растут альты. Золото растет независимо от Bitcoin.

Исходя от дней роста Bitcoin подряд, смещать распределение портфеля из золота в криптовалюты. Криптовалюты покупать в равной доле независимо от объема торгов, так как все коррелируют с биткоином. При этом не держать в USDT ничего совсем, чтобы избежать инфляции

Закрытие кассы и ребалансировку делаем раз в неделю

import {
  addLauncherSchema,
  addStrategySchema,
  Cache,
  getCandles,
  listenDoneBacktest,
  Position,
  setConfig,
} from "backtest-kit";

setConfig({
  CC_MAX_STOPLOSS_DISTANCE_PERCENT: 100, // иначе валидатор не пропустит технический стоп -50%
});

// Депозит делится поровну между тикерами корзины; доля депозита вне корзины паркуется в золото
const DEPOSIT_USD = 1000;
const PARKING_SYMBOL = "PAXGUSDT";

// Позиция живёт ровно неделю и закрывается по времени; перезаход на первом тике после закрытия
const HOLD_MINUTES = 7 * 24 * 60;

// Трендовый гейт по BTC: доля окон 20..45 дней с положительной доходностью BTC. Это экспозиция
// корзины от 0 до 1; остаток уходит в PARKING_SYMBOL. Ансамбль окон вместо одного N: одиночные
// окна за пределами 25..45 дней заметно хуже, внутри плато результат от выбора N не зависит.
const GATE_SYMBOL = "BTCUSDT";
const GATE_WINDOWS_DAYS = [20, 25, 30, 35, 40, 45];

// Технические уровни: за неделю на споте без плеча недостижимы, штатный выход только по времени
const STOP_LOSS_PERCENT = 50;
const TAKE_PROFIT_PERCENT = 500;

// BASKET:BEGIN
// Сентябрь 2020: топ-20 USDT-пар спота Binance по обороту за август 2020 (известен до начала месяца),
// листинг не моложе 90 дней, без стейблкоинов, плечевых токенов и обёрток BTC/ETH.
const BASKET = [
  "BTCUSDT",
  "ETHUSDT",
  "LINKUSDT",
  "XRPUSDT",
  "BNBUSDT",
  "EOSUSDT",
  "LTCUSDT",
  "TRXUSDT",
  "BCHUSDT",
  "BANDUSDT",
  "OMGUSDT",
  "XTZUSDT",
  "ADAUSDT",
  "ATOMUSDT",
  "VETUSDT",
  "LENDUSDT",
  "ZECUSDT",
  "WAVESUSDT",
  "QTUMUSDT",
  "NEOUSDT",
];
// BASKET:END

const SYMBOL_LIST = [...BASKET, PARKING_SYMBOL];
const PER_SYMBOL_USD = DEPOSIT_USD / BASKET.length;

// getCandles внутри getSignal обрезан по времени движка: последняя дневная свеча - последний
// закрытый день, заглядывания вперёд нет. Cache.fn с интервалом 1d считает гейт один раз
// в день на все тикеры и сам инвалидируется при переходе движка на следующий день.
const getGate = Cache.fn(async (): Promise<number> => {
  const candles = await getCandles(GATE_SYMBOL, "1d", Math.max(...GATE_WINDOWS_DAYS) + 1);
  const closes = candles.map(({ close }) => close);
  const last = closes[closes.length - 1];
  const up = GATE_WINDOWS_DAYS.filter((days) => last > closes[closes.length - 1 - days]).length;
  return up / GATE_WINDOWS_DAYS.length;
}, { interval: "1d" });

addStrategySchema({
  strategyName: "index_fund",
  interval: "1h",
  getSignal: async (symbol, when, currentPrice) => {

    const gate = await getGate();

    const cost = symbol === PARKING_SYMBOL
      ? DEPOSIT_USD * (1 - gate)
      : PER_SYMBOL_USD * gate;

    // cost: 0 движок молча заменяет на CC_POSITION_ENTRY_COST, поэтому нулевая доля - это отсутствие сигнала
    if (cost < 1) {
      return null;
    }

    return {
      id: `${symbol.toLowerCase()}-${when.toISOString().slice(0, 10)}`,
      symbol,
      ...Position.bracket({
        position: "long",
        currentPrice,
        percentStopLoss: STOP_LOSS_PERCENT,
        percentTakeProfit: TAKE_PROFIT_PERCENT,
      }),
      cost: Math.round(cost * 100) / 100,
      minuteEstimatedTime: HOLD_MINUTES,
      payload: { gate, weight: cost / DEPOSIT_USD, basketSize: BASKET.length },
      note: `${symbol} gate=${gate.toFixed(2)} cost=$${cost.toFixed(2)}`,
    };
  },
});

addLauncherSchema({
  launcherName: "main_launcher",
  backtest: true,
  symbolList: SYMBOL_LIST,
  cache: false,
})
Теги:
+3
Комментарии3

Представлен открытый проект Doory (бесплатная альтернатива Canva). Это полноценный графический редактор, работающий прямо в браузере.

«Создавайте плакаты, публикации для соцсетей, сторис, слайды, приглашения, резюме, миниатюры и визитки: начинайте с шаблона или чистого листа, редактируйте любые элементы и экспортируйте результат в форматах PNG, JPG, SVG, PDF, MP4 или GIF. Все функции бесплатны, для начала работы не требуется регистрация, а сам сервис можно развернуть на собственном сервере.

Doory против Canva: Canva — отличный продукт. Doory создан для тех, кому нужен аналогичный инструмент, но бесплатный, с открытым исходным кодом и возможностью полного контроля над ним», — пояснили в команде проекта.

Теги:
+3
Комментарии0

Вышел мод для Minecraft под названием AgentCraft, где ИИ‑агенты играют роль персонажей пользовательской IT‑компании:

  • за каждого сотрудника отвечает отдельный ИИ‑агент;

  • у каждого ИИ‑сотрудника есть свой рабочий стол с ПК, имя и подключение к сервисам;

  • ИИ‑сотрудники пишут реальный код, а пользователь следит за ними и раздаёт указания;

  • когда у ИИ‑агентов возникает вопрос, он реально бежит к пользователю в игре и задаёт его;

  • код от сотрудников готов к принятию в работу только тогда, когда пользователь лично ставит подпись под каждой фичей;

  • ИИ‑сотрудники пишут код даже тогда, когда пользователь выходит из игры.

Теги:
0
Комментарии0

Представлен клон MS Word — открытый проект под названием EdenText для работы с docx‑ и dot‑документами прямо в браузере. Возможности проекта:

  • автоматическая нумерация, колонтитулы, оглавление, сноски, поля и прочее.

  • можно устанавливать стили абзацев, таблиц и других элементов.

  • возможности по работе с таблицами и даже формулы как в Excel.

  • вставка изображений и подписей к ним.

  • знает русский язык и правила орфографии и грамматики.

  • работает без интернета, без регистрации и без лицензионных ключей.

Теги:
Всего голосов 3: ↑3 и ↓0+5
Комментарии0

pear-crypt: клиентское шифрование

pear-crypt — небольшая TypeScript-библиотека, которая шифрует на клиенте и больше ничего не делает. На входе — пароль, PIN или Recovery Code, на выходе — ciphertext, который можно положить хоть в S3, хоть в Postgres. Пароль в этот blob не зашит.

Лицензия MIT. Из зависимостей только hash-wasm: нативного Argon2id в браузере нет. AES-256-GCM и HKDF-SHA256 берутся из Web Crypto, без велосипедостроения.

Почему бы не собирать самому?

Типичный сценарий: сгенерить мастер-ключ, обернуть его паролем, тем же ключом зашифровать файл и отдельно мету. Если каждый раз клеить это из crypto.subtle, через год уже не вспомнить, был ли AAD, какой длины nonce и куда делась salt.

Здесь wire-format зашит в спеке и в тестовых векторах. Поменять раскладку байтов «чуть-чуть» нельзя: старый ciphertext просто перестанет открываться.

Под капотом

Мастер-ключ — 32 случайных байта. В открытом виде наружу не светится: только внутри AES-GCM-обёртки. Ключ обёртки получается из секрета через Argon2id: 32 МиБ памяти, два прохода, без раскладки на несколько ядер. Параметры KDF лежат в JSON рядом с nonce и ciphertext, чтобы было видно, чем именно заворачивали.

Дальше HKDF с пустой солью режет мастер-ключ на домены. В info зашито, для чего ключ: файл или метаданные. Строка вида pear-keep-file:{uid} — это и есть domain separation. Файл и его имя одним ключом не вскрываются: это разные info.

Сам файл — кадр версия | nonce 12 байт | ciphertext и GCM-тег. AAD pear-keep-file:{uid}:{bindAt} привязывает blob к идентификатору и поколению содержимого. Подменили uid или bindAt — тег не сойдётся, расшифровки не будет.

Метаданные — тот же кадр, другой ключ и JSON внутри: подпись, комментарий, время, etc. Recovery Code — 25 символов из алфавита без сомнительных похожих, группами по пять. Им заворачивается тот же мастер-ключ, но отдельно от пароля: пароль забыл — ищи бумажку с кодом.

Как проверяется, что байты не разъехались

В репозитории лежат docs/crypto/SPEC.md и JSON с векторами. Тесты бьют не только в прямую «зашифровал и тут же расшифровал», но и в зафиксированный ciphertext. Покрытие держится выше 90%. Поменяли src/ — пересобрали векторы через npm run export:vectors и закоммитили вместе с кодом. Иначе спецификация и реализация тихо разъедутся.

Чего в комплекте нет

Библиотека не решает, куда класть ciphertext, как устроен логин и когда блокировать сессию. Длину PIN тоже не проверяет. И кофе не варит.

Ошибки — PearKeepCryptoError с машинным кодом: wrongPassword, cannotDecryptMetadata и дальше по списку. Человеческого текста ошибок нет и не будет. Как и i18n.

Итого

Обернуть мастер-ключ, зашифровать контент и мету и не таскать раскладку байтов в голове — вот и весь контракт. Спека, векторы и код смотрят в одну сторону: сдвинули кадр, тесты покраснеют раньше, чем это заметит пользователь. Куда класть готовый ciphertext и как пускать человека внутрь — уже забота приложения.

Теги:
Всего голосов 3: ↑3 и ↓0+5
Комментарии0

Представлен открытый проект NextSteamGame, который помогает выдавать рекомендации по играм в Steam. В отличие от алгоритмов Valve, в этом проекте считываются не только пересечения предпочтений других игроков, а и метаданные каждого тайтла. Специальная нейросеть разбирает проект на набор механик и жанров, после чего ищет совпадения в других играх.

Теги:
Всего голосов 2: ↑2 и ↓0+4
Комментарии0

🤔 Как не терять requestId в логах не пробрасывая его через параметры методов?

Классическая проблема NodeJS разработки: логи не читаемы. При дебаге когда пользователь один, разобрать что происходит ещё можно. Но после запуска в прод в логах сборная солянка из запросов и восстановить трейс вызова композиции методов нельзя

import { scoped } from "di-scoped";

export interface IRequestContext {
  userId: string;
  requestId: string;
  serviceName: "mobile" | "desktop";
  version: number;
}

export const RequestContextService = scoped(
  class {
    constructor(readonly context: IRequestContext) {}
  }
);

export type TRequestContextService = InstanceType<
  typeof RequestContextService
>;

export default RequestContextService;

Согласно MVC, делается два слоя: View и Controller. На уровне view кладем requestId в контекст исполнения через RequestContextService.runInContext

import { inject } from "di-kit";

export class SocketViewService {
  readonly loggerService = inject<LoggerService>(TYPES.loggerService);
  readonly socketControllerService = inject<SocketControllerService>(TYPES.socketControllerService);

  public sendNewOrder = async (
    request: TRequest<{ room: string; orderId: string }>,
  ): Promise<TResponse<SendNewOrder>> => {
    this.loggerService.log("socketViewService sendNewOrder", { request });
    try {
      const data = await RequestContextService.runInContext(
//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        async () =>
          await this.socketControllerService.sendNewOrder(request.data),
        request,
      );
      return { status: "ok", serviceName: request.serviceName, version: request.version, userId: request.userId, requestId: request.requestId, data };
    } catch (error: any) {
      this.loggerService.log("socketViewService sendNewOrder error", { request, error: errorData(error) });
      return { status: "error", error: VerificationError.getErrorMessage(error), errorCode: VerificationError.getErrorCode(error), serviceName: request.serviceName, version: request.version, userId: request.userId, requestId: request.requestId };
    }
  };
}

Voila! Во всех вложенных сервисах к записи в лог будет приложен идентификатор requestId. Дополнительно, этот код позволяет сериализовать ошибки так, чтобы передавать их по шине gRPC

import { inject } from "di-kit";
import { createLogger } from 'pinolog';

const logger = createLogger("socket.log");

export class LoggerService {

  readonly requestContextService = inject<TRequestContextService>(TYPES.requestContextService);

  private get context() {
    if (RequestContextService.hasContext()) {
      // в лог - только конверт IRequestContext; scoped-контекст. но дебаггеру виден весь запрос
      const { serviceName, version, userId, requestId } = this.contextService.context;
      return { serviceName, version, userId, requestId };
    }
    return {};
  }

  public log = (topic: string, ...args: any[]) => {
    logger.log(topic, ...args, this.context);
  }

}
Теги:
Всего голосов 4: ↑4 и ↓0+4
Комментарии0

🤡 Новый фреймворк на NodeJS

Это не draft, а работающий код из прода. Посмотрите код сервиса, код http контроллера и код декларации

Шутки шутками, а существующие реализации DI на ноде либо перегружены, либо используют декораторы, для которых нет единого стандарта у старого и нового кода.

import { provide, inject } from "di-kit";

export class WalkerLogicPublicService {

  private readonly loggerService = inject<LoggerService>("loggerService");

  ...

}

...

provide("loggerService", () => new LoggerService());

Вот почему нельзя просто вот так? Никаких минусов нет, выносите типы в enum, создавайте изолированные пространства имен.

import { createActivator } from "di-kit";

export const { init, inject, provide } = createActivator("separate-scope");
Теги:
Всего голосов 6: ↑6 и ↓0+8
Комментарии0

Представлен открытый проект Spotify Portal AI Plugins. Это решение от инженеров Spotify, которое экономит до 90% ресурсов ИИ-агентов:

  • перенаправляет шаблонные задачи на более дешёвых агентов и оставляет Claude только приоритетные дела;

  • bulk‑reader разбирает многострочный код, Gemini 2.5 Flash внутри читает файлы на тысячи строк и отдаёт Claude саммари;

  • code‑writer генерит рутинный, проверенный и предсказуемый код, пишет тексты, конфиги, type stubs, boilerplate и другие переиспользуемые части;

  • Claude забирает себе только самые важные и реально сложные задачи, где нужен мощный ризонинг — фикс багов, проработка архитектуры и внесение сложных правок.

Теги:
Всего голосов 3: ↑3 и ↓0+7
Комментарии0

Представлен открытый проект Phone Farm iOS - TikTok-ферма на устройствах с iOS. Подключаем iPhone к Mac, регистрируем в панели и управляем прямо из браузера: можно смотреть экран в реальном времени, тапать, свайпать и запускать автоматизацию TikTok. Встроенный планировщик публикует посты и слайд-шоу по расписанию, а очередь и история запусков хранятся в PostgreSQL. Проект работает без джейлбрейка и полностью локально.

Теги:
Всего голосов 3: ↑1 и ↓2+1
Комментарии0

Ближайшие события

Анализаторы кода легко и быстро умеют находить множество ошибок, не очевидных с первого взгляда. Попробуйте посоревноваться с PVS-Studio в прозорливости!

Мы сделали новый квиз «Найдите ошибки в JS & TS коде»!

Вас ждут 10 фрагментов кода, в которых наш анализатор нашёл ошибки. Все они взяты из известных Open Source проектов. Ваша задача — успеть найти ошибку за 60 секунд (не переживайте, фрагменты небольшие).

Время посоревноваться с анализатором! А потом можно и его проверить 😉

Переходите по ссылке!

Теги:
Всего голосов 4: ↑3 и ↓1+4
Комментарии6

Представлен открытый проект ИИ‑учёного OmniScientist, который сам пишет статьи, составляет библиографию, таблицы и рисует схемы для любых исследователей:

  • анализирует любые файлы: изображения, видео, схемы, таблицы, документы, формулы и даже аудио.

  • выдвигает гипотезы как настоящая команда учёных.

  • проверяет информацию до последней запятой, чтобы не было ни одной выдумки или неточности;

  • строит графики, таблицы и схемы;

  • собирает результат в PDF и отдаёт в удобном формате;

  • знает русский язык и ориентируется в культурном контексте;

  • может подключаться к различным ИИ‑агентам;

  • работает на Windows, macOS и Linux.

Теги:
Всего голосов 9: ↑9 и ↓0+11
Комментарии4

Чуть лучше код

Короче, котаны, сейчас открою вам секрет, который бустанет вас нереально по качеству кода. Люди давние в профессии интуитивно чувствуют его, даже если никогда не слышали о нем. Самые признанные олды выступают на конференциях, как вы догадались, о мега секрете. Итак, барабанная дробь, хотя еще секунду, почему об этом хочется написать министатью, потому что иногда (а на деле слишком часто) стандартную задачу сходить за репортом и положить в базу нельзя переиспользовать и нельзя легко затестить. Речь пойдет о идемпотентности.

Что дано:

  1. поход в базу (начальные данные)

  2. поход по апи за списком (указателей или стримов)

  3. для каждого (репорта): поход по апи за данными и сохранение в базу

Легко пишем (неправильный) скрипт, кладем в крон и профит? Почти. Через пару лет в дев базе 2kk записей и селект ну очень долго ждать. Порядочные пацаны (и девушки) пишут тесты на sqlite, и неявно имплeмeнтируют идемпотентность, создавая и дропая базу данных на каждую пачку тестов. Sql insert не является идемпотентной операцией, но с пустой базой прокатывает.

В чем, собственно, проблема? Идемпотентность (от лат. idem — тот же самый и potens — сильный, буквально — равносильность) — свойство объекта или операции при повторном применении операции к объекту давать тот же результат, что и при первом. Так вот, sql insert и app_call(date_now) не обладают идемпотентностью.

Что делать? Как и в примере выше, создаем искусственную идемпотентность (да, этот термин повторится еще много раз), вынося в контекст доступ к базе, апи вызовы и т.д. (трансформация csv). Короче, контекст может быть пустой и код должен корректно работать. Или в контексте будет передан доступ к базе, но без апи вызовов или трансформации csv. И опять код должен работать корректно.

Чем заменить? Дефолтными значениями, как ни странно, дефолтные значения идемпотентны, если это, например, список и словарь. Удачного кодинга :)

P.S.: Хотел приложить примеры кода, но кол-во строк оказалось больше размера статьи :)

Теги:
Всего голосов 6: ↑1 и ↓5-2
Комментарии3

Делаем профессиональное ревью кода и не пропускаем ни одного бага — вышел открытый инструмент Rеjudge, который проверяет код с помощью трех ИИ-агентов, а затем ИИ-судья выносит вердикт в готовый отчёт:

  • каждая ИИ-модель проверяет один и тот же запрос, разбирая его в изолированном контексте. При этом ни одна модель не видит, что делают другие;

  • ИИ-судья затем проверяет все три ответа, задаёт уточняющие вопросы там, где расходятся независимые проверки;

  • затем судья выдает один готовый отчет, где указывает все риски, баги и уязвимости в коде.

Теги:
Всего голосов 1: ↑1 и ↓0+3
Комментарии1

Представлен открытый проект torlink, который умеет искать и работать с торрентами из проверенных источников. Запускается командой npx torlnk. Одновременно проверяет FitGirl, YTS, The Pirate Bay, 1337x, Nyaa и другие источники, а результаты показывает вместе с размером и числом сидов. Выбранный файл скачивается в фоне, а после завершения автоматически встаёт на раздачу.

«Найти торрент в наши дни — сплошная головная боль. Один сайт — это минное поле из поддельных кнопок загрузки. Другой скрывает настоящую ссылку под всплывающим окном, которое открывает ещё две вкладки. И после всего этого половина результатов — это неработающие сайты с нулевым количеством раздающих. Torlink — это программа для поиска торрентов, которая работает в вашем терминале, не требует никакой настройки и конфигурации. Один поиск проверяет короткий, тщательно отобранный список надёжных источников, и всё, что вы выберете, загрузится прямо на ваш компьютер. Файлы ваши, сохранены в папке загрузок», — пояснил автор проекта.

Теги:
Всего голосов 7: ↑7 и ↓0+11
Комментарии1

Представлен открытый проект repowise — оптимизатор кодовых баз, который экономит токены в кодинге и работает с Claude Code, Cursor, Copilot:

  • не читает каждый файл, а сразу индексирует весь репозиторий;

  • создаёт документацию для каждого файла;

  • строит графы зависимости и анализирует историю Git с слабыми местами;

  • неиспользуемый код и устаревшие зависимости чистит сам;

  • результат: минимальная задокументированная экономия — 36%.

Теги:
Всего голосов 1: ↑1 и ↓0+3
Комментарии0