@smwb/onreel-git-mcp 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -425,6 +425,141 @@ PUT, GitHub — PATCH, SourceCraft не дёргает эндпоинт сост
425
425
  `githubPulls()`, `gitlabPulls()` и `sourcecraftPulls()`. Всё это выходит из субпути `…/tracker` — нового субпути
426
426
  нет (D-001, D-005). За модель отвечают таблицы сопоставления и запись D-005, отказ до запроса — правило R-002.
427
427
 
428
+ ### CI
429
+
430
+ Прогоны CI — необязательный раздел `ci` того же `TrackerDefinition`, на том же подключении, что задачи (D-005):
431
+ возможности `CiCapabilities` плюс фабрика `create(context)` на том же `AdapterContext`. Раздел строят фабрики
432
+ `githubCi()`, `gitlabCi()` и `sourcecraftCi()`; у локального трекера и Jira раздела нет. Адаптер раздела —
433
+ `ciAdapterOf(definition, context)`; у трекера без `ci` это `TrackerError('unsupported', 'Трекер <title> не ведёт CI.')`.
434
+ `CiAdapter` умеет: `listWorkflows`, `listRuns`, `getRun`, `listJobs`, `getJob`, `log`, `trigger`, `rerun`,
435
+ `rerunJob`, `cancel`, `cancelJob`. Каждый возвращённый объект проходит parse своей схемы zod (`ciWorkflowSchema`,
436
+ `ciRunSchema`, `ciJobSchema`, `ciLogSchema`); состояние — категория `CiStatusCategory` (`queued`, `running`,
437
+ `waiting`, `success`, `failed`, `canceled`, `skipped`) плюс сырое имя трекера в `status.name`, событие —
438
+ категория `CiEventCategory` плюс сырое имя. Метод вне возможностей своего трекера — отказ `unsupported`
439
+ **до запроса**.
440
+
441
+ Сопоставление сырых статусов и событий с единой моделью — открытые таблицы, как у задач, чтобы потребитель
442
+ видел, во что именно преводится значение его трекера. Правила для неизвестного: статус → `running` (прогон
443
+ ещё не закончен, и тот, кто ждёт конца, продолжает опрос), законченный прогон GitHub с незнакомым
444
+ `conclusion` → `failed` (незнакомое заключение не бывает зелёным), событие → `other`.
445
+
446
+ GitHub Actions (`GITHUB_RUN_STATUSES` — `status`, пока он не `completed`; `GITHUB_RUN_CONCLUSIONS` —
447
+ `conclusion` при `status: completed`; `GITHUB_RUN_EVENTS` — `event` прогона):
448
+
449
+ - `queued`/`requested`/`pending` → `queued`, `waiting` → `waiting`, `in_progress` → `running`;
450
+ - `success`/`neutral` → `success`, `failure`/`timed_out`/`startup_failure` → `failed`,
451
+ `cancelled`/`stale` → `canceled`, `skipped` → `skipped`, `action_required` → `waiting`;
452
+ - `push` → `push`, `pull_request`/`pull_request_target`/`merge_group` → `pull_request`,
453
+ `workflow_dispatch` → `manual`, `schedule` → `schedule`,
454
+ `repository_dispatch`/`workflow_run`/`workflow_call` → `trigger`.
455
+
456
+ GitLab (`GITLAB_CI_STATUSES` — `status` пайплайна и задания; `GITLAB_PIPELINE_SOURCES` — `source` пайплайна):
457
+
458
+ - `created`/`waiting_for_resource`/`preparing`/`pending` → `queued`, `running`/`canceling` → `running`,
459
+ `waiting_for_callback`/`manual`/`scheduled` → `waiting`, `success`/`failed`/`canceled`/`skipped` →
460
+ одноимённые категории;
461
+ - `push` → `push`, `merge_request_event`/`external_pull_request_event` → `pull_request`,
462
+ `web`/`api`/`chat`/`webide` → `manual`, `schedule`/`pipeline_execution_policy_schedule` → `schedule`,
463
+ `trigger`/`pipeline`/`parent_pipeline` → `trigger`.
464
+
465
+ SourceCraft (`SOURCECRAFT_CI_STATUSES` — `status` прогона, workflow, задачи и куба; `SOURCECRAFT_RUN_EVENTS`
466
+ — `event_type` прогона):
467
+
468
+ - `created`/`prepared` → `queued`, `processing` → `running`, `awaiting_approval` → `waiting`,
469
+ `success`/`failed`/`skipped` → одноимённые, `timeout` → `failed`, `canceled`/`rejected` → `canceled`;
470
+ - `push` → `push`, `pr_update` → `pull_request`, `manual` → `manual`, `restart` → `retry`,
471
+ `schedule` → `schedule`, `repository_event` → `trigger`.
472
+
473
+ Что умеет каждый трекер, описывает раздел `ci` определения (R11 — все фильтры `ciRunFilterSchema`: `status`,
474
+ `ref`, `sha`, `event`, `workflow`, `actor`, `pullRequest`, `createdAfter`, `createdBefore`, `updatedAfter`,
475
+ `updatedBefore`):
476
+
477
+ | Поле | GitHub Actions | GitLab | SourceCraft |
478
+ |---|---|---|---|
479
+ | `workflows` | да (`listWorkflows`) | нет | нет |
480
+ | `runs.filters` | все | все | кроме `ref` и `sha` |
481
+ | `runs.clientSide` | `status`, `event`, `updatedAfter`, `updatedBefore` | `status`, `event` | все фильтры |
482
+ | `runs.sorts` | — | `created`, `updated` | — |
483
+ | `jobs` | фильтры `status`, `allAttempts`; `status` на странице | фильтры `status`, `allAttempts` | фильтр `status`; `status` на странице |
484
+ | `log` | `live: false`, курсор есть | `live: true`, курсор есть | `live: true`, курсор есть |
485
+ | `trigger` | ровно один workflow, `inputs`, теги | без workflow, `inputs`, теги | хотя бы один workflow, `inputs`, теги |
486
+ | `rerun` | всё, включая задание и `debug` | только `failedOnly` и задание | не поддерживается |
487
+ | `cancel` | прогон | прогон и задание | не поддерживается |
488
+
489
+ Запросы списков — `CiRunQuery` (`PageQuery` плюс фильтры из таблицы и `sort` по `created`/`updated`) и
490
+ `CiJobQuery` (`status`, `allAttempts` — задания прежних попыток); имена допустимых фильтров и полей сортировки
491
+ выведены в типы `CiRunFilter`, `CiRunSortField` и `CiJobFilter` из схем `ciRunFilterSchema`,
492
+ `ciRunSortFieldSchema` и `ciJobFilterSchema` — теми же перечислениями оперирует `CiCapabilities`. У GitLab
493
+ список прогонов с `pullRequest` идёт через пайплайны MR: остальные фильтры тогда проверяются по странице.
494
+ Запуск — `CiTriggerInput` (`ref`,
495
+ `refType`, `workflows`, `inputs`): у GitHub ровно один workflow (иначе `invalid_request`, входов не больше 25),
496
+ у GitLab `workflows` не задаётся (непустой — `unsupported`), у SourceCraft нужен хотя бы один workflow.
497
+ `rerun`/`rerunJob` возвращают свежее состояние прогона, `cancel`/`cancelJob` — свежее состояние (оно может быть
498
+ ещё `running`).
499
+
500
+ **Лог окном с курсором (D-006).** `log(jobKey, CiLogQuery)` читает лог задания окном: `maxBytes` от 1 до
501
+ `CI_LOG_MAX_BYTES` (1 МиБ), по умолчанию `CI_LOG_DEFAULT_BYTES` (16 КиБ) — конец лога, где обычно причина
502
+ падения; `from: 'head'` — начало. Тело читается потоком до `CI_LOG_READ_MAX_BYTES` (64 МиБ), удерживается
503
+ кольцевым буфером, таймаут загрузки — `CI_LOG_TIMEOUT_MS` (60 с). ANSI-последовательности и перерисовки
504
+ строки вычищаются (`cleanLogText`), если не `raw: true`; маскирование секретов идёт всегда. Ответ `CiLog`:
505
+ `text` (окно), `truncated`, `complete` (задание закончилось), `size` (если тело прочитано целиком) и
506
+ `nextCursor` — его нет, когда дальше не будет ни байта. Курсор — `c:<страница>:<байт>` (`logCursor`); страница
507
+ 0 у GitHub и GitLab, у SourceCraft — номер страницы его пагинации (за один вызов читается до
508
+ `CI_LOG_PAGES_MAX` страниц). Окно из запроса разбирает `logWindow(query)`, ответ собирает `logOf(...)`;
509
+ `isFinished(category)` — категория из `CI_FINISHED_STATUSES`.
510
+
511
+ **Края окна — по целым строкам.** Секрет или ANSI-последовательность, разрезанные краем окна, не узнаются ни в
512
+ одном из окон, а два склеенных ответа отдают их целиком — поэтому окно выравнивается по строкам внутри
513
+ `logOf`: окно с курсором кончается после последнего `\n` (курсор указывает на начало следующей строки), а окно
514
+ с отрезанным началом — флаг `startCut: true`, по умолчанию `truncated && !more` — начинается после первого
515
+ `\n`. Строка длиннее окна режется по слову: конец — перед последним словом вместе с ключом присваивания перед
516
+ ним, начало — после первого пробела; без пробелов окно режется по байту, и тогда откладываются незаконченная
517
+ ANSI-последовательность и `\r`. Отдельно добирается хвост приватного ключа: `logOf` маскирует строки тела PEM,
518
+ на которых окно начинается, и откладёт строку `-----BEGIN … PRIVATE KEY-----`, если парного `END` в этом окне
519
+ нет. Так замаскированный и очищенный текст склеенных окон совпадает с текстом лога, прочитанного целиком, а
520
+ `nextCursor` уходит на начало следующей строки — кроме случая, когда окно упёрлось в потолок `maxBytes`
521
+ посреди единственной строки длиннее окна либо в границу страницы SourceCraft.
522
+
523
+ Дочитывание лога идущего задания — поллинг по `nextCursor`:
524
+
525
+ ```ts
526
+ let cursor: string | undefined;
527
+ for (;;) {
528
+ const chunk = await ci.log(job.key, cursor === undefined ? {} : { cursor });
529
+ process.stdout.write(chunk.text);
530
+ cursor = chunk.nextCursor;
531
+ if (cursor === undefined) break;
532
+ await new Promise((resolve) => setTimeout(resolve, 5000));
533
+ }
534
+ ```
535
+
536
+ Пределы трекеров: у GitHub лог задания доступен **только после завершения** (`log.live: false`): идущему
537
+ заданию отвечают пустым текстом и курсором `c:0:0`, не скачивая ничего. Сам лог GitHub отдаёт 302 на
538
+ подписанный URL (живёт около минуты) — `fetch` в контексте должен следовать редиректам. У SourceCraft нет
539
+ перезапуска и отмены (`rerun`/`cancel` — `unsupported`), а `listJobs` стоит 1 + N запросов (прогон и каждый
540
+ его workflow); список прогонов не фильтрует сервером вообще — все фильтры на странице, листайте `nextCursor`.
541
+ Логи служебных кубов прогона (`#git-clone`, `#create-environment`) через API не читаются: слаг с `#`
542
+ площадка не принимает (400 на шаблон имени), а без `#` куб не находится, поэтому `log()` на таком задании —
543
+ `unsupported` **до запроса**; в `listJobs` эти кубы остаются. Хвост SourceCraft дочитывает не больше
544
+ `CI_LOG_PAGES_MAX` страниц за вызов: у более длинного лога это конец первой прочитанной пачки, а не всего
545
+ лога — остальное добирается по `nextCursor`.
546
+
547
+ Символы субпути: фабрики `githubCi()`, `gitlabCi()`, `sourcecraftCi()`, `ciAdapterOf`, типы `CiAdapter`,
548
+ `CiCapabilities`, `CiDefinition`, `CiWorkflow`, `CiRun`, `CiJob`, `CiLog`, `CiStatus`, `CiStatusCategory`,
549
+ `CiEventCategory`, `CiRunQuery`, `CiJobQuery`, `CiLogQuery`, `CiLogWindow`, `CiTriggerInput`,
550
+ `CiTriggerResult`, `CiRerunInput`, `CiJobRerunInput`, наборы значений запроса — типы `CiRunFilter`,
551
+ `CiRunSortField`, `CiJobFilter`, схемы `ciStatusCategorySchema`, `ciEventCategorySchema`,
552
+ `ciRunFilterSchema`, `ciRunSortFieldSchema`, `ciJobFilterSchema`, `ciStatusSchema`, `ciWorkflowSchema`,
553
+ `ciRunSchema`, `ciJobSchema`, `ciLogSchema`, помощники `logWindow`, `logCursor`, `logOf` (у его входа —
554
+ необязательное поле `startCut`: начало окна отрезано краем, первая неполная строка отбрасывается),
555
+ `cleanLogText`, `isFinished` и константы `CI_LOG_DEFAULT_BYTES`, `CI_LOG_MAX_BYTES`, `CI_LOG_READ_MAX_BYTES`,
556
+ `CI_LOG_TIMEOUT_MS`, `CI_LOG_PAGES_MAX`, `CI_FINISHED_STATUSES`. Таблицы сопоставления — `GITHUB_RUN_STATUSES`,
557
+ `GITHUB_RUN_CONCLUSIONS`, `GITHUB_RUN_EVENTS`, `GITLAB_CI_STATUSES`, `GITLAB_PIPELINE_SOURCES`,
558
+ `SOURCECRAFT_CI_STATUSES`, `SOURCECRAFT_RUN_EVENTS` (содержание — выше). Загрузку текста наружу держит
559
+ `requestText(url, TextRequest): TextResponse` — тело читается потоком, `skip` пропускает байты от начала
560
+ (дочитывание по курсору), `keep: { bytes, from: 'head' | 'tail' }` удерживает окно кольцевым буфером,
561
+ `readMax` и `timeoutMs` перекрывают потолки по умолчанию. Модель лога — запись D-006.
562
+
428
563
  ## mcp
429
564
 
430
565
  `serveMcp` — построчный JSON-RPC 2.0 на stdio, только инструменты: `initialize`, `ping`, `tools/list`,
@@ -160,7 +160,8 @@ var defaultSecretSink = {
160
160
  };
161
161
 
162
162
  export {
163
+ REDACTED,
163
164
  redactSecretText,
164
165
  defaultSecretSink
165
166
  };
166
- //# sourceMappingURL=chunk-L7CPE2SO.js.map
167
+ //# sourceMappingURL=chunk-AGGJK2XZ.js.map
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-3YP22YLA.js";
8
8
  import {
9
9
  redactSecretText
10
- } from "./chunk-L7CPE2SO.js";
10
+ } from "./chunk-AGGJK2XZ.js";
11
11
 
12
12
  // src/git/git.const.ts
13
13
  var GIT_TIMEOUT_MS = 12e4;
@@ -418,4 +418,4 @@ export {
418
418
  showBlob,
419
419
  readWorktreeFile
420
420
  };
421
- //# sourceMappingURL=chunk-GPRMI4PG.js.map
421
+ //# sourceMappingURL=chunk-ZTME4HFD.js.map
package/dist/git/index.js CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  showBlob,
26
26
  statusEntries,
27
27
  untrackedFiles
28
- } from "../chunk-GPRMI4PG.js";
28
+ } from "../chunk-ZTME4HFD.js";
29
29
  import {
30
30
  PROJECT_WORKTREE_SEGMENT,
31
31
  PathEscapeError,
@@ -47,7 +47,7 @@ import "../chunk-3YP22YLA.js";
47
47
  import {
48
48
  defaultSecretSink,
49
49
  redactSecretText
50
- } from "../chunk-L7CPE2SO.js";
50
+ } from "../chunk-AGGJK2XZ.js";
51
51
  import "../chunk-4ZGRXIVA.js";
52
52
  export {
53
53
  GIT_CHECKOUT_TIMEOUT_MS,
package/dist/index.js CHANGED
@@ -59,7 +59,7 @@ import {
59
59
  // package.json
60
60
  var package_default = {
61
61
  name: "@smwb/onreel-git-mcp",
62
- version: "0.4.0",
62
+ version: "0.5.0",
63
63
  description: "\u0411\u0438\u0431\u043B\u0438\u043E\u0442\u0435\u043A\u0430 \u043C\u043E\u0434\u0443\u043B\u0435\u0439, \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u043D\u044B\u0445 \u0438\u0437 onreel: git-\u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u044B\u0435 \u043F\u0443\u0442\u0438, \u0441\u043F\u0438\u0441\u043E\u043A \u0444\u0430\u0439\u043B\u043E\u0432 worktree, \u0436\u0438\u0437\u043D\u0435\u043D\u043D\u044B\u0439 \u0446\u0438\u043A\u043B worktree \u043F\u0440\u043E\u0442\u0438\u0432 \u043F\u043E\u0440\u0442\u0430 WorktreeStore, \u0430\u0434\u0430\u043F\u0442\u0435\u0440\u044B \u0442\u0440\u0435\u043A\u0435\u0440\u043E\u0432 GitHub/GitLab/Jira/SourceCraft/\u043B\u043E\u043A\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u0438 MCP-\u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0430 stdio",
64
64
  keywords: [
65
65
  "git",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@smwb/onreel-git-mcp\",\n \"version\": \"0.4.0\",\n \"description\": \"Библиотека модулей, выделенных из onreel: git-операции и безопасные пути, список файлов worktree, жизненный цикл worktree против порта WorktreeStore, адаптеры трекеров GitHub/GitLab/Jira/SourceCraft/локального и MCP-сервер на stdio\",\n \"keywords\": [\n \"git\",\n \"worktree\",\n \"mcp\",\n \"issue-tracker\",\n \"github\",\n \"gitlab\",\n \"jira\",\n \"sourcecraft\",\n \"onreel\",\n \"typescript\"\n ],\n \"type\": \"module\",\n \"engines\": {\n \"node\": \">=24\"\n },\n \"files\": [\n \"dist\"\n ],\n \"sideEffects\": false,\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://git.sourcecraft.dev/elfenmail/onreel-git-mcp.git\"\n },\n \"homepage\": \"https://git.sourcecraft.dev/elfenmail/onreel-git-mcp\",\n \"license\": \"MIT\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"default\": \"./dist/index.js\"\n },\n \"./git\": {\n \"types\": \"./dist/git/index.d.ts\",\n \"import\": \"./dist/git/index.js\",\n \"default\": \"./dist/git/index.js\"\n },\n \"./files\": {\n \"types\": \"./dist/files/index.d.ts\",\n \"import\": \"./dist/files/index.js\",\n \"default\": \"./dist/files/index.js\"\n },\n \"./worktree\": {\n \"types\": \"./dist/worktree/index.d.ts\",\n \"import\": \"./dist/worktree/index.js\",\n \"default\": \"./dist/worktree/index.js\"\n },\n \"./tracker\": {\n \"types\": \"./dist/tracker/index.d.ts\",\n \"import\": \"./dist/tracker/index.js\",\n \"default\": \"./dist/tracker/index.js\"\n },\n \"./mcp\": {\n \"types\": \"./dist/mcp/index.d.ts\",\n \"import\": \"./dist/mcp/index.js\",\n \"default\": \"./dist/mcp/index.js\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"scripts\": {\n \"build\": \"tsup && tsc -p tsconfig.build.json\",\n \"typecheck\": \"tsc -p tsconfig.json && tsc -p tsconfig.examples.json\",\n \"lint\": \"oxlint --type-aware\",\n \"test\": \"node --test \\\"test/**/*.test.ts\\\"\",\n \"changeset\": \"changeset\",\n \"version\": \"changeset version\",\n \"release\": \"npm run build && changeset publish\"\n },\n \"dependencies\": {\n \"zod\": \"^4.6.5\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"2.29.2\",\n \"@types/node\": \"24.19.1\",\n \"oxlint\": \"1.87.0\",\n \"oxlint-tsgolint\": \"7.0.2003\",\n \"tsup\": \"8.5.1\",\n \"typescript\": \"7.0.2\"\n }\n}\n","// Корневой подпуть пакета @smwb/onreel-git-mcp: срез контракта (константы, схемы, типы, чистые\n// функции) и версия пакета. Всё без побочных эффектов при импорте (R-001). Швы ядра\n// (SecretSink, WorktreeStore, LocalIssueStore) и модули git/files/worktree/tracker/mcp\n// экспортируют свои подпути — см. exports в package.json и README.\nimport pkg from '../package.json' with { type: 'json' };\n\nexport * from './contract/contract.const.ts';\nexport * from './contract/contract.schema.ts';\nexport * from './contract/contract.types.ts';\nexport * from './contract/contract.lib.ts';\n\n// Версия пакета — из version в package.json: статический импорт JSON, его значение tsup подставляет\n// в бандл на сборке, поэтому VERSION не расходится с релизом changesets (тот правит только version).\nexport const VERSION: string = pkg.version;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,UAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,MAAQ;AAAA,EACR,SAAW;AAAA,IACT,MAAQ;AAAA,EACV;AAAA,EACA,OAAS;AAAA,IACP;AAAA,EACF;AAAA,EACA,aAAe;AAAA,EACf,eAAiB;AAAA,IACf,QAAU;AAAA,IACV,UAAY;AAAA,EACd;AAAA,EACA,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,UAAY;AAAA,EACZ,SAAW;AAAA,EACX,SAAW;AAAA,IACT,KAAK;AAAA,MACH,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,SAAS;AAAA,MACP,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,WAAW;AAAA,MACT,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,cAAc;AAAA,MACZ,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,aAAa;AAAA,MACX,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,SAAS;AAAA,MACP,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,kBAAkB;AAAA,EACpB;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,WAAa;AAAA,IACb,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,WAAa;AAAA,IACb,SAAW;AAAA,IACX,SAAW;AAAA,EACb;AAAA,EACA,cAAgB;AAAA,IACd,KAAO;AAAA,EACT;AAAA,EACA,iBAAmB;AAAA,IACjB,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,QAAU;AAAA,IACV,mBAAmB;AAAA,IACnB,MAAQ;AAAA,IACR,YAAc;AAAA,EAChB;AACF;;;AC1EO,IAAM,UAAkB,gBAAI;","names":[]}
1
+ {"version":3,"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@smwb/onreel-git-mcp\",\n \"version\": \"0.5.0\",\n \"description\": \"Библиотека модулей, выделенных из onreel: git-операции и безопасные пути, список файлов worktree, жизненный цикл worktree против порта WorktreeStore, адаптеры трекеров GitHub/GitLab/Jira/SourceCraft/локального и MCP-сервер на stdio\",\n \"keywords\": [\n \"git\",\n \"worktree\",\n \"mcp\",\n \"issue-tracker\",\n \"github\",\n \"gitlab\",\n \"jira\",\n \"sourcecraft\",\n \"onreel\",\n \"typescript\"\n ],\n \"type\": \"module\",\n \"engines\": {\n \"node\": \">=24\"\n },\n \"files\": [\n \"dist\"\n ],\n \"sideEffects\": false,\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://git.sourcecraft.dev/elfenmail/onreel-git-mcp.git\"\n },\n \"homepage\": \"https://git.sourcecraft.dev/elfenmail/onreel-git-mcp\",\n \"license\": \"MIT\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"default\": \"./dist/index.js\"\n },\n \"./git\": {\n \"types\": \"./dist/git/index.d.ts\",\n \"import\": \"./dist/git/index.js\",\n \"default\": \"./dist/git/index.js\"\n },\n \"./files\": {\n \"types\": \"./dist/files/index.d.ts\",\n \"import\": \"./dist/files/index.js\",\n \"default\": \"./dist/files/index.js\"\n },\n \"./worktree\": {\n \"types\": \"./dist/worktree/index.d.ts\",\n \"import\": \"./dist/worktree/index.js\",\n \"default\": \"./dist/worktree/index.js\"\n },\n \"./tracker\": {\n \"types\": \"./dist/tracker/index.d.ts\",\n \"import\": \"./dist/tracker/index.js\",\n \"default\": \"./dist/tracker/index.js\"\n },\n \"./mcp\": {\n \"types\": \"./dist/mcp/index.d.ts\",\n \"import\": \"./dist/mcp/index.js\",\n \"default\": \"./dist/mcp/index.js\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"scripts\": {\n \"build\": \"tsup && tsc -p tsconfig.build.json\",\n \"typecheck\": \"tsc -p tsconfig.json && tsc -p tsconfig.examples.json\",\n \"lint\": \"oxlint --type-aware\",\n \"test\": \"node --test \\\"test/**/*.test.ts\\\"\",\n \"changeset\": \"changeset\",\n \"version\": \"changeset version\",\n \"release\": \"npm run build && changeset publish\"\n },\n \"dependencies\": {\n \"zod\": \"^4.6.5\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"2.29.2\",\n \"@types/node\": \"24.19.1\",\n \"oxlint\": \"1.87.0\",\n \"oxlint-tsgolint\": \"7.0.2003\",\n \"tsup\": \"8.5.1\",\n \"typescript\": \"7.0.2\"\n }\n}\n","// Корневой подпуть пакета @smwb/onreel-git-mcp: срез контракта (константы, схемы, типы, чистые\n// функции) и версия пакета. Всё без побочных эффектов при импорте (R-001). Швы ядра\n// (SecretSink, WorktreeStore, LocalIssueStore) и модули git/files/worktree/tracker/mcp\n// экспортируют свои подпути — см. exports в package.json и README.\nimport pkg from '../package.json' with { type: 'json' };\n\nexport * from './contract/contract.const.ts';\nexport * from './contract/contract.schema.ts';\nexport * from './contract/contract.types.ts';\nexport * from './contract/contract.lib.ts';\n\n// Версия пакета — из version в package.json: статический импорт JSON, его значение tsup подставляет\n// в бандл на сборке, поэтому VERSION не расходится с релизом changesets (тот правит только version).\nexport const VERSION: string = pkg.version;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,UAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,MAAQ;AAAA,EACR,SAAW;AAAA,IACT,MAAQ;AAAA,EACV;AAAA,EACA,OAAS;AAAA,IACP;AAAA,EACF;AAAA,EACA,aAAe;AAAA,EACf,eAAiB;AAAA,IACf,QAAU;AAAA,IACV,UAAY;AAAA,EACd;AAAA,EACA,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,UAAY;AAAA,EACZ,SAAW;AAAA,EACX,SAAW;AAAA,IACT,KAAK;AAAA,MACH,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,SAAS;AAAA,MACP,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,WAAW;AAAA,MACT,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,cAAc;AAAA,MACZ,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,aAAa;AAAA,MACX,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,SAAS;AAAA,MACP,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,kBAAkB;AAAA,EACpB;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,WAAa;AAAA,IACb,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,WAAa;AAAA,IACb,SAAW;AAAA,IACX,SAAW;AAAA,EACb;AAAA,EACA,cAAgB;AAAA,IACd,KAAO;AAAA,EACT;AAAA,EACA,iBAAmB;AAAA,IACjB,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,QAAU;AAAA,IACV,mBAAmB;AAAA,IACnB,MAAQ;AAAA,IACR,YAAc;AAAA,EAChB;AACF;;;AC1EO,IAAM,UAAkB,gBAAI;","names":[]}
package/dist/mcp/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  } from "../chunk-3YP22YLA.js";
5
5
  import {
6
6
  redactSecretText
7
- } from "../chunk-L7CPE2SO.js";
7
+ } from "../chunk-AGGJK2XZ.js";
8
8
  import {
9
9
  ENV_DISPATCH_ID,
10
10
  ENV_HOST_URL,
@@ -0,0 +1,36 @@
1
+ import type { CiLog, CiStatusCategory } from './ci.schema.ts';
2
+ import type { CiAdapter, CiLogQuery, CiLogWindow } from './ci.types.ts';
3
+ import type { AdapterContext, TrackerDefinition } from './tracker.types.ts';
4
+ /** Адаптер CI трекера (D-005); трекер без раздела ci — TrackerError('unsupported', 'Трекер <title> не ведёт CI.'). */
5
+ export declare function ciAdapterOf(definition: TrackerDefinition, context: AdapterContext): CiAdapter;
6
+ /**
7
+ * Окно лога из запроса (D-006): maxBytes 1..CI_LOG_MAX_BYTES (по умолчанию CI_LOG_DEFAULT_BYTES), from по умолчанию tail,
8
+ * курсор `c:<страница>:<байт>` — в resume; иначе TrackerError('invalid_request').
9
+ */
10
+ export declare function logWindow(query: CiLogQuery): CiLogWindow;
11
+ /** Курсор дочитывания с места (страница, байт в ней): `c:<page>:<offset>`. */
12
+ export declare function logCursor(page: number, offset: number): string;
13
+ /**
14
+ * Лог единой модели из прочитанного окна: окно выравнивается по целым строкам (lineWindow), затем cleanLogText
15
+ * (если не raw), хвост приватного ключа из прошлого окна и redactSecretText — всегда. nextCursor = logCursor(page, end)
16
+ * со сдвигом end назад на отложенный конец окна, если задание не закончилось или окно head оборвалось раньше конца
17
+ * тела; иначе курсора нет. Окно, которое не сдвинулось (пусто при more: потолок чтения, символ шире окна), у законченного
18
+ * задания курсора не даёт — тот же курсор зациклил бы дочитывание. startCut — начало окна отрезано (хвост лога): первая
19
+ * неполная строка отбрасывается; по умолчанию truncated && !more — окно усечено, а дальше читать нечего.
20
+ * end — байт за окном на странице page; на эту страницу приходятся не больше end последних байт окна.
21
+ */
22
+ export declare function logOf(input: {
23
+ text: string;
24
+ truncated: boolean;
25
+ complete: boolean;
26
+ page: number;
27
+ end: number;
28
+ more: boolean;
29
+ size?: number | undefined;
30
+ raw: boolean;
31
+ startCut?: boolean | undefined;
32
+ }): CiLog;
33
+ /** Текст лога без ANSI-последовательностей (CSI, OSC), перерисовок строки через \r и маркеров section_start/section_end GitLab. */
34
+ export declare function cleanLogText(text: string): string;
35
+ /** Категория законченного состояния: success, failed, canceled, skipped. */
36
+ export declare function isFinished(category: CiStatusCategory): boolean;
@@ -0,0 +1,162 @@
1
+ import { z } from 'zod';
2
+ /** Категория состояния прогона, задания и шага CI единой модели (D-006); своё имя трекер отдаёт в status.name. */
3
+ export declare const ciStatusCategorySchema: z.ZodEnum<{
4
+ canceled: "canceled";
5
+ failed: "failed";
6
+ queued: "queued";
7
+ running: "running";
8
+ skipped: "skipped";
9
+ success: "success";
10
+ waiting: "waiting";
11
+ }>;
12
+ /** Что запустило прогон; своё имя события трекер отдаёт в event.name. */
13
+ export declare const ciEventCategorySchema: z.ZodEnum<{
14
+ manual: "manual";
15
+ other: "other";
16
+ pull_request: "pull_request";
17
+ push: "push";
18
+ retry: "retry";
19
+ schedule: "schedule";
20
+ trigger: "trigger";
21
+ }>;
22
+ export declare const ciRunFilterSchema: z.ZodEnum<{
23
+ actor: "actor";
24
+ createdAfter: "createdAfter";
25
+ createdBefore: "createdBefore";
26
+ event: "event";
27
+ pullRequest: "pullRequest";
28
+ ref: "ref";
29
+ sha: "sha";
30
+ status: "status";
31
+ updatedAfter: "updatedAfter";
32
+ updatedBefore: "updatedBefore";
33
+ workflow: "workflow";
34
+ }>;
35
+ export declare const ciRunSortFieldSchema: z.ZodEnum<{
36
+ created: "created";
37
+ updated: "updated";
38
+ }>;
39
+ export declare const ciJobFilterSchema: z.ZodEnum<{
40
+ allAttempts: "allAttempts";
41
+ status: "status";
42
+ }>;
43
+ export declare const ciStatusSchema: z.ZodObject<{
44
+ category: z.ZodEnum<{
45
+ canceled: "canceled";
46
+ failed: "failed";
47
+ queued: "queued";
48
+ running: "running";
49
+ skipped: "skipped";
50
+ success: "success";
51
+ waiting: "waiting";
52
+ }>;
53
+ name: z.ZodString;
54
+ }, z.core.$strip>;
55
+ export declare const ciWorkflowSchema: z.ZodObject<{
56
+ key: z.ZodString;
57
+ name: z.ZodString;
58
+ path: z.ZodOptional<z.ZodString>;
59
+ enabled: z.ZodBoolean;
60
+ }, z.core.$strip>;
61
+ export declare const ciRunSchema: z.ZodObject<{
62
+ key: z.ZodString;
63
+ number: z.ZodOptional<z.ZodNumber>;
64
+ workflows: z.ZodArray<z.ZodString>;
65
+ status: z.ZodObject<{
66
+ category: z.ZodEnum<{
67
+ canceled: "canceled";
68
+ failed: "failed";
69
+ queued: "queued";
70
+ running: "running";
71
+ skipped: "skipped";
72
+ success: "success";
73
+ waiting: "waiting";
74
+ }>;
75
+ name: z.ZodString;
76
+ }, z.core.$strip>;
77
+ event: z.ZodOptional<z.ZodObject<{
78
+ category: z.ZodEnum<{
79
+ manual: "manual";
80
+ other: "other";
81
+ pull_request: "pull_request";
82
+ push: "push";
83
+ retry: "retry";
84
+ schedule: "schedule";
85
+ trigger: "trigger";
86
+ }>;
87
+ name: z.ZodString;
88
+ }, z.core.$strip>>;
89
+ ref: z.ZodOptional<z.ZodString>;
90
+ sha: z.ZodOptional<z.ZodString>;
91
+ actor: z.ZodOptional<z.ZodString>;
92
+ pullRequest: z.ZodOptional<z.ZodString>;
93
+ attempt: z.ZodOptional<z.ZodNumber>;
94
+ errors: z.ZodOptional<z.ZodArray<z.ZodString>>;
95
+ links: z.ZodArray<z.ZodObject<{
96
+ url: z.ZodString;
97
+ title: z.ZodOptional<z.ZodString>;
98
+ }, z.core.$strip>>;
99
+ createdAt: z.ZodOptional<z.ZodNumber>;
100
+ startedAt: z.ZodOptional<z.ZodNumber>;
101
+ finishedAt: z.ZodOptional<z.ZodNumber>;
102
+ updatedAt: z.ZodOptional<z.ZodNumber>;
103
+ }, z.core.$strip>;
104
+ export declare const ciJobSchema: z.ZodObject<{
105
+ key: z.ZodString;
106
+ runKey: z.ZodString;
107
+ name: z.ZodString;
108
+ stage: z.ZodOptional<z.ZodString>;
109
+ status: z.ZodObject<{
110
+ category: z.ZodEnum<{
111
+ canceled: "canceled";
112
+ failed: "failed";
113
+ queued: "queued";
114
+ running: "running";
115
+ skipped: "skipped";
116
+ success: "success";
117
+ waiting: "waiting";
118
+ }>;
119
+ name: z.ZodString;
120
+ }, z.core.$strip>;
121
+ steps: z.ZodOptional<z.ZodArray<z.ZodObject<{
122
+ number: z.ZodNumber;
123
+ name: z.ZodString;
124
+ status: z.ZodObject<{
125
+ category: z.ZodEnum<{
126
+ canceled: "canceled";
127
+ failed: "failed";
128
+ queued: "queued";
129
+ running: "running";
130
+ skipped: "skipped";
131
+ success: "success";
132
+ waiting: "waiting";
133
+ }>;
134
+ name: z.ZodString;
135
+ }, z.core.$strip>;
136
+ }, z.core.$strip>>>;
137
+ attempt: z.ZodOptional<z.ZodNumber>;
138
+ links: z.ZodArray<z.ZodObject<{
139
+ url: z.ZodString;
140
+ title: z.ZodOptional<z.ZodString>;
141
+ }, z.core.$strip>>;
142
+ createdAt: z.ZodOptional<z.ZodNumber>;
143
+ startedAt: z.ZodOptional<z.ZodNumber>;
144
+ finishedAt: z.ZodOptional<z.ZodNumber>;
145
+ }, z.core.$strip>;
146
+ export declare const ciLogSchema: z.ZodObject<{
147
+ text: z.ZodString;
148
+ truncated: z.ZodBoolean;
149
+ complete: z.ZodBoolean;
150
+ nextCursor: z.ZodOptional<z.ZodString>;
151
+ size: z.ZodOptional<z.ZodNumber>;
152
+ }, z.core.$strip>;
153
+ export type CiStatusCategory = z.infer<typeof ciStatusCategorySchema>;
154
+ export type CiEventCategory = z.infer<typeof ciEventCategorySchema>;
155
+ export type CiRunFilter = z.infer<typeof ciRunFilterSchema>;
156
+ export type CiRunSortField = z.infer<typeof ciRunSortFieldSchema>;
157
+ export type CiJobFilter = z.infer<typeof ciJobFilterSchema>;
158
+ export type CiStatus = z.infer<typeof ciStatusSchema>;
159
+ export type CiWorkflow = z.infer<typeof ciWorkflowSchema>;
160
+ export type CiRun = z.infer<typeof ciRunSchema>;
161
+ export type CiJob = z.infer<typeof ciJobSchema>;
162
+ export type CiLog = z.infer<typeof ciLogSchema>;
@@ -0,0 +1,117 @@
1
+ import type { CiEventCategory, CiJob, CiJobFilter, CiLog, CiRun, CiRunFilter, CiRunSortField, CiStatusCategory, CiWorkflow } from './ci.schema.ts';
2
+ import type { AdapterContext, ListCapabilities, ListSort, PageQuery, TrackerPage } from './tracker.types.ts';
3
+ export type CiRunQuery = PageQuery & {
4
+ status?: readonly CiStatusCategory[] | undefined;
5
+ /** Ветка или тег — имя без refs/heads/. */
6
+ ref?: string | undefined;
7
+ sha?: string | undefined;
8
+ event?: readonly CiEventCategory[] | undefined;
9
+ /** GitHub — id или имя файла workflow (`ci.yml`), GitLab — имя пайплайна, SourceCraft — имя workflow из конфига. */
10
+ workflow?: string | undefined;
11
+ /** Кто запустил — логин или slug трекера. */
12
+ actor?: string | undefined;
13
+ /** Ключ PR: прогоны для его головы. */
14
+ pullRequest?: string | undefined;
15
+ createdAfter?: number | undefined;
16
+ createdBefore?: number | undefined;
17
+ updatedAfter?: number | undefined;
18
+ updatedBefore?: number | undefined;
19
+ sort?: ListSort<CiRunSortField> | undefined;
20
+ };
21
+ export type CiJobQuery = PageQuery & {
22
+ status?: readonly CiStatusCategory[] | undefined;
23
+ /** И задания прежних попыток (GitHub filter=all, GitLab include_retried); по умолчанию — только последние. */
24
+ allAttempts?: boolean | undefined;
25
+ };
26
+ export type CiLogQuery = {
27
+ /**
28
+ * Сколько байт текста вернуть: 1..CI_LOG_MAX_BYTES, по умолчанию CI_LOG_DEFAULT_BYTES. Края окна выравниваются
29
+ * по целым строкам (секрет на краю не делится между окнами), поэтому текст бывает короче.
30
+ */
31
+ maxBytes?: number | undefined;
32
+ /** Без курсора: tail (по умолчанию) — конец лога, где обычно причина падения; head — начало. */
33
+ from?: 'head' | 'tail' | undefined;
34
+ /** nextCursor прошлого ответа: текст с этого места вперёд (дочитывание идущего задания); from тогда не читается. */
35
+ cursor?: string | undefined;
36
+ /** Не вычищать ANSI-последовательности и маркеры секций; секреты маскируются всегда. */
37
+ raw?: boolean | undefined;
38
+ };
39
+ /** Окно чтения лога после проверки запроса: resume — место курсора (страница и байт в ней; у GitHub и GitLab страница 0). */
40
+ export type CiLogWindow = {
41
+ bytes: number;
42
+ from: 'head' | 'tail';
43
+ resume?: {
44
+ page: number;
45
+ offset: number;
46
+ } | undefined;
47
+ };
48
+ export type CiTriggerInput = {
49
+ /** Ветка или тег, на котором запустить. */
50
+ ref: string;
51
+ /** Что такое ref; по умолчанию branch (GitHub и GitLab определяют сами, SourceCraft — нет). */
52
+ refType?: 'branch' | 'tag' | undefined;
53
+ /** GitHub — ровно один (id или имя файла), SourceCraft — хотя бы один (имена из конфига), GitLab — не задаётся. */
54
+ workflows?: readonly string[] | undefined;
55
+ /** Параметры: GitHub inputs (не больше 25), SourceCraft values каждого workflow, GitLab — переменные пайплайна. */
56
+ inputs?: Readonly<Record<string, string>> | undefined;
57
+ };
58
+ /** run нет — трекер принял запуск, но не сказал, какой прогон создан. */
59
+ export type CiTriggerResult = {
60
+ run?: CiRun | undefined;
61
+ };
62
+ export type CiRerunInput = {
63
+ /** Только упавшие задания и зависящие от них; GitLab умеет только так. */
64
+ failedOnly?: boolean | undefined;
65
+ /** Отладочное логирование (GitHub enable_debug_logging). */
66
+ debug?: boolean | undefined;
67
+ };
68
+ export type CiJobRerunInput = {
69
+ debug?: boolean | undefined;
70
+ };
71
+ export type CiAdapter = {
72
+ listWorkflows(query: PageQuery): Promise<TrackerPage<CiWorkflow>>;
73
+ listRuns(query: CiRunQuery): Promise<TrackerPage<CiRun>>;
74
+ getRun(key: string): Promise<CiRun>;
75
+ listJobs(runKey: string, query: CiJobQuery): Promise<TrackerPage<CiJob>>;
76
+ getJob(key: string): Promise<CiJob>;
77
+ log(jobKey: string, query: CiLogQuery): Promise<CiLog>;
78
+ trigger(input: CiTriggerInput): Promise<CiTriggerResult>;
79
+ /** Перезапуск прогона; вернётся его свежее состояние. */
80
+ rerun(runKey: string, input: CiRerunInput): Promise<CiRun>;
81
+ /** Перезапуск задания; вернётся свежее состояние прогона, в который оно попало. */
82
+ rerunJob(jobKey: string, input: CiJobRerunInput): Promise<CiRun>;
83
+ /** Отмена; вернётся свежее состояние (может быть ещё running). */
84
+ cancel(runKey: string): Promise<CiRun>;
85
+ cancelJob(jobKey: string): Promise<CiJob>;
86
+ };
87
+ export type CiCapabilities = {
88
+ workflows: boolean;
89
+ runs: ListCapabilities<CiRunFilter, CiRunSortField>;
90
+ jobs: ListCapabilities<CiJobFilter, never>;
91
+ /** live — лог идущего задания читается; cursor — дочитывание по nextCursor. */
92
+ log: {
93
+ live: boolean;
94
+ cursor: boolean;
95
+ };
96
+ trigger: {
97
+ supported: boolean;
98
+ workflows: 'one' | 'many' | 'none';
99
+ inputs: boolean;
100
+ tags: boolean;
101
+ };
102
+ rerun: {
103
+ all: boolean;
104
+ failedOnly: boolean;
105
+ job: boolean;
106
+ debug: boolean;
107
+ };
108
+ cancel: {
109
+ run: boolean;
110
+ job: boolean;
111
+ };
112
+ };
113
+ /** Раздел ci определения трекера (D-005): на том же подключении, что и задачи. */
114
+ export type CiDefinition = {
115
+ capabilities: CiCapabilities;
116
+ create(context: AdapterContext): CiAdapter;
117
+ };
@@ -0,0 +1,2 @@
1
+ import type { CiDefinition } from './ci.types.ts';
2
+ export declare function githubCi(): CiDefinition;
@@ -0,0 +1,2 @@
1
+ import type { CiDefinition } from './ci.types.ts';
2
+ export declare function gitlabCi(): CiDefinition;
@@ -1,4 +1,12 @@
1
- import type { JsonRequest, JsonResponse } from './tracker.types.ts';
1
+ import type { JsonRequest, JsonResponse, TextRequest, TextResponse } from './tracker.types.ts';
2
2
  export declare function requestJson(url: string, request: JsonRequest): Promise<JsonResponse>;
3
+ /**
4
+ * Запрос текста (лог CI): тело читается потоком, в памяти — только окно keep после skip. head — первые keep.bytes,
5
+ * поток отменяется, как только окно набрано; tail — последние keep.bytes в кольцевом буфере. Чтение обрывается
6
+ * на readMax байт тела. Границы окна сдвигаются к целым символам UTF-8: начало — вперёд, конец — назад (и у тела,
7
+ * оборванного посреди символа). Отказ — как у requestJson: missing, rate_limited, failed с телом без секретов.
8
+ * fetch следует редиректам (302 GitHub на подписанный адрес); по спецификации fetch Authorization на чужой origin не уходит.
9
+ */
10
+ export declare function requestText(url: string, request: TextRequest): Promise<TextResponse>;
3
11
  /** Базовый адрес без хвостовых слэшей; не http и не https — отказ подключения. */
4
12
  export declare function baseUrl(value: string | undefined, fallback: string): string;
@@ -3,6 +3,12 @@ export * from './tracker.types.ts';
3
3
  export * from './tracker.lib.ts';
4
4
  export * from './mapping.const.ts';
5
5
  export * from './http.lib.ts';
6
+ export * from './ci.schema.ts';
7
+ export * from './ci.types.ts';
8
+ export * from './ci.lib.ts';
9
+ export * from './github-ci.lib.ts';
10
+ export * from './gitlab-ci.lib.ts';
11
+ export * from './sourcecraft-ci.lib.ts';
6
12
  export * from './registry.lib.ts';
7
13
  export * from './builtin.lib.ts';
8
14
  export * from './secrets.lib.ts';