@wenathlan/saddle 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/LICENSE +203 -0
  2. package/README.md +192 -0
  3. package/adapters/forge.js +16 -0
  4. package/adapters/forgejo.js +8 -0
  5. package/adapters/github.js +19 -0
  6. package/adapters/gitlab.js +10 -0
  7. package/adapters/huggingface.js +6 -0
  8. package/adapters/socket.js +14 -0
  9. package/adapters/transport.js +30 -0
  10. package/ai/chunk.js +22 -0
  11. package/ai/llmstxt.js +12 -0
  12. package/ai/provenance.js +18 -0
  13. package/ai/rag.js +14 -0
  14. package/ai/tokens.js +9 -0
  15. package/api/auth.js +13 -0
  16. package/api/contracts.js +17 -0
  17. package/api/control.js +33 -0
  18. package/api/http.js +12 -0
  19. package/api/rate.js +31 -0
  20. package/api/security.js +42 -0
  21. package/api/service.js +36 -0
  22. package/binary/build.js +17 -0
  23. package/bot/adapter.js +8 -0
  24. package/bot/bot.js +39 -0
  25. package/bot/commands.js +18 -0
  26. package/bot/permissions.js +16 -0
  27. package/browser/actions.js +33 -0
  28. package/browser/agent.js +9 -0
  29. package/browser/context.js +52 -0
  30. package/browser/fingerprint.js +12 -0
  31. package/browser/index.js +10 -0
  32. package/browser/recorder.js +15 -0
  33. package/browser/session.js +19 -0
  34. package/browser/snapshot.js +57 -0
  35. package/captcha/contract.js +15 -0
  36. package/captcha/evidence.js +9 -0
  37. package/captcha/guard.js +10 -0
  38. package/cli/main.js +36 -0
  39. package/core/errors.js +37 -0
  40. package/core/events.js +21 -0
  41. package/core/hash.js +73 -0
  42. package/core/ids.js +15 -0
  43. package/crawl/crawler.js +29 -0
  44. package/crawl/frontier.js +34 -0
  45. package/crawl/normalize.js +14 -0
  46. package/crawl/persistent.js +13 -0
  47. package/dispatch/resumable.js +31 -0
  48. package/dispatch/workflow.js +33 -0
  49. package/docs/assets/architecture.svg +45 -0
  50. package/docs/assets/saddlemark.svg +13 -0
  51. package/docs/comparativeaudit.md +63 -0
  52. package/docs/ecosystemplan.md +59 -0
  53. package/docs/enginearchitecture.md +83 -0
  54. package/docs/featureaudit.md +63 -0
  55. package/docs/gapmatrix.md +80 -0
  56. package/docs/libraryapi.md +63 -0
  57. package/docs/modes.md +27 -0
  58. package/docs/productindex.md +28 -0
  59. package/docs/registryresearch.md +56 -0
  60. package/docs/release.md +28 -0
  61. package/docs/release17notes.md +24 -0
  62. package/docs/release181notes.md +15 -0
  63. package/docs/release18notes.md +15 -0
  64. package/docs/roadmapp2p3.md +33 -0
  65. package/docs/toolchains.md +28 -0
  66. package/docs/usage.md +107 -0
  67. package/domain/artifacts.js +13 -0
  68. package/domain/jobs.js +20 -0
  69. package/domain/providers.js +8 -0
  70. package/domain/runtime.js +10 -0
  71. package/domain/sessions.js +34 -0
  72. package/errors/taxonomy.js +18 -0
  73. package/examples/localjob.js +15 -0
  74. package/examples/publicapi.js +7 -0
  75. package/extension/README.md +23 -0
  76. package/extension/content.js +85 -0
  77. package/extension/index.js +5 -0
  78. package/extension/manifest.json +10 -0
  79. package/extension/popup.css +13 -0
  80. package/extension/popup.html +24 -0
  81. package/extension/popup.js +25 -0
  82. package/extension/protocol.js +76 -0
  83. package/extension/serviceworker.js +43 -0
  84. package/extension/worker.js +20 -0
  85. package/format/check.js +21 -0
  86. package/index.js +120 -0
  87. package/library/public.js +83 -0
  88. package/license.md +203 -0
  89. package/license.txt +203 -0
  90. package/mcp/browser.js +12 -0
  91. package/mcp/server.js +28 -0
  92. package/mcp/transport.js +14 -0
  93. package/memory/bridge.js +16 -0
  94. package/memory/engine.js +45 -0
  95. package/memory/modes.js +55 -0
  96. package/memory/objects.js +18 -0
  97. package/memory/targets.js +21 -0
  98. package/memory/transforms.js +15 -0
  99. package/modes/matrix.js +20 -0
  100. package/modes/modes.js +16 -0
  101. package/modes/resolve.js +39 -0
  102. package/package.json +47 -0
  103. package/packager/manifest.js +28 -0
  104. package/packager/publish.js +15 -0
  105. package/persistence/adapter.js +8 -0
  106. package/persistence/drizzle.js +10 -0
  107. package/persistence/memory.js +26 -0
  108. package/persistence/migrations.js +14 -0
  109. package/persistence/prisma.js +23 -0
  110. package/persistence/schema.js +29 -0
  111. package/persistence/sql.js +30 -0
  112. package/protocol/blocks.js +18 -0
  113. package/protocol/json.js +5 -0
  114. package/protocol/ndjson.js +17 -0
  115. package/protocol/sse.js +22 -0
  116. package/proxy/pool.js +12 -0
  117. package/queue/idempotency.js +12 -0
  118. package/queue/persistent.js +44 -0
  119. package/queue/queue.js +50 -0
  120. package/queue/saga.js +13 -0
  121. package/readme.txt +163 -0
  122. package/retry/circuit.js +15 -0
  123. package/retry/policy.js +12 -0
  124. package/runners/health.js +23 -0
  125. package/runners/heartbeat.js +26 -0
  126. package/runners/inprocess.js +19 -0
  127. package/runners/scheduler.js +16 -0
  128. package/runtime/abort.js +10 -0
  129. package/runtime/compatibility.js +13 -0
  130. package/runtime/detect.js +14 -0
  131. package/runtime/engine.js +56 -0
  132. package/runtime/worker.js +18 -0
  133. package/scrape/cache.js +14 -0
  134. package/scrape/extract.js +14 -0
  135. package/scrape/robots.js +32 -0
  136. package/scrape/schema.js +21 -0
  137. package/scrape/scraper.js +40 -0
  138. package/scrape/semantic.js +22 -0
  139. package/server/node.js +34 -0
  140. package/sessions/file.js +13 -0
  141. package/sessions/replay.js +21 -0
  142. package/sessions/store.js +13 -0
  143. package/storage/adapter.js +8 -0
  144. package/storage/cache.js +54 -0
  145. package/storage/checksum.js +17 -0
  146. package/storage/chunked.js +58 -0
  147. package/storage/content.js +42 -0
  148. package/storage/filehosting.js +17 -0
  149. package/storage/githubcontents.js +18 -0
  150. package/storage/index.js +10 -0
  151. package/storage/local.js +35 -0
  152. package/storage/memory.js +28 -0
  153. package/storage/s3compatible.js +23 -0
  154. package/storage/sync.js +55 -0
  155. package/surfaces/adapters.js +48 -0
  156. package/surfaces/controls.js +37 -0
  157. package/surfaces/manifest.js +25 -0
  158. package/surfaces/n8n.js +24 -0
  159. package/surfaces/operations.js +43 -0
  160. package/surfaces/targets.js +16 -0
  161. package/webhook/delivery.js +26 -0
  162. package/webhook/receiver.js +20 -0
  163. package/webhook/signature.js +7 -0
  164. package/workflow/manifest.js +20 -0
  165. package/workflow/registry.js +16 -0
  166. package/workflow/templates.js +18 -0
  167. package/workflow/triggers.js +31 -0
package/license.md ADDED
@@ -0,0 +1,203 @@
1
+ PROPRIETARY SOURCE-AVAILABLE LICENSE - VIEW ONLY
2
+ Version 1.0, August 2026
3
+
4
+ Copyright (C) August 2026 devthink, nathlan, iakadion, nathu filho, allan neris, andraneris
5
+ Everyone is permitted to view this license document, but changing it
6
+ is not allowed. This license is NOT an Open Source license.
7
+
8
+ Preamble
9
+
10
+ This License governs the source code made available by the Licensor.
11
+ Unlike free software licenses such as the GNU GPL, this is a
12
+ proprietary, source-available license.
13
+
14
+ The Software is made visible for transparency and verification
15
+ purposes only. It is NOT free software. It is NOT open source.
16
+
17
+ When we speak of proprietary, we are referring to full ownership and
18
+ restriction, not freedom. Our intention is to protect the Licensor's
19
+ exclusive rights to copy, modify, distribute and use the work. By
20
+ contrast to the GPL which guarantees your freedom to share and change,
21
+ this License is intended to guarantee that the Software remains the
22
+ exclusive property of its authors and that no rights beyond viewing
23
+ are granted.
24
+
25
+ To protect our rights, we must prevent others from copying, modifying,
26
+ distributing, or using the Software without permission. Therefore,
27
+ you have no rights to convey, modify, or use the Software beyond
28
+ viewing it in its public repository form.
29
+
30
+ For the authors' protection, this License clearly explains that there
31
+ is no warranty for this proprietary software and that any unauthorized
32
+ use will be treated as copyright infringement.
33
+
34
+ The precise terms and conditions for viewing and restriction follow.
35
+
36
+ TERMS AND CONDITIONS
37
+
38
+ 0. Definitions.
39
+
40
+ "This License" refers to version 1.0 of the Proprietary Source-Available
41
+ License - View Only.
42
+
43
+ "Copyright" also means copyright-like laws that apply to other kinds of
44
+ works.
45
+
46
+ "The Program" or "The Software" refers to any copyrightable work licensed
47
+ under this License, including source code, object code, documentation,
48
+ and associated files. Each licensee is addressed as "you".
49
+
50
+ "Licensor" refers to the copyright holders: devthink, nathlan, iakadion,
51
+ nathu filho, allan neris, andraneris.
52
+
53
+ To "view" means to read and examine the Software in its public repository
54
+ form through a web browser, without creating a local copy beyond the
55
+ temporary cache of your browser.
56
+
57
+ To "use" means to execute, run, compile, deploy, host, or otherwise
58
+ benefit from the functionality of the Software, which is NOT permitted.
59
+
60
+ 1. Ownership and Intellectual Property.
61
+
62
+ The Software is and shall remain the exclusive property of the Licensor.
63
+ All right, title, and interest in and to the Software, including all
64
+ copyrights, trademarks, trade secrets, and other intellectual property
65
+ rights, are owned solely by the Licensor.
66
+
67
+ No ownership rights, implied or otherwise, are transferred to you under
68
+ this License. All rights not expressly granted are reserved.
69
+
70
+ 2. Grant of Rights - VIEW ONLY.
71
+
72
+ Subject to the terms of this License, Licensor grants you a limited,
73
+ non-exclusive, non-transferable, revocable license solely to VIEW the
74
+ Software in its public repository form for personal evaluation.
75
+
76
+ This grant DOES NOT include any right to:
77
+
78
+ a) use, execute, or run the Software;
79
+ b) copy, reproduce, or duplicate;
80
+ c) modify, adapt, or create derivative works;
81
+ d) distribute, publish, sublicense, or sell;
82
+ e) reverse engineer or decompile.
83
+
84
+ 3. Prohibitions and Restrictions.
85
+
86
+ You are STRICTLY PROHIBITED from undertaking any of the following
87
+ without prior written permission from the Licensor:
88
+
89
+ a) Copying, reproducing, duplicating, or storing the Software, in
90
+ whole or in part, in any medium;
91
+
92
+ b) Modifying, adapting, translating, transforming, or creating
93
+ derivative works based on the Software;
94
+
95
+ c) Distributing, publishing, sublicensing, disclosing, or otherwise
96
+ making the Software available to third parties, whether gratis or
97
+ for a fee;
98
+
99
+ d) Using the Software for any purpose, including but not limited to
100
+ development, production, commercial use, internal business operations,
101
+ offering as a service (SaaS), or training artificial intelligence
102
+ models;
103
+
104
+ e) Removing, altering, or obscuring any copyright, proprietary, or
105
+ license notices contained in the Software;
106
+
107
+ f) Reverse engineering, decompiling, disassembling, or attempting to
108
+ derive the source code of the Software.
109
+
110
+ Any use beyond viewing constitutes copyright infringement and will be
111
+ prosecuted to the fullest extent of the law.
112
+
113
+ 4. Confidentiality.
114
+
115
+ The Software contains confidential information and proprietary trade
116
+ secrets of the Licensor. Unauthorized access, inspection, or disclosure
117
+ is strictly prohibited and may result in civil and criminal liability.
118
+
119
+ 5. No Warranty.
120
+
121
+ The Software is provided for viewing only and may contain errors or
122
+ omissions. No support, maintenance, or updates are implied.
123
+
124
+ 6. Acceptance Not Required for Viewing.
125
+
126
+ You are not required to accept this License to view the Software in a
127
+ web browser. However, any action beyond viewing, such as copying,
128
+ modifying, or using the Software, requires explicit written permission
129
+ and a separate license agreement. By doing so without permission, you
130
+ infringe copyright.
131
+
132
+ 7. Termination.
133
+
134
+ This License and all rights granted herein automatically terminate upon
135
+ any breach of Section 3 by you. Upon termination, you must cease all
136
+ viewing and destroy all copies, including cached or local copies, of
137
+ the Software in your possession.
138
+
139
+ Moreover, termination does not terminate the rights of the Licensor
140
+ to seek damages or injunctive relief.
141
+
142
+ 8. Disclaimer of Warranty.
143
+
144
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
145
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
146
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
147
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
148
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
149
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
150
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
151
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
152
+
153
+ 9. Limitation of Liability.
154
+
155
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
156
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO HAS VIEWED THE PROGRAM
157
+ AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
158
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
159
+ VIEWING OR INABILITY TO VIEW THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS
160
+ OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
161
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE), EVEN IF SUCH HOLDER OR
162
+ OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
163
+
164
+ 10. Interpretation and Governing Law.
165
+
166
+ If the disclaimer of warranty and limitation of liability provided above
167
+ cannot be given local legal effect according to their terms, reviewing
168
+ courts shall apply local law that most closely approximates an absolute
169
+ waiver of all civil liability in connection with the Program, unless a
170
+ warranty or assumption of liability accompanies a copy of the Program
171
+ in return for a fee.
172
+
173
+ This License shall be governed by the laws of Brazil.
174
+
175
+ END OF TERMS AND CONDITIONS
176
+
177
+ How to Apply These Terms to Your New Programs
178
+
179
+ If you develop a new program, and you want it to remain proprietary and
180
+ fully owned by you, with source visible but with no rights granted, the
181
+ best way to achieve this is to attach the following notices to the program.
182
+ It is safest to attach them to the start of each source file.
183
+
184
+ <one line to give the program's name and a brief idea of what it does.>
185
+ Copyright (C) August 2026 devthink, nathlan, iakadion, nathu filho, allan neris, andraneris
186
+ Project ID: saddle
187
+
188
+ This program is proprietary and confidential: you can view its source
189
+ code for evaluation purposes only under the terms of the Proprietary
190
+ Source-Available License - View Only as published by the Licensor.
191
+ You are not permitted to copy, modify, distribute, or use this program
192
+ without prior written permission.
193
+
194
+ This program is distributed in the hope that it will be transparent,
195
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
196
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
197
+ Proprietary Source-Available License for more details.
198
+
199
+ You should have received a copy of the Proprietary Source-Available
200
+ License along with this program. If not, see
201
+ <https://github.com/iakadion/saddle/blob/main/license.txt>
202
+
203
+ Also add information on how to contact you by electronic and paper mail.
package/license.txt ADDED
@@ -0,0 +1,203 @@
1
+ PROPRIETARY SOURCE-AVAILABLE LICENSE - VIEW ONLY
2
+ Version 1.0, August 2026
3
+
4
+ Copyright (C) August 2026 devthink, nathlan, iakadion, nathu filho, allan neris, andraneris
5
+ Everyone is permitted to view this license document, but changing it
6
+ is not allowed. This license is NOT an Open Source license.
7
+
8
+ Preamble
9
+
10
+ This License governs the source code made available by the Licensor.
11
+ Unlike free software licenses such as the GNU GPL, this is a
12
+ proprietary, source-available license.
13
+
14
+ The Software is made visible for transparency and verification
15
+ purposes only. It is NOT free software. It is NOT open source.
16
+
17
+ When we speak of proprietary, we are referring to full ownership and
18
+ restriction, not freedom. Our intention is to protect the Licensor's
19
+ exclusive rights to copy, modify, distribute and use the work. By
20
+ contrast to the GPL which guarantees your freedom to share and change,
21
+ this License is intended to guarantee that the Software remains the
22
+ exclusive property of its authors and that no rights beyond viewing
23
+ are granted.
24
+
25
+ To protect our rights, we must prevent others from copying, modifying,
26
+ distributing, or using the Software without permission. Therefore,
27
+ you have no rights to convey, modify, or use the Software beyond
28
+ viewing it in its public repository form.
29
+
30
+ For the authors' protection, this License clearly explains that there
31
+ is no warranty for this proprietary software and that any unauthorized
32
+ use will be treated as copyright infringement.
33
+
34
+ The precise terms and conditions for viewing and restriction follow.
35
+
36
+ TERMS AND CONDITIONS
37
+
38
+ 0. Definitions.
39
+
40
+ "This License" refers to version 1.0 of the Proprietary Source-Available
41
+ License - View Only.
42
+
43
+ "Copyright" also means copyright-like laws that apply to other kinds of
44
+ works.
45
+
46
+ "The Program" or "The Software" refers to any copyrightable work licensed
47
+ under this License, including source code, object code, documentation,
48
+ and associated files. Each licensee is addressed as "you".
49
+
50
+ "Licensor" refers to the copyright holders: devthink, nathlan, iakadion,
51
+ nathu filho, allan neris, andraneris.
52
+
53
+ To "view" means to read and examine the Software in its public repository
54
+ form through a web browser, without creating a local copy beyond the
55
+ temporary cache of your browser.
56
+
57
+ To "use" means to execute, run, compile, deploy, host, or otherwise
58
+ benefit from the functionality of the Software, which is NOT permitted.
59
+
60
+ 1. Ownership and Intellectual Property.
61
+
62
+ The Software is and shall remain the exclusive property of the Licensor.
63
+ All right, title, and interest in and to the Software, including all
64
+ copyrights, trademarks, trade secrets, and other intellectual property
65
+ rights, are owned solely by the Licensor.
66
+
67
+ No ownership rights, implied or otherwise, are transferred to you under
68
+ this License. All rights not expressly granted are reserved.
69
+
70
+ 2. Grant of Rights - VIEW ONLY.
71
+
72
+ Subject to the terms of this License, Licensor grants you a limited,
73
+ non-exclusive, non-transferable, revocable license solely to VIEW the
74
+ Software in its public repository form for personal evaluation.
75
+
76
+ This grant DOES NOT include any right to:
77
+
78
+ a) use, execute, or run the Software;
79
+ b) copy, reproduce, or duplicate;
80
+ c) modify, adapt, or create derivative works;
81
+ d) distribute, publish, sublicense, or sell;
82
+ e) reverse engineer or decompile.
83
+
84
+ 3. Prohibitions and Restrictions.
85
+
86
+ You are STRICTLY PROHIBITED from undertaking any of the following
87
+ without prior written permission from the Licensor:
88
+
89
+ a) Copying, reproducing, duplicating, or storing the Software, in
90
+ whole or in part, in any medium;
91
+
92
+ b) Modifying, adapting, translating, transforming, or creating
93
+ derivative works based on the Software;
94
+
95
+ c) Distributing, publishing, sublicensing, disclosing, or otherwise
96
+ making the Software available to third parties, whether gratis or
97
+ for a fee;
98
+
99
+ d) Using the Software for any purpose, including but not limited to
100
+ development, production, commercial use, internal business operations,
101
+ offering as a service (SaaS), or training artificial intelligence
102
+ models;
103
+
104
+ e) Removing, altering, or obscuring any copyright, proprietary, or
105
+ license notices contained in the Software;
106
+
107
+ f) Reverse engineering, decompiling, disassembling, or attempting to
108
+ derive the source code of the Software.
109
+
110
+ Any use beyond viewing constitutes copyright infringement and will be
111
+ prosecuted to the fullest extent of the law.
112
+
113
+ 4. Confidentiality.
114
+
115
+ The Software contains confidential information and proprietary trade
116
+ secrets of the Licensor. Unauthorized access, inspection, or disclosure
117
+ is strictly prohibited and may result in civil and criminal liability.
118
+
119
+ 5. No Warranty.
120
+
121
+ The Software is provided for viewing only and may contain errors or
122
+ omissions. No support, maintenance, or updates are implied.
123
+
124
+ 6. Acceptance Not Required for Viewing.
125
+
126
+ You are not required to accept this License to view the Software in a
127
+ web browser. However, any action beyond viewing, such as copying,
128
+ modifying, or using the Software, requires explicit written permission
129
+ and a separate license agreement. By doing so without permission, you
130
+ infringe copyright.
131
+
132
+ 7. Termination.
133
+
134
+ This License and all rights granted herein automatically terminate upon
135
+ any breach of Section 3 by you. Upon termination, you must cease all
136
+ viewing and destroy all copies, including cached or local copies, of
137
+ the Software in your possession.
138
+
139
+ Moreover, termination does not terminate the rights of the Licensor
140
+ to seek damages or injunctive relief.
141
+
142
+ 8. Disclaimer of Warranty.
143
+
144
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
145
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
146
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
147
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
148
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
149
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
150
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
151
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
152
+
153
+ 9. Limitation of Liability.
154
+
155
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
156
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO HAS VIEWED THE PROGRAM
157
+ AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
158
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
159
+ VIEWING OR INABILITY TO VIEW THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS
160
+ OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
161
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE), EVEN IF SUCH HOLDER OR
162
+ OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
163
+
164
+ 10. Interpretation and Governing Law.
165
+
166
+ If the disclaimer of warranty and limitation of liability provided above
167
+ cannot be given local legal effect according to their terms, reviewing
168
+ courts shall apply local law that most closely approximates an absolute
169
+ waiver of all civil liability in connection with the Program, unless a
170
+ warranty or assumption of liability accompanies a copy of the Program
171
+ in return for a fee.
172
+
173
+ This License shall be governed by the laws of Brazil.
174
+
175
+ END OF TERMS AND CONDITIONS
176
+
177
+ How to Apply These Terms to Your New Programs
178
+
179
+ If you develop a new program, and you want it to remain proprietary and
180
+ fully owned by you, with source visible but with no rights granted, the
181
+ best way to achieve this is to attach the following notices to the program.
182
+ It is safest to attach them to the start of each source file.
183
+
184
+ <one line to give the program's name and a brief idea of what it does.>
185
+ Copyright (C) August 2026 devthink, nathlan, iakadion, nathu filho, allan neris, andraneris
186
+ Project ID: saddle
187
+
188
+ This program is proprietary and confidential: you can view its source
189
+ code for evaluation purposes only under the terms of the Proprietary
190
+ Source-Available License - View Only as published by the Licensor.
191
+ You are not permitted to copy, modify, distribute, or use this program
192
+ without prior written permission.
193
+
194
+ This program is distributed in the hope that it will be transparent,
195
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
196
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
197
+ Proprietary Source-Available License for more details.
198
+
199
+ You should have received a copy of the Proprietary Source-Available
200
+ License along with this program. If not, see
201
+ <https://github.com/iakadion/saddle/blob/main/license.txt>
202
+
203
+ Also add information on how to contact you by electronic and paper mail.
package/mcp/browser.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * browser MCP tools expose snapshots and actions only through an injected browser adapter.
3
+ */
4
+
5
+ /** Creates optional browser tools for an MCP server without selecting Playwright or another vendor. */
6
+ export function browsertools(browser) {
7
+ if (typeof browser?.snapshot !== "function" || typeof browser?.action !== "function") throw new TypeError("browser MCP tools require snapshot and action");
8
+ return {
9
+ browser_snapshot: async (input = {}) => browser.snapshot(input),
10
+ browser_action: async (input = {}) => browser.action(input)
11
+ };
12
+ }
package/mcp/server.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * mcp server implements a small JSON RPC tool surface and remains transport agnostic.
3
+ */
4
+ import { crawl } from "../crawl/crawler.js";
5
+ import { extractwithschema } from "../scrape/schema.js";
6
+ import { jsonencode } from "../protocol/json.js";
7
+ import { browsertools } from "./browser.js";
8
+
9
+ export function mcpserver(options = {}) {
10
+ if (typeof options.scrape !== "function") throw new TypeError("mcp server requires scrape");
11
+ const tools = {
12
+ scrape: async (input) => options.scrape(input.url, input),
13
+ crawl: async (input) => crawl(input.url, { ...input, scrape: (url) => options.scrape(url, input) }),
14
+ batch: async (input) => ({ results: await Promise.all((input.urls ?? []).map((url) => options.scrape(url, input))) }),
15
+ extract: async (input) => extractwithschema(input.html, input.schema, input.url),
16
+ serialize: async (input) => jsonencode(input.value),
17
+ ...(options.browser ? browsertools(options.browser) : {}),
18
+ ...(options.tools ?? {})
19
+ };
20
+ return {
21
+ listtools() { return Object.keys(tools).map((name) => ({ name, description: `saddle ${name} tool` })); },
22
+ async handle(request) {
23
+ if (request.method === "tools/list") return { jsonrpc: "2.0", id: request.id, result: { tools: this.listtools() } };
24
+ if (request.method === "tools/call") { const handler = tools[request.params?.name]; if (!handler) return { jsonrpc: "2.0", id: request.id, error: { code: -32601, message: "tool not found" } }; try { return { jsonrpc: "2.0", id: request.id, result: { content: [{ type: "text", text: JSON.stringify(await handler(request.params.arguments ?? {})) }] } }; } catch (error) { return { jsonrpc: "2.0", id: request.id, error: { code: -32000, message: error.message } }; } }
25
+ return { jsonrpc: "2.0", id: request.id, error: { code: -32601, message: "method not found" } };
26
+ }
27
+ };
28
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * mcp transport keeps JSON RPC framing separate from the tool server.
3
+ */
4
+ import { jsondecode, jsonencode } from "../protocol/json.js";
5
+
6
+ /** Creates JSONL and HTTP handlers for the transport agnostic MCP server. */
7
+ export function mcptransport(server) {
8
+ if (typeof server?.handle !== "function") throw new TypeError("mcp transport requires server");
9
+ return {
10
+ async handleline(line) { const request = jsondecode(line); return jsonencode(await server.handle(request)); },
11
+ async *stream(lines) { for await (const line of lines) if (String(line).trim()) yield await this.handleline(line); },
12
+ async handlehttp(request) { const body = await request.text(); const response = await server.handle(jsondecode(body)); return new Response(jsonencode(response), { status: 200, headers: { "content-type": "application/json" } }); }
13
+ };
14
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * memory bridges materialize and clear temporary working sets.
3
+ */
4
+ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
5
+ import { join } from "node:path";
6
+ import { tmpdir } from "node:os";
7
+ import { syncresult, workingset } from "../domain/runtime.js";
8
+
9
+ export function localmemory(options = {}) {
10
+ const base = options.base ?? tmpdir();
11
+ return {
12
+ async prepare(job) { const location = await mkdtemp(join(base, "saddlejob")); return workingset(job.id, location, join(location, "resultbin")); },
13
+ async sync(set, bytes) { await mkdir(set.location, { recursive: true }); await writeFile(set.resultpath, bytes); return syncresult(bytes.byteLength, set.resultpath); },
14
+ async cleanup(set) { await rm(set.location, { recursive: true, force: true }); }
15
+ };
16
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * memory engine loads from the first backend and persists to every backend.
3
+ */
4
+ import { memoryobject, tobytes } from "./objects.js";
5
+ import { transformtocompute, transformtostorage } from "./transforms.js";
6
+ import { storagecapabilities, syncbackends } from "../storage/sync.js";
7
+
8
+ export function memoryengine(options = {}) {
9
+ const backends = options.backends ?? [];
10
+ const values = new Map();
11
+ async function load(key) {
12
+ if (!key) throw new TypeError("memory key is required");
13
+ if (values.has(key)) return values.get(key);
14
+ let last;
15
+ for (const backend of backends) {
16
+ try {
17
+ const value = await backend.get(key);
18
+ if (value == null) continue;
19
+ const object = memoryobject({ id: key, buffer: value.data ?? value, type: value.contenttype ?? value.type, metadata: value.metadata });
20
+ values.set(key, object);
21
+ return object;
22
+ } catch (error) { last = error; }
23
+ }
24
+ if (last) throw new Error(`memory engine load failed for key "${key}": ${last.message}`, { cause: last });
25
+ throw new Error(`memory engine load failed for key "${key}": not found`);
26
+ }
27
+ async function persist(key, data, options = {}) {
28
+ const payload = tobytes(data?.payload ?? data?.buffer ?? data);
29
+ const object = memoryobject({ id: key, buffer: payload, type: options.mimetype ?? data?.mimetype, metadata: options.metadata ?? data?.metadata });
30
+ for (const backend of backends) await backend.put(key, { data: object.buffer, contenttype: object.type, metadata: object.metadata });
31
+ values.set(key, object);
32
+ return object;
33
+ }
34
+ function release(key) { values.delete(key); }
35
+ async function safeload(key) { try { return { success: true, data: await load(key) }; } catch (error) { return { success: false, error }; } }
36
+ async function sync(key, options = {}) {
37
+ const sourceindex = Number(options.sourceindex ?? 0);
38
+ const source = backends[sourceindex];
39
+ if (!source) throw new TypeError("memory sync source backend is missing");
40
+ const targets = backends.filter((_backend, index) => index !== sourceindex);
41
+ return syncbackends(source, targets, key, options);
42
+ }
43
+ function capabilities() { return backends.map((backend, index) => ({ index, capabilities: storagecapabilities(backend) })); }
44
+ return { load, persist, release, safeload, sync, capabilities, transformtocompute, transformtostorage, list() { return [...values.keys()]; } };
45
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * memory modes expose the same byte contract with different backing choices.
3
+ */
4
+ export function internalmemory(initial = {}) {
5
+ const values = new Map(Object.entries(initial).map(([key, value]) => [key, tobytes(value)]));
6
+ return {
7
+ mode: "internal",
8
+ async put(key, value) { values.set(key, tobytes(value)); return { key, bytes: values.get(key).byteLength }; },
9
+ async get(key) { return values.get(key) ?? null; },
10
+ async delete(key) { values.delete(key); },
11
+ async list() { return [...values.keys()]; }
12
+ };
13
+ }
14
+
15
+ export function externalmemory(storage) {
16
+ if (!storage?.put || !storage?.get) throw new TypeError("external memory requires storage adapter");
17
+ return {
18
+ mode: "external",
19
+ async put(key, value) { return storage.put({ key, data: tobytes(value) }); },
20
+ async get(key) { try { return await storage.get(key); } catch (error) { if (error.code === "ARTIFACT_NOT_FOUND") return null; throw error; } },
21
+ async delete(key) { return storage.delete(key); },
22
+ async list(prefix) { return storage.list(prefix); }
23
+ };
24
+ }
25
+
26
+ export function physicalmemory(options = {}) {
27
+ if (!options.path) throw new TypeError("physical memory requires a path");
28
+ return { mode: "physical", path: options.path, put: options.put, get: options.get, delete: options.delete, list: options.list };
29
+ }
30
+
31
+ export function vectorizedmemory() {
32
+ const vectors = new Map();
33
+ return {
34
+ mode: "vectorized",
35
+ async put(key, vector) { assertvector(vector); vectors.set(key, [...vector]); return { key, dimensions: vector.length }; },
36
+ async get(key) { return vectors.get(key) ?? null; },
37
+ async average(keys) { const selected = keys.map((key) => vectors.get(key)).filter(Boolean); if (!selected.length) return null; const size = selected[0].length; const result = Array.from({ length: size }, () => 0); for (const vector of selected) for (let index = 0; index < size; index += 1) result[index] += vector[index] / selected.length; return result; },
38
+ async list() { return [...vectors.keys()]; }
39
+ };
40
+ }
41
+
42
+ export function librarymemory(factory) {
43
+ if (typeof factory !== "function") throw new TypeError("library memory requires a factory");
44
+ return { mode: "library", async load(options) { return factory(options); } };
45
+ }
46
+
47
+ function tobytes(value) {
48
+ if (value instanceof Uint8Array) return value;
49
+ if (typeof value === "string") return new TextEncoder().encode(value);
50
+ return new TextEncoder().encode(JSON.stringify(value));
51
+ }
52
+
53
+ function assertvector(vector) {
54
+ if (!Array.isArray(vector) || vector.length === 0 || vector.some((value) => !Number.isFinite(value))) throw new TypeError("vector must be a non empty numeric array");
55
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * memory objects and compute results are serializable contracts between storage and runtime.
3
+ */
4
+ export function memoryobject(options = {}) {
5
+ const buffer = tobytes(options.buffer ?? options.data ?? new Uint8Array(0));
6
+ return { id: options.id ?? `memory${Date.now().toString(36)}`, buffer, size: buffer.byteLength, type: options.type ?? "application/octet-stream", createdat: options.createdat ?? Date.now(), metadata: { ...(options.metadata ?? {}) } };
7
+ }
8
+
9
+ export function computeresult(options = {}) {
10
+ return { id: options.id ?? `result${Date.now().toString(36)}`, payload: options.payload, mimetype: options.mimetype, metadata: { ...(options.metadata ?? {}) }, processingtimems: options.processingtimems ?? 0, memoryusedbytes: options.memoryusedbytes ?? 0 };
11
+ }
12
+
13
+ export function tobytes(value) {
14
+ if (value instanceof Uint8Array) return value;
15
+ if (value instanceof ArrayBuffer) return new Uint8Array(value);
16
+ if (typeof value === "string") return new TextEncoder().encode(value);
17
+ return new TextEncoder().encode(JSON.stringify(value));
18
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * storage targets describe provider intent without importing a provider client.
3
+ */
4
+ const types = new Set(["github", "gitlab", "forgejo", "gitea", "huggingface", "kaggle", "modelscope", "filehosting"]);
5
+
6
+ export function targetfactory(type, options = {}) {
7
+ if (!types.has(type)) throw new TypeError(`unknown memory target: ${type}`);
8
+ if (type === "github" || type === "gitlab" || type === "forgejo" || type === "gitea") return { type, platform: type, owner: options.owner, repo: options.repo, branch: options.branch ?? "main", path: options.path, token: options.token };
9
+ if (type === "huggingface") return { type, space: options.space, revision: options.revision ?? "main", path: options.path, token: options.token };
10
+ if (type === "kaggle") return { type, dataset: options.dataset, sslverification: options.sslverification ?? true, path: options.path, token: options.token };
11
+ if (type === "modelscope") return { type, namespace: options.namespace, repo: options.repo, revision: options.revision ?? "master", path: options.path, token: options.token };
12
+ return { type, host: options.host, path: options.path, method: options.method ?? "s3compatible", token: options.token };
13
+ }
14
+
15
+ export function targeturi(target) {
16
+ if (target.type === "github" || target.type === "gitlab" || target.type === "forgejo" || target.type === "gitea") return `${target.type}://${target.owner}/${target.repo}/${target.path}`;
17
+ if (target.type === "huggingface") return `hf://${target.space}/${target.path}`;
18
+ if (target.type === "kaggle") return `kaggle://${target.dataset}/${target.path}`;
19
+ if (target.type === "modelscope") return `modelscope://${target.namespace}/${target.repo}/${target.path}`;
20
+ return `${target.method}://${target.host}/${target.path}`;
21
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * transforms annotate byte movement without pretending remote storage is physical vram.
3
+ */
4
+ import { computeresult, memoryobject, tobytes } from "./objects.js";
5
+
6
+ export function transformtocompute(value, options = {}) {
7
+ const started = performance.now();
8
+ const object = memoryobject({ ...options, buffer: value?.buffer ?? value });
9
+ return { ...object, processingtimems: performance.now() - started, memoryusedbytes: object.size };
10
+ }
11
+
12
+ export function transformtostorage(value, options = {}) {
13
+ const payload = tobytes(value?.payload ?? value?.buffer ?? value);
14
+ return computeresult({ id: value?.id, payload, mimetype: options.mimetype ?? value?.mimetype ?? "application/octet-stream", metadata: options.metadata ?? value?.metadata, processingtimems: value?.processingtimems, memoryusedbytes: payload.byteLength });
15
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * mode matrix keeps supported execution choices in one grouped contract.
3
+ */
4
+ export const modeaxes = Object.freeze({
5
+ execution: ["library", "application", "browser", "desktopapp", "mobileapp", "extension", "cli", "binary", "computer", "internet"],
6
+ runtime: ["node", "browser", "deno", "bun", "worker", "unknown"],
7
+ memory: ["internal", "external", "physical", "vectorized", "library"],
8
+ file: ["internal", "external", "physical", "vector"],
9
+ dependency: ["internal", "external", "dev"],
10
+ visibility: ["visible", "headless"],
11
+ pair: ["without", "with"]
12
+ });
13
+
14
+ export const operationmodes = Object.freeze(modeaxes.execution.flatMap((execution) => modeaxes.pair.map((pair) => `${execution}${pair}`)));
15
+
16
+ /** Returns true when the matrix contains the requested axis value. */
17
+ export function validatemode(axis, value) { return Boolean(modeaxes[axis]?.includes(value)); }
18
+
19
+ /** Returns a serializable snapshot for documentation and diagnostics. */
20
+ export function modecatalog() { return { axes: Object.fromEntries(Object.entries(modeaxes).map(([key, values]) => [key, [...values]])), operationmodes: [...operationmodes] }; }