@wenathlan/saddle 1.8.2 → 1.8.5
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 +9 -9
- package/browser/playwright.js +22 -0
- package/docs/.gitkeep +0 -0
- package/docs/gapmatrix.md +3 -3
- package/docs/libraryapi.md +1 -0
- package/docs/logs/.gitkeep +0 -0
- package/docs/packageaudit185.md +23 -0
- package/docs/plans/00.index.md +50 -0
- package/docs/plans/01.architecture.md +86 -0
- package/docs/plans/02.research.computer.use.md +58 -0
- package/docs/plans/03.research.captcha.bypass.md +68 -0
- package/docs/plans/04.research.sandbox.ai.md +52 -0
- package/docs/plans/05.capture.platform.md +57 -0
- package/docs/plans/06.dependencies.md +97 -0
- package/docs/plans/07.captcha.test.page.md +41 -0
- package/docs/plans/08.production.infra.md +70 -0
- package/docs/plans/09.database.schema.md +121 -0
- package/docs/plans/10.cloudinary.storage.md +57 -0
- package/docs/plans/11.movement.logs.json.md +72 -0
- package/docs/plans/12.research.atlas.agent.browser.md +79 -0
- package/docs/plans/13.research.anti.detection.md +898 -0
- package/docs/plans/14.research.proxy.md +1495 -0
- package/docs/plans/15.research.retry.rate.limit.md +1958 -0
- package/docs/plans/16.research.crawling.md +1417 -0
- package/docs/plans/17.research.caching.md +1610 -0
- package/docs/plans/18.research.content.extraction.md +1952 -0
- package/docs/plans/19.research.errors.events.md +1523 -0
- package/docs/plans/20.research.zod.validation.md +1350 -0
- package/docs/plans/21.research.batch.concurrency.md +1888 -0
- package/docs/plans/22.research.universal.runtime.md +944 -0
- package/docs/plans/23.research.ai.integration.md +1465 -0
- package/docs/plans/24.research.memory.persistence.md +1979 -0
- package/docs/plans/25.research.server.api.md +342 -0
- package/docs/plans/26.research.compilation.md +249 -0
- package/docs/plans/27.research.html.parsing.md +251 -0
- package/docs/plans/28.action.plan.md +50 -0
- package/docs/plans/29.api.reference.md +174 -0
- package/docs/plans/30.architecture.plan.md +94 -0
- package/docs/plans/31.auditoria.dados.md +163 -0
- package/docs/plans/32.bots.automacao.computacional.md +214 -0
- package/docs/plans/33.bots.codigo.revisao.md +220 -0
- package/docs/plans/34.bots.seguranca.cicd.md +366 -0
- package/docs/plans/35.comparativo.concorrencia.md +464 -0
- package/docs/plans/36.computational.memory.md +340 -0
- package/docs/plans/37.deploystrategy.md +394 -0
- package/docs/plans/38.flow.md +155 -0
- package/docs/plans/39.multi.platform.bot.md +252 -0
- package/docs/plans/40.npm.publish.md +250 -0
- package/docs/plans/41.o.que.falta.md +407 -0
- package/docs/plans/42.pesquisa.concorrencia.md +721 -0
- package/docs/plans/43.plan.universal.architecture.md +496 -0
- package/docs/plans/44.reference.md +100 -0
- package/docs/plans/45.robotarchitecture.md +237 -0
- package/docs/plans/46.scdnintegration.md +284 -0
- package/docs/plans/47.multiforge.readme.md +129 -0
- package/docs/plans/48.theory.v4.repo.os.md +152 -0
- package/docs/plans/49.third.party.infra.md +12 -0
- package/docs/plans/50.file.as.compute.md +39 -0
- package/docs/plans/51.architecture.virtual.processor.md +80 -0
- package/docs/plans/52.manifesto.v8.md +11 -0
- package/docs/plans/58.cdn.list.md +23 -0
- package/docs/plans/59.sql.frameworks.md +33 -0
- package/docs/plans/60.sql.thirdparty.md +26 -0
- package/docs/plans/61.objective.multiforge.md +63 -0
- package/docs/plans/62.huggingface.upload.md +26 -0
- package/docs/plans/63.kaggle.upload.md +24 -0
- package/docs/plans/64.npm.storage.md +30 -0
- package/docs/plans/65.rclone.terabox.md +32 -0
- package/docs/plans/66.buckets.and.models.todo.md +14 -0
- package/docs/plans/67.database.todo.md +13 -0
- package/docs/plans/68.deploy.packages.todo.md +12 -0
- package/docs/plans/69.report.human.operator.md +133 -0
- package/docs/plans/70.report.brain2qwerty.ems.md +135 -0
- package/docs/plans/71.report.hd.infinito.vram.md +155 -0
- package/docs/plans/72.plan.hd.infinito.node.md +146 -0
- package/docs/plans/73.plan.scifi.repos.md +125 -0
- package/docs/plans/74.000.manifesto.v8.flat.2..md +11 -0
- package/docs/plans/README.md +489 -0
- package/docs/plans/aggregate_platforms.mjs +146 -0
- package/docs/plans/examplesession.json +36 -0
- package/docs/plans/missing-facts.md +192 -0
- package/docs/plans/models.md +64 -0
- package/docs/plans/organize.cjs +270 -0
- package/docs/plans/platforms.md +2887 -0
- package/docs/plans/sites.md +31322 -0
- package/docs/platformpipelineaudit.md +18 -0
- package/docs/platformpipelines.md +13 -0
- package/docs/registryresearch.md +4 -0
- package/docs/release.md +4 -4
- package/docs/release182notes.md +2 -0
- package/docs/release184notes.md +7 -0
- package/docs/release185notes.md +7 -0
- package/docs/sources/farm.py +117 -0
- package/docs/sources/html/saddle1.html +132 -0
- package/docs/sources/html/saddle2.html +157 -0
- package/docs/sources/html/saddle3.html +119 -0
- package/docs/sources/html/saddle4.html +144 -0
- package/docs/sources/html/saddle5.html +72 -0
- package/docs/sources/html/saddle6.html +171 -0
- package/docs/sources/html/saddle7.html +236 -0
- package/docs/sources/saddle.ts +74 -0
- package/docs/sources/schema.prisma +88 -0
- package/docs/sources/script.sh +64 -0
- package/docs/sources/workflows.yml +458 -0
- package/docs/talks1/_body.txt +14 -0
- package/docs/talks1/_index.md +15 -0
- package/docs/talks1/_screenshot.png +0 -0
- package/docs/talks1/assistant-01.md +5 -0
- package/docs/talks1/assistant-02.md +5 -0
- package/docs/talks1/assistant-03.md +531 -0
- package/docs/talks1/assistant-04.md +26 -0
- package/docs/talks1/assistant-05.md +774 -0
- package/docs/talks1/assistant-06.md +1718 -0
- package/docs/talks1/scrape-share.cjs +185 -0
- package/docs/talks1/scrape-share.ts +183 -0
- package/docs/talks1/user-01.md +3 -0
- package/docs/talks1/user-02.md +3 -0
- package/docs/talks1/user-03.md +88 -0
- package/docs/talks1/user-04.md +3 -0
- package/docs/talks1/user-05.md +3 -0
- package/docs/talks1/user-06.md +88 -0
- package/docs/talks1/user-07.md +88 -0
- package/docs/talks2/_body.txt +14 -0
- package/docs/talks2/_index.md +16 -0
- package/docs/talks2/_screenshot.png +0 -0
- package/docs/talks2/assistant-01.md +5 -0
- package/docs/talks2/assistant-02.md +5 -0
- package/docs/talks2/assistant-03.md +424 -0
- package/docs/talks2/assistant-04.md +598 -0
- package/docs/talks2/assistant-05.md +1280 -0
- package/docs/talks2/assistant-06.md +1227 -0
- package/docs/talks2/assistant-07.md +1252 -0
- package/docs/talks2/user-01.md +3 -0
- package/docs/talks2/user-02.md +3 -0
- package/docs/talks2/user-03.md +88 -0
- package/docs/talks2/user-04.md +88 -0
- package/docs/talks2/user-05.md +88 -0
- package/docs/talks2/user-06.md +88 -0
- package/docs/talks2/user-07.md +3 -0
- package/docs/talks3/_body.txt +467 -0
- package/docs/talks3/_index.md +10 -0
- package/docs/talks3/_screenshot.png +0 -0
- package/docs/talks3/assistant-01.md +417 -0
- package/docs/talks3/assistant-02.md +417 -0
- package/docs/talks3/assistant-03.md +29 -0
- package/docs/talks3/assistant-04.md +727 -0
- package/docs/talks3/user-01.md +88 -0
- package/docs/talks3/user-02.md +88 -0
- package/docs/talks3/user-03.md +3 -0
- package/docs/talks3/user-04.md +3 -0
- package/docs/talks4/_body.txt +14 -0
- package/docs/talks4/_index.md +12 -0
- package/docs/talks4/_screenshot.png +0 -0
- package/docs/talks4/assistant-01.md +5 -0
- package/docs/talks4/assistant-02.md +5 -0
- package/docs/talks4/assistant-03.md +35 -0
- package/docs/talks4/assistant-04.md +512 -0
- package/docs/talks4/assistant-05.md +599 -0
- package/docs/talks4/user-01.md +3 -0
- package/docs/talks4/user-02.md +3 -0
- package/docs/talks4/user-03.md +88 -0
- package/docs/talks4/user-04.md +88 -0
- package/docs/talks4/user-05.md +7 -0
- package/docs/talks5/_body.txt +14 -0
- package/docs/talks5/_index.md +13 -0
- package/docs/talks5/_screenshot.png +0 -0
- package/docs/talks5/assistant-01.md +5 -0
- package/docs/talks5/assistant-02.md +5 -0
- package/docs/talks5/assistant-03.md +690 -0
- package/docs/talks5/assistant-04.md +758 -0
- package/docs/talks5/assistant-05.md +974 -0
- package/docs/talks5/user-01.md +3 -0
- package/docs/talks5/user-02.md +3 -0
- package/docs/talks5/user-03.md +105 -0
- package/docs/talks5/user-04.md +105 -0
- package/docs/talks5/user-05.md +63 -0
- package/docs/talks5/user-06.md +105 -0
- package/docs/talks6/_body.txt +14 -0
- package/docs/talks6/_index.md +9 -0
- package/docs/talks6/_screenshot.png +0 -0
- package/docs/talks6/assistant-01.md +5 -0
- package/docs/talks6/assistant-02.md +5 -0
- package/docs/talks6/assistant-03.md +1499 -0
- package/docs/talks6/user-01.md +3 -0
- package/docs/talks6/user-02.md +3 -0
- package/docs/talks6/user-03.md +88 -0
- package/docs/talks6/user-04.md +88 -0
- package/docs/talks7/_body.txt +14 -0
- package/docs/talks7/_index.md +10 -0
- package/docs/talks7/_screenshot.png +0 -0
- package/docs/talks7/assistant-01.md +5 -0
- package/docs/talks7/assistant-02.md +5 -0
- package/docs/talks7/assistant-03.md +523 -0
- package/docs/talks7/assistant-04.md +617 -0
- package/docs/talks7/user-01.md +3 -0
- package/docs/talks7/user-02.md +3 -0
- package/docs/talks7/user-03.md +105 -0
- package/docs/talks7/user-04.md +67 -0
- package/docs/talks8/conversa1.txt +1322 -0
- package/docs/talks8/conversa2.txt +237 -0
- package/docs/talks9/Beyond the Obvious_ 50 Plataformas Auto-Hospedadas de Forja de C/303/263digo para Al/303/251m de Gitea e GitLab.md" +174 -0
- package/docs/talks9/De NPM a Multi-Linguagem_ Uma Arquitetura T/303/251cnica para a Execu/303/247/303/243o Integrada de C/303/263digo no Ecossistema Node.js.md" +59 -0
- package/docs/talks9/De NPM a VMs Virtuais_ Uma An/303/241lise Arquitet/303/264nica para a Realiza/303/247/303/243o do Ciclo de Vida do Projeto SADDLE.md" +91 -0
- package/docs/talks9/Mapeamento da Engrenagem Computacional_ Uma Arquitetura para Execu/303/247/303/243o Isolada e Persist/303/252ncia em Ambientes Distribu/303/255dos.md" +116 -0
- package/docs/talks9/O Cen/303/241rio Pr/303/241tico do SADDLE_ Uma An/303/241lise de Viabilidade e Modelo de Ciclo de Vida Integrado.md" +128 -0
- package/docs/talks9/README (2).md +489 -0
- package/docs/talks9/README.md +198 -0
- package/docs/talks9/Viabilidade do Saddle_ Uma An/303/241lise T/303/251cnica da Transforma/303/247/303/243o de Armazenamento Remoto em Mem/303/263ria Computacional.md" +80 -0
- package/docs/talks9/conversa.txt +544 -0
- package/docs/talks9/other (2).md +39 -0
- package/docs/talks9/other.md +57 -0
- package/docs/talks9/outro.txt +24 -0
- package/extension/README.md +3 -3
- package/extension/serviceworker.js +63 -4
- package/extension/worker.js +3 -1
- package/package.json +12 -2
- package/packager/manifest.js +1 -1
- package/scrape/agent.ts +122 -0
- package/scrape/batch.ts +79 -0
- package/scrape/biome.json +76 -0
- package/scrape/browser.ts +222 -0
- package/scrape/cache.ts +84 -0
- package/scrape/chunking.ts +193 -0
- package/scrape/cli.ts +105 -0
- package/scrape/crawler.ts +115 -0
- package/scrape/dev-server.ts +94 -0
- package/scrape/errors.ts +132 -0
- package/scrape/events.ts +26 -0
- package/scrape/extract.ts +165 -0
- package/scrape/fetch.ts +105 -0
- package/scrape/formats.ts +85 -0
- package/scrape/headers.ts +71 -0
- package/scrape/index.ts +92 -0
- package/scrape/jsdom.d.ts +6 -0
- package/scrape/llms-txt.ts +84 -0
- package/scrape/middleware.ts +90 -0
- package/scrape/package-lock.json +9397 -0
- package/scrape/package.json +1420 -0
- package/scrape/pool.ts +95 -0
- package/scrape/port.ts +18 -0
- package/scrape/proxy.ts +103 -0
- package/scrape/rate-limiter.ts +95 -0
- package/scrape/renderer.ts +194 -0
- package/scrape/retry.ts +64 -0
- package/scrape/robots.ts +137 -0
- package/scrape/scrape.ts +123 -0
- package/scrape/serialize.ts +310 -0
- package/scrape/server.ts +137 -0
- package/scrape/session.ts +109 -0
- package/scrape/sitemap.ts +131 -0
- package/scrape/tokens.ts +45 -0
- package/scrape/tsconfig.json +28 -0
- package/scrape/types.ts +214 -0
- package/scrape/utils.ts +77 -0
- package/scrape/vite.config.ts +55 -0
- package/scrape/vitest.config.ts +17 -0
- package/workflow/templates.js +4 -4
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Scraping Pipeline Flow
|
|
2
|
+
|
|
3
|
+
## High-Level Pipeline
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
User Input (URL or HTML)
|
|
7
|
+
│
|
|
8
|
+
▼
|
|
9
|
+
┌──────────────────────┐
|
|
10
|
+
│ scrapeUrl() │
|
|
11
|
+
│ ┌────────────────┐ │
|
|
12
|
+
│ │ AgentBrowser │ │
|
|
13
|
+
│ │ ┌──────────┐ │ │
|
|
14
|
+
│ │ │ Launch │ │ │
|
|
15
|
+
│ │ │ Browser │ │ │
|
|
16
|
+
│ │ └────┬─────┘ │ │
|
|
17
|
+
│ │ ▼ │ │
|
|
18
|
+
│ │ ┌──────────┐ │ │
|
|
19
|
+
│ │ │ Navigate │ │ │
|
|
20
|
+
│ │ │ to URL │ │ │
|
|
21
|
+
│ │ └────┬─────┘ │ │
|
|
22
|
+
│ │ ▼ │ │
|
|
23
|
+
│ │ ┌──────────┐ │ │
|
|
24
|
+
│ │ │ Scroll / │ │ │
|
|
25
|
+
│ │ │ Interact │ │ │
|
|
26
|
+
│ │ └────┬─────┘ │ │
|
|
27
|
+
│ │ ▼ │ │
|
|
28
|
+
│ │ ┌──────────┐ │ │
|
|
29
|
+
│ │ │ Extract │ │ │
|
|
30
|
+
│ │ │ HTML │ │ │
|
|
31
|
+
│ │ └──────────┘ │ │
|
|
32
|
+
│ └────────────────┘ │
|
|
33
|
+
│ │ │
|
|
34
|
+
│ ▼ │
|
|
35
|
+
│ ┌────────────────┐ │
|
|
36
|
+
│ │ extractContent │ │
|
|
37
|
+
│ │ (Cheerio parse) │ │
|
|
38
|
+
│ └────────────────┘ │
|
|
39
|
+
└──────────┬───────────┘
|
|
40
|
+
│ ScrapeResult
|
|
41
|
+
▼
|
|
42
|
+
┌──────────────────────┐
|
|
43
|
+
│ serializeResult() │
|
|
44
|
+
│ Format: markdown / │
|
|
45
|
+
│ json / xml / redis │
|
|
46
|
+
│ / text │
|
|
47
|
+
└──────────┬───────────┘
|
|
48
|
+
│ SerializedOutput
|
|
49
|
+
▼
|
|
50
|
+
┌──────────────────────┐
|
|
51
|
+
│ formatForAgent() │
|
|
52
|
+
│ (LLM-friendly) │
|
|
53
|
+
│ or render with │
|
|
54
|
+
│ PygameRenderer │
|
|
55
|
+
└──────────────────────┘
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Execution Paths
|
|
59
|
+
|
|
60
|
+
### URL Scraping
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
scrapeUrl(url, options)
|
|
64
|
+
├── AgentBrowser.launch('chromium')
|
|
65
|
+
├── AgentBrowser.navigate(url)
|
|
66
|
+
├── [optional] AgentBrowser.scrollToBottom()
|
|
67
|
+
├── AgentBrowser.html() → raw HTML
|
|
68
|
+
├── AgentBrowser.screenshot() → Buffer
|
|
69
|
+
├── extractContent(html) → ExtractedContent
|
|
70
|
+
├── AgentBrowser.close()
|
|
71
|
+
└── returns ScrapeResult { url, title, html, text, links, images, tables, metadata, screenshot }
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### HTML Scraping (offline)
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
scrapeHtml(html, options)
|
|
78
|
+
├── extractContent(html) → ExtractedContent
|
|
79
|
+
└── returns ScrapeResult { url: 'inline', html, ...extracted }
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Browser Reuse
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
scrapeWithBrowser(browser, url, options)
|
|
86
|
+
├── browser.navigate(url)
|
|
87
|
+
├── browser.html()
|
|
88
|
+
├── extractContent(html)
|
|
89
|
+
└── returns ScrapeResult
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Data Flow
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
Raw HTML
|
|
96
|
+
│
|
|
97
|
+
▼
|
|
98
|
+
Cheerio.parse(html)
|
|
99
|
+
│
|
|
100
|
+
├── Title: $('title').text() / $('h1').first().text()
|
|
101
|
+
├── Author: $('[rel=author]') / meta tags
|
|
102
|
+
├── Text: $('p, li, blockquote').text() (joined)
|
|
103
|
+
├── Links: $('a[href]') → { href, text }
|
|
104
|
+
├── Images: $('img[src]') → { src, alt }
|
|
105
|
+
├── Tables: $('table') → { headers, rows }
|
|
106
|
+
└── Metadata: meta tags → { description, keywords, og:* }
|
|
107
|
+
│
|
|
108
|
+
▼
|
|
109
|
+
ExtractedContent
|
|
110
|
+
│
|
|
111
|
+
▼
|
|
112
|
+
serializeResult(result, { format })
|
|
113
|
+
│
|
|
114
|
+
├── markdown: TurndownService.turndown(html)
|
|
115
|
+
├── json: JSON.stringify(content)
|
|
116
|
+
├── xml: xml2js.Builder.buildObject(content)
|
|
117
|
+
├── redis: JSON.SET key path value
|
|
118
|
+
└── text: strip tags + join
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Serialization Flow
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
serializeResult(result, options)
|
|
125
|
+
│
|
|
126
|
+
├── resolveFormat(options.format) → format name
|
|
127
|
+
├── resolveExtension(formatName) → file extension
|
|
128
|
+
│
|
|
129
|
+
├── format === 'markdown'
|
|
130
|
+
│ └── TurndownService.turndown(html)
|
|
131
|
+
│
|
|
132
|
+
├── format === 'json'
|
|
133
|
+
│ └── JSON.stringify(content, null, pretty ? 2 : 0)
|
|
134
|
+
│
|
|
135
|
+
├── format === 'xml'
|
|
136
|
+
│ └── xml2js.Builder.buildObject({ root: content })
|
|
137
|
+
│
|
|
138
|
+
├── format === 'redis'
|
|
139
|
+
│ └── "JSON.SET key $ '...escaped json...'\n"
|
|
140
|
+
│
|
|
141
|
+
└── format === 'text'
|
|
142
|
+
└── strip all HTML tags, join text nodes
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Agent Output Flow
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
formatForAgent(result)
|
|
149
|
+
│
|
|
150
|
+
├── Build summary (first 200 chars of text)
|
|
151
|
+
├── Extract key points (sentences with key phrases)
|
|
152
|
+
├── Collect relevant URLs
|
|
153
|
+
├── Chunk content for token limits
|
|
154
|
+
└── Returns { summary, keyPoints, content, relevantUrls, chunks, tokenCount }
|
|
155
|
+
```
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# Saddle Multi-Platform Bot
|
|
2
|
+
|
|
3
|
+
> Bot that operates across GitHub, GitLab, Forgejo, Gitea, and Discord.
|
|
4
|
+
> Unified interface for all platform integrations.
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
The saddle robot operates as a bot across multiple code
|
|
9
|
+
hosting platforms and messaging services through a unified
|
|
10
|
+
adapter interface. Each platform has a dedicated adapter
|
|
11
|
+
implementing the same interface contract.
|
|
12
|
+
|
|
13
|
+
## Platform Adapters
|
|
14
|
+
|
|
15
|
+
### GitHub Adapter
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
interface GitHubAdapter {
|
|
19
|
+
type: 'github'
|
|
20
|
+
authenticate(token: string): Promise<boolean>
|
|
21
|
+
listRepos(query?: string): Promise<Repo[]>
|
|
22
|
+
getRepo(owner: string, repo: string): Promise<Repo>
|
|
23
|
+
createIssue(repo: string, title: string, body: string): Promise<Issue>
|
|
24
|
+
createPR(repo: string, title: string, body: string, branch: string): Promise<PR>
|
|
25
|
+
addComment(repo: string, issueNumber: number, body: string): Promise<Comment>
|
|
26
|
+
createWebhook(repo: string, url: string, events: string[]): Promise<Webhook>
|
|
27
|
+
executeWorkflow(repo: string, workflow: string): Promise<WorkflowRun>
|
|
28
|
+
uploadReleaseAsset(repo: string, tag: string, name: string, path: string): Promise<Asset>
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Authentication uses a personal access token or GitHub App token.
|
|
33
|
+
|
|
34
|
+
Token scopes required:
|
|
35
|
+
- `repo` (full control)
|
|
36
|
+
- `workflow` (manage workflows)
|
|
37
|
+
- `read:org` (read organization data)
|
|
38
|
+
|
|
39
|
+
### GitLab Adapter
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
interface GitLabAdapter {
|
|
43
|
+
type: 'gitlab'
|
|
44
|
+
authenticate(token: string): Promise<boolean>
|
|
45
|
+
listProjects(query?: string): Promise<Project[]>
|
|
46
|
+
getProject(id: number | string): Promise<Project>
|
|
47
|
+
createIssue(projectId: number, title: string, description: string): Promise<Issue>
|
|
48
|
+
createMergeRequest(projectId: number, title: string, description: string, sourceBranch: string, targetBranch: string): Promise<MR>
|
|
49
|
+
addComment(projectId: number, noteableType: string, noteableId: number, body: string): Promise<Note>
|
|
50
|
+
createWebhook(projectId: number, url: string, events: string[]): Promise<Webhook>
|
|
51
|
+
triggerPipeline(projectId: number, ref: string, variables: Record<string, string>): Promise<Pipeline>
|
|
52
|
+
uploadFile(projectId: number, filePath: string, content: Buffer): Promise<Attachment>
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Authentication uses a personal access token with `api` scope.
|
|
57
|
+
|
|
58
|
+
### Forgejo Adapter
|
|
59
|
+
|
|
60
|
+
Forgejo is fully compatible with the GitHub API, making the
|
|
61
|
+
GitHub adapter usable with minimal configuration changes.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
interface ForgejoAdapter {
|
|
65
|
+
extends: GitHubAdapter
|
|
66
|
+
customBaseUrl: string
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Configuration:
|
|
71
|
+
- Use GitHub adapter with custom `baseUrl` pointing to Forgejo instance
|
|
72
|
+
- Token type: access token with `write:repository`, `write:issue`, `write:webhook` scopes
|
|
73
|
+
|
|
74
|
+
### Gitea Adapter
|
|
75
|
+
|
|
76
|
+
Gitea also provides GitHub-compatible API endpoints.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
interface GiteaAdapter {
|
|
80
|
+
extends: GitHubAdapter
|
|
81
|
+
customBaseUrl: string
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Configuration:
|
|
86
|
+
- Use GitHub adapter with custom `baseUrl` pointing to Gitea instance
|
|
87
|
+
- Token type: API token with full repository scope
|
|
88
|
+
|
|
89
|
+
### Discord Adapter
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
interface DiscordAdapter {
|
|
93
|
+
type: 'discord'
|
|
94
|
+
authenticate(token: string): Promise<boolean>
|
|
95
|
+
sendMessage(channelId: string, content: string): Promise<Message>
|
|
96
|
+
createWebhook(channelId: string, name: string): Promise<Webhook>
|
|
97
|
+
executeWebhook(webhookId: string, webhookToken: string, payload: WebhookPayload): Promise<Message>
|
|
98
|
+
addReaction(channelId: string, messageId: string, emoji: string): Promise<void>
|
|
99
|
+
createThread(channelId: string, name: string, messageId: string): Promise<Thread>
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Unified Bot Interface
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
interface SaddleBot {
|
|
107
|
+
platform: PlatformAdapter
|
|
108
|
+
config: BotConfig
|
|
109
|
+
|
|
110
|
+
start(): Promise<void>
|
|
111
|
+
stop(): Promise<void>
|
|
112
|
+
executeCommand(command: BotCommand): Promise<BotResult>
|
|
113
|
+
handleWebhook(event: WebhookEvent): Promise<void>
|
|
114
|
+
scheduleTask(task: ScheduledTask): Promise<ScheduledTaskHandle>
|
|
115
|
+
getStatus(): Promise<BotStatus>
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Bot Config
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
interface BotConfig {
|
|
123
|
+
platforms: PlatformConfig[]
|
|
124
|
+
memoryEngine: MemoryEngineConfig
|
|
125
|
+
deploy: DeployConfig
|
|
126
|
+
logging: LogConfig
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
interface PlatformConfig {
|
|
130
|
+
type: 'github' | 'gitlab' | 'forgejo' | 'gitea' | 'discord'
|
|
131
|
+
name: string
|
|
132
|
+
token: string
|
|
133
|
+
baseUrl?: string
|
|
134
|
+
webhookSecret?: string
|
|
135
|
+
repositories: string[]
|
|
136
|
+
channels: string[]
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Bot Commands
|
|
141
|
+
|
|
142
|
+
| Command | Description | Platforms |
|
|
143
|
+
|---------|-------------|-----------|
|
|
144
|
+
| `capture` | Start browser capture session | All |
|
|
145
|
+
| `scrape` | Scrape URLs and extract content | All |
|
|
146
|
+
| `review` | Review PRs/issues automatically | GitHub, GitLab, Forgejo, Gitea |
|
|
147
|
+
| `deploy` | Deploy to target platform | GitHub, GitLab, Forgejo |
|
|
148
|
+
| `memory` | Store/retrieve memory objects | All |
|
|
149
|
+
| `status` | Report bot status | All |
|
|
150
|
+
| `test` | Run test suite | GitHub, GitLab, Forgejo |
|
|
151
|
+
| `release` | Create release with assets | GitHub, GitLab, Forgejo |
|
|
152
|
+
| `webhook` | Manage webhooks | GitHub, GitLab, Forgejo, Gitea |
|
|
153
|
+
| `schedule` | Schedule recurring tasks | All |
|
|
154
|
+
| `npm publish` | Publish NPM package | GitHub |
|
|
155
|
+
| `artifact` | Upload artifacts to storage | All |
|
|
156
|
+
|
|
157
|
+
## Multi-Platform Workflow
|
|
158
|
+
|
|
159
|
+
A typical workflow uses the saddle robot across platforms:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
1. Discord webhook receives user command
|
|
163
|
+
2. Saddle robot parses command
|
|
164
|
+
3. Bot selects target platform adapter
|
|
165
|
+
4. Executes command on target platform
|
|
166
|
+
5. Stores result in memory backend
|
|
167
|
+
6. Reports status back to Discord
|
|
168
|
+
7. Optionally triggers CI/CD pipeline
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Webhook Integration
|
|
172
|
+
|
|
173
|
+
### GitHub Webhooks
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
{
|
|
177
|
+
"webhooks": [
|
|
178
|
+
{
|
|
179
|
+
"url": "https://saddle.example.com/webhook/github",
|
|
180
|
+
"content_type": "json",
|
|
181
|
+
"secret": "${WEBHOOK_SECRET}",
|
|
182
|
+
"events": [
|
|
183
|
+
"push",
|
|
184
|
+
"pull_request",
|
|
185
|
+
"issues",
|
|
186
|
+
"issue_comment",
|
|
187
|
+
"release",
|
|
188
|
+
"deployment"
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### GitLab Webhooks
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"webhooks": [
|
|
200
|
+
{
|
|
201
|
+
"url": "https://saddle.example.com/webhook/gitlab",
|
|
202
|
+
"secret_token": "${WEBHOOK_SECRET}",
|
|
203
|
+
"trigger_events": true,
|
|
204
|
+
"push_events": true,
|
|
205
|
+
"merge_request_events": true,
|
|
206
|
+
"issue_events": true,
|
|
207
|
+
"tag_push_events": true
|
|
208
|
+
}
|
|
209
|
+
]
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Deployment per Platform
|
|
214
|
+
|
|
215
|
+
| Platform | Deploy Method | Best For |
|
|
216
|
+
|----------|--------------|----------|
|
|
217
|
+
| GitHub | GitHub Actions + NPM package | Team collaboration |
|
|
218
|
+
| GitLab | GitLab CI + Docker | Self-hosted or cloud |
|
|
219
|
+
| Forgejo | Forgejo Actions + Docker | Lightweight self-hosted |
|
|
220
|
+
| Gitea | Gitea Actions + Docker | Minimal self-hosted |
|
|
221
|
+
| Discord | Discord bot token + HTTPS | Messaging integration |
|
|
222
|
+
|
|
223
|
+
## Error Handling
|
|
224
|
+
|
|
225
|
+
Each adapter implements error handling with contextual error
|
|
226
|
+
messages for later tracing. Adapter failures are caught and
|
|
227
|
+
reported without crashing the bot.
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
class SafeAdapter {
|
|
231
|
+
private adapter: PlatformAdapter
|
|
232
|
+
|
|
233
|
+
async execute(
|
|
234
|
+
method: string,
|
|
235
|
+
...args: unknown[]
|
|
236
|
+
): Promise<{ success: boolean; result?: unknown; error?: string }> {
|
|
237
|
+
try {
|
|
238
|
+
const result = await (this.adapter as Record<string, unknown>)[method](...args)
|
|
239
|
+
return { success: true, result }
|
|
240
|
+
} catch (error) {
|
|
241
|
+
return {
|
|
242
|
+
success: false,
|
|
243
|
+
error: error instanceof Error ? error.message : String(error),
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## License
|
|
251
|
+
|
|
252
|
+
MIT
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# NPM Package Publishing for Saddle Robot
|
|
2
|
+
|
|
3
|
+
> Package `@devthink/saddle` published to NPM registry.
|
|
4
|
+
> Acts as both library and CLI binary.
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Saddle robot is published as an NPM package for easy
|
|
9
|
+
distribution as a library and a CLI tool. The package
|
|
10
|
+
includes browser automation, bot functionality, captcha
|
|
11
|
+
bypass, and memory engine capabilities.
|
|
12
|
+
|
|
13
|
+
## Package Configuration
|
|
14
|
+
|
|
15
|
+
### package.json
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"name": "@devthink/saddle",
|
|
20
|
+
"version": "1.0.0",
|
|
21
|
+
"description": "Super bot: agent browser, captcha bypass, multi-platform GitHub/GitLab/Forgejo/Gitea automation with computational memory",
|
|
22
|
+
"main": "lib/index.js",
|
|
23
|
+
"bin": {
|
|
24
|
+
"saddle": "bin/saddle.js"
|
|
25
|
+
},
|
|
26
|
+
"type": "module",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"import": "./lib/index.js",
|
|
30
|
+
"require": "./lib/index.cjs"
|
|
31
|
+
},
|
|
32
|
+
"./browser": {
|
|
33
|
+
"import": "./lib/browser.js"
|
|
34
|
+
},
|
|
35
|
+
"./bot": {
|
|
36
|
+
"import": "./lib/bot.js"
|
|
37
|
+
},
|
|
38
|
+
"./ captcha": {
|
|
39
|
+
"import": "./lib/captcha.js"
|
|
40
|
+
},
|
|
41
|
+
"./memory-engine": {
|
|
42
|
+
"import": "./lib/memory-engine.js"
|
|
43
|
+
},
|
|
44
|
+
"./deploy": {
|
|
45
|
+
"import": "./lib/deploy.js"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc",
|
|
50
|
+
"test": "vitest run",
|
|
51
|
+
"lint": "biome check .",
|
|
52
|
+
"typecheck": "tsc --noEmit",
|
|
53
|
+
"prepublishOnly": "npm run build && npm test",
|
|
54
|
+
"prepare": "husky"
|
|
55
|
+
},
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "https://github.com/username/saddle.git"
|
|
59
|
+
},
|
|
60
|
+
"keywords": [
|
|
61
|
+
"agent",
|
|
62
|
+
"browser",
|
|
63
|
+
"automation",
|
|
64
|
+
"bot",
|
|
65
|
+
"captcha-bypass",
|
|
66
|
+
"github-bot",
|
|
67
|
+
"gitlab-bot",
|
|
68
|
+
"scraper",
|
|
69
|
+
"computer-use",
|
|
70
|
+
"ai-agent"
|
|
71
|
+
],
|
|
72
|
+
"author": "iakadion",
|
|
73
|
+
"license": "MIT",
|
|
74
|
+
"bugs": {
|
|
75
|
+
"url": "https://github.com/username/saddle/issues"
|
|
76
|
+
},
|
|
77
|
+
"homepage": "https://github.com/username/saddle#readme"
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Publishing Steps
|
|
82
|
+
|
|
83
|
+
### 1. Build and Test
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm run build
|
|
87
|
+
npm test
|
|
88
|
+
npm run lint
|
|
89
|
+
npm run typecheck
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
All checks must pass before publishing.
|
|
93
|
+
|
|
94
|
+
### 2. Login to NPM
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npm login
|
|
98
|
+
# Enter NPM credentials (token recommended)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 3. Publish
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Publish as public package
|
|
105
|
+
npm publish --access public
|
|
106
|
+
|
|
107
|
+
# Publish as scoped package
|
|
108
|
+
npm publish --access public
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 4. Version Bumping
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Patch version (1.0.0 → 1.0.1)
|
|
115
|
+
npm version patch
|
|
116
|
+
|
|
117
|
+
# Minor version (1.0.0 → 1.1.0)
|
|
118
|
+
npm version minor
|
|
119
|
+
|
|
120
|
+
# Major version (1.0.0 → 2.0.0)
|
|
121
|
+
npm version major
|
|
122
|
+
|
|
123
|
+
# Push tags after version bump
|
|
124
|
+
git push --follow-tags
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Installation
|
|
128
|
+
|
|
129
|
+
### As Library
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npm install @devthink/saddle
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
import { SaddleRobot } from '@devthink/saddle'
|
|
137
|
+
|
|
138
|
+
const robot = new SaddleRobot({
|
|
139
|
+
platform: 'github',
|
|
140
|
+
token: process.env.SBOT_TOKEN,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
await robot.start()
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### As CLI
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
npm install -g @devthink/saddle
|
|
150
|
+
|
|
151
|
+
saddle --help
|
|
152
|
+
saddle capture --url https://example.com
|
|
153
|
+
saddle bot --platform github --token $SBOT_TOKEN
|
|
154
|
+
saddle memory --load repo://owner/repo/path/file.json
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Binary Entry Point
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
#!/usr/bin/env node
|
|
161
|
+
|
|
162
|
+
import { SaddleRobot } from '../lib/index.js'
|
|
163
|
+
import { parseArgs } from 'node:util'
|
|
164
|
+
|
|
165
|
+
const options = parseArgs({
|
|
166
|
+
options: {
|
|
167
|
+
command: { type: 'string' },
|
|
168
|
+
platform: { type: 'string' },
|
|
169
|
+
token: { type: 'string' },
|
|
170
|
+
verbose: { type: 'boolean' },
|
|
171
|
+
},
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
const { values } = options
|
|
175
|
+
const robot = new SaddleRobot({
|
|
176
|
+
platform: values.platform ?? 'auto',
|
|
177
|
+
token: values.token ?? '',
|
|
178
|
+
verbose: values.verbose ?? false,
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
async function main() {
|
|
182
|
+
try {
|
|
183
|
+
const command = values.command ?? 'help'
|
|
184
|
+
await robot.start()
|
|
185
|
+
const result = await robot.executeCommand(command)
|
|
186
|
+
if (values.verbose) {
|
|
187
|
+
console.log(JSON.stringify(result, null, 2))
|
|
188
|
+
}
|
|
189
|
+
} catch (error) {
|
|
190
|
+
console.error(
|
|
191
|
+
`saddle: ${error instanceof Error ? error.message : String(error)}`
|
|
192
|
+
)
|
|
193
|
+
process.exit(1)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
main()
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Scoped Package Structure
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
@devthink/saddle/
|
|
204
|
+
├── lib/
|
|
205
|
+
│ ├── index.js main entry point
|
|
206
|
+
│ ├── index.cjs CommonJS entry point
|
|
207
|
+
│ ├── browser.js browser automation engine
|
|
208
|
+
│ ├── bot.js multi-platform bot engine
|
|
209
|
+
│ ├── captcha.js captcha bypass module
|
|
210
|
+
│ ├── memory-engine.js storage-to-compute memory
|
|
211
|
+
│ ├── deploy.js deploy strategy implementations
|
|
212
|
+
│ └── adapters/
|
|
213
|
+
│ ├── github.js GitHub platform adapter
|
|
214
|
+
│ ├── gitlab.js GitLab platform adapter
|
|
215
|
+
│ ├── forgejo.js Forgejo platform adapter
|
|
216
|
+
│ ├── gitea.js Gitea platform adapter
|
|
217
|
+
│ └── discord.js Discord messaging adapter
|
|
218
|
+
├── bin/
|
|
219
|
+
│ └── saddle.js CLI entry point
|
|
220
|
+
├── types/
|
|
221
|
+
│ └── index.d.ts TypeScript declarations
|
|
222
|
+
├── docs/
|
|
223
|
+
│ └── index.md package documentation
|
|
224
|
+
├── package.json
|
|
225
|
+
└── README.md
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Versioning Strategy
|
|
229
|
+
|
|
230
|
+
Follow semantic versioning (semver):
|
|
231
|
+
|
|
232
|
+
| Change Type | Version Bump |
|
|
233
|
+
|-------------|-------------|
|
|
234
|
+
| Bug fix | Patch (1.x.X) |
|
|
235
|
+
| New backward-compatible feature | Minor (1.X.0) |
|
|
236
|
+
| Breaking change | Major (X.0.0) |
|
|
237
|
+
|
|
238
|
+
## Pre-publish Checklist
|
|
239
|
+
|
|
240
|
+
1. All tests pass (`npm test`)
|
|
241
|
+
2. Linting passes (`npm run lint`)
|
|
242
|
+
3. TypeScript checks pass (`npm run typecheck`)
|
|
243
|
+
4. Build succeeds (`npm run build`)
|
|
244
|
+
5. README is updated
|
|
245
|
+
6. Changelog is updated
|
|
246
|
+
7. No breaking changes without major version bump
|
|
247
|
+
|
|
248
|
+
## License
|
|
249
|
+
|
|
250
|
+
MIT
|