@wenathlan/saddle 1.8.14 → 1.8.15
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 +2 -2
- package/dist/apps/registry.d.ts +1 -1
- package/dist/binary/archive.d.ts +27 -0
- package/dist/binary/archive.d.ts.map +1 -0
- package/dist/binary/archive.js +46 -0
- package/dist/binary/archive.js.map +1 -0
- package/dist/binary/transform.d.ts +70 -0
- package/dist/binary/transform.d.ts.map +1 -0
- package/dist/binary/transform.js +105 -0
- package/dist/binary/transform.js.map +1 -0
- package/dist/delivery/manifest.d.ts +35 -0
- package/dist/delivery/manifest.d.ts.map +1 -0
- package/dist/delivery/manifest.js +68 -0
- package/dist/delivery/manifest.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +1 -1
- package/dist/memory/engine.d.ts +1 -1
- package/dist/memory/planner.d.ts +66 -0
- package/dist/memory/planner.d.ts.map +1 -0
- package/dist/memory/planner.js +108 -0
- package/dist/memory/planner.js.map +1 -0
- package/dist/runners/chain.d.ts +125 -0
- package/dist/runners/chain.d.ts.map +1 -0
- package/dist/runners/chain.js +95 -0
- package/dist/runners/chain.js.map +1 -0
- package/dist/scrape/robots.js +1 -1
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +1 -0
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/memory.js +2 -2
- package/dist/storage/memory.js.map +1 -1
- package/dist/storage/pool.d.ts +95 -0
- package/dist/storage/pool.d.ts.map +1 -0
- package/dist/storage/pool.js +202 -0
- package/dist/storage/pool.js.map +1 -0
- package/dist/surfaces/requirements.d.ts +29 -0
- package/dist/surfaces/requirements.d.ts.map +1 -0
- package/dist/surfaces/requirements.js +50 -0
- package/dist/surfaces/requirements.js.map +1 -0
- package/docs/artifactavailability.md +3 -1
- package/docs/ecosystemplan.md +1 -1
- package/docs/enginearchitecture.md +28 -0
- package/docs/plans/00.index.md +2 -2
- package/docs/plans/06.dependencies.md +1 -1
- package/docs/plans/18.research.content.extraction.md +3 -3
- package/docs/plans/22.research.universal.runtime.md +10 -10
- package/docs/plans/28.action.plan.md +1 -1
- package/docs/plans/35.comparativo.concorrencia.md +10 -10
- package/docs/plans/40.npm.publish.md +6 -6
- package/docs/plans/41.o.que.falta.md +2 -2
- package/docs/plans/42.pesquisa.concorrencia.md +2 -2
- package/docs/plans/43.plan.universal.architecture.md +2 -2
- package/docs/plans/44.reference.md +1 -1
- package/docs/plans/45.robotarchitecture.md +3 -3
- package/docs/plans/46.scdnintegration.md +1 -1
- package/docs/plans/README.md +2 -2
- package/docs/plans/missing-facts.md +1 -1
- package/docs/registryresearch.md +3 -3
- package/docs/release17notes.md +1 -1
- package/docs/releasenotes-1.8.14.md +24 -9
- package/docs/releasenotes-1.8.15.md +37 -0
- package/docs/talks9/README (2).md +2 -2
- package/docs/talks9/README.md +4 -4
- 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" +4 -4
- package/docs/talks9/conversa.txt +4 -4
- package/docs/todo-1.8.15.md +483 -0
- package/docs/todo-1.8.16.md +651 -0
- package/docs/todo.md +708 -0
- package/extension/manifest.json +1 -1
- package/package.json +9 -2
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* storage pools combine caller-owned adapters without selecting a provider or creating background work.
|
|
3
|
+
*/
|
|
4
|
+
import { collectbytes, sha256 } from "./checksum.js";
|
|
5
|
+
import { storagecapabilities } from "./sync.js";
|
|
6
|
+
/** Creates a deterministic pool over explicit caller-owned storage adapters. */
|
|
7
|
+
export function storagepool(options = {}) {
|
|
8
|
+
const members = normalizemembers(options.members);
|
|
9
|
+
const clock = typeof options.clock === "function" ? options.clock : () => Date.now();
|
|
10
|
+
const metrics = { reads: 0, writes: 0, hits: 0, misses: 0, mismatches: 0, bytes: 0, attempts: 0, elapsedms: 0 };
|
|
11
|
+
async function read(key, options = {}) {
|
|
12
|
+
const normalizedkey = requiredkey(key);
|
|
13
|
+
const expectedsha = optionalsha(options.sha256);
|
|
14
|
+
const attempts = [];
|
|
15
|
+
const startedat = Number(clock());
|
|
16
|
+
const selected = selectable(members, options.memberids);
|
|
17
|
+
const budget = operationbudget(options.budget, selected.length);
|
|
18
|
+
metrics.reads += 1;
|
|
19
|
+
for (const member of selected.slice(0, budget.maxattempts)) {
|
|
20
|
+
if (options.signal?.aborted)
|
|
21
|
+
throw poolerror("STORAGE_POOL_ABORTED", "storage pool read was aborted", { key: normalizedkey, attempts });
|
|
22
|
+
if (elapsed(clock, startedat) > budget.maxmilliseconds)
|
|
23
|
+
throw poolerror("STORAGE_POOL_TIME_BUDGET", "storage pool read time budget was exceeded", { key: normalizedkey, attempts });
|
|
24
|
+
try {
|
|
25
|
+
metrics.attempts += 1;
|
|
26
|
+
const manifest = await optionalhead(member.storage, normalizedkey);
|
|
27
|
+
const raw = await member.storage.get(normalizedkey);
|
|
28
|
+
const data = await collectbytes(raw?.data ?? raw);
|
|
29
|
+
if (data.byteLength > budget.maxbytes)
|
|
30
|
+
throw poolerror("STORAGE_POOL_BYTE_BUDGET", "storage pool read byte budget was exceeded", { key: normalizedkey, memberid: member.id, maxbytes: budget.maxbytes, sizebytes: data.byteLength });
|
|
31
|
+
const actualsha = sha256(data);
|
|
32
|
+
const requiredsha = expectedsha ?? manifest?.sha256;
|
|
33
|
+
if (requiredsha && actualsha !== requiredsha) {
|
|
34
|
+
metrics.mismatches += 1;
|
|
35
|
+
throw poolerror("STORAGE_POOL_DIGEST_MISMATCH", "storage pool read digest did not match", { key: normalizedkey, memberid: member.id, expectedsha: requiredsha, actualsha });
|
|
36
|
+
}
|
|
37
|
+
metrics.hits += 1;
|
|
38
|
+
metrics.bytes += data.byteLength;
|
|
39
|
+
metrics.elapsedms += elapsed(clock, startedat);
|
|
40
|
+
return Object.freeze({ version: 1, key: normalizedkey, memberid: member.id, data, sha256: actualsha, verified: Boolean(requiredsha), manifest: manifest ?? null, attempts: Object.freeze(attempts), budget, readat: Number(clock()) });
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
attempts.push(attempt(member.id, error));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
metrics.misses += 1;
|
|
47
|
+
metrics.elapsedms += elapsed(clock, startedat);
|
|
48
|
+
throw poolerror("STORAGE_POOL_READ_FAILED", "storage pool could not read a verified object", { key: normalizedkey, attempts });
|
|
49
|
+
}
|
|
50
|
+
async function put(input = {}, options = {}) {
|
|
51
|
+
const key = requiredkey(input.key);
|
|
52
|
+
const data = await collectbytes(input.data);
|
|
53
|
+
const digest = sha256(data);
|
|
54
|
+
const selected = writeselection(selectable(members, options.memberids), options.mode);
|
|
55
|
+
const budget = operationbudget(options.budget, selected.length);
|
|
56
|
+
if (data.byteLength > budget.maxbytes)
|
|
57
|
+
throw poolerror("STORAGE_POOL_BYTE_BUDGET", "storage pool write byte budget was exceeded", { key, maxbytes: budget.maxbytes, sizebytes: data.byteLength });
|
|
58
|
+
const quorum = positiveinteger(options.quorum ?? 1, "storage pool quorum");
|
|
59
|
+
if (quorum > selected.length)
|
|
60
|
+
throw new RangeError("storage pool quorum exceeds selected members");
|
|
61
|
+
const results = [];
|
|
62
|
+
metrics.writes += 1;
|
|
63
|
+
const startedat = Number(clock());
|
|
64
|
+
for (const member of selected.slice(0, budget.maxattempts)) {
|
|
65
|
+
if (options.signal?.aborted) {
|
|
66
|
+
results.push({ memberid: member.id, state: "skipped", code: "STORAGE_POOL_ABORTED" });
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
if (elapsed(clock, startedat) > budget.maxmilliseconds) {
|
|
70
|
+
results.push({ memberid: member.id, state: "skipped", code: "STORAGE_POOL_TIME_BUDGET" });
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
metrics.attempts += 1;
|
|
75
|
+
const manifest = await member.storage.put({ ...input, key, data: new Uint8Array(data), metadata: { ...(input.metadata ?? {}), sha256: digest } });
|
|
76
|
+
if (manifest?.sha256 && manifest.sha256 !== digest)
|
|
77
|
+
throw poolerror("STORAGE_POOL_DIGEST_MISMATCH", "storage pool write digest did not match", { key, memberid: member.id, expectedsha: digest, actualsha: manifest.sha256 });
|
|
78
|
+
results.push({ memberid: member.id, state: "written", manifest: manifest ?? null });
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
results.push({ memberid: member.id, state: "failed", code: error?.code ?? "STORAGE_POOL_WRITE_FAILED", message: String(error?.message ?? error) });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const written = results.filter((result) => result.state === "written");
|
|
85
|
+
metrics.bytes += data.byteLength * written.length;
|
|
86
|
+
metrics.elapsedms += elapsed(clock, startedat);
|
|
87
|
+
const output = Object.freeze({ version: 1, key, sha256: digest, sizebytes: data.byteLength, mode: options.mode ?? "fanout", quorum, state: written.length === selected.length ? "complete" : "partial", results: Object.freeze(results), written: written.length, budget, writtenat: Number(clock()) });
|
|
88
|
+
if (written.length < quorum)
|
|
89
|
+
throw poolerror("STORAGE_POOL_QUORUM_FAILED", "storage pool write quorum was not met", output);
|
|
90
|
+
return output;
|
|
91
|
+
}
|
|
92
|
+
async function readrange(key, start, end, options = {}) {
|
|
93
|
+
const normalizedkey = requiredkey(key);
|
|
94
|
+
const range = validrange(start, end);
|
|
95
|
+
const expectedsha = optionalsha(options.sha256);
|
|
96
|
+
const attempts = [];
|
|
97
|
+
const selected = selectable(members, options.memberids);
|
|
98
|
+
const budget = operationbudget(options.budget, selected.length);
|
|
99
|
+
const startedat = Number(clock());
|
|
100
|
+
metrics.reads += 1;
|
|
101
|
+
for (const member of selected.slice(0, budget.maxattempts)) {
|
|
102
|
+
if (options.signal?.aborted)
|
|
103
|
+
throw poolerror("STORAGE_POOL_ABORTED", "storage pool range read was aborted", { key: normalizedkey, range, attempts });
|
|
104
|
+
if (elapsed(clock, startedat) > budget.maxmilliseconds)
|
|
105
|
+
throw poolerror("STORAGE_POOL_TIME_BUDGET", "storage pool range read time budget was exceeded", { key: normalizedkey, range, attempts });
|
|
106
|
+
if (typeof member.storage.getrange !== "function") {
|
|
107
|
+
attempts.push({ memberid: member.id, code: "STORAGE_POOL_RANGE_UNSUPPORTED", message: "storage pool member does not support range reads" });
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
metrics.attempts += 1;
|
|
112
|
+
const data = await collectbytes(await member.storage.getrange(normalizedkey, range.start, range.end));
|
|
113
|
+
if (data.byteLength !== range.end - range.start)
|
|
114
|
+
throw poolerror("STORAGE_POOL_RANGE_SIZE", "storage pool range result size did not match", { key: normalizedkey, range, memberid: member.id, sizebytes: data.byteLength });
|
|
115
|
+
const actualsha = sha256(data);
|
|
116
|
+
if (expectedsha && actualsha !== expectedsha)
|
|
117
|
+
throw poolerror("STORAGE_POOL_DIGEST_MISMATCH", "storage pool range digest did not match", { key: normalizedkey, range, memberid: member.id, expectedsha, actualsha });
|
|
118
|
+
metrics.hits += 1;
|
|
119
|
+
metrics.bytes += data.byteLength;
|
|
120
|
+
metrics.elapsedms += elapsed(clock, startedat);
|
|
121
|
+
return Object.freeze({ version: 1, key: normalizedkey, range, memberid: member.id, data, sha256: actualsha, verified: Boolean(expectedsha), attempts: Object.freeze(attempts), budget, readat: Number(clock()) });
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
attempts.push(attempt(member.id, error));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
metrics.misses += 1;
|
|
128
|
+
metrics.elapsedms += elapsed(clock, startedat);
|
|
129
|
+
throw poolerror("STORAGE_POOL_RANGE_FAILED", "storage pool could not read the requested range", { key: normalizedkey, range, attempts });
|
|
130
|
+
}
|
|
131
|
+
function repairplan(key, options = {}) {
|
|
132
|
+
const normalizedkey = requiredkey(key);
|
|
133
|
+
const sourceid = String(options.sourceid ?? "");
|
|
134
|
+
if (!members.some((member) => member.id === sourceid))
|
|
135
|
+
throw new TypeError("storage pool repair source member is unknown");
|
|
136
|
+
return Object.freeze({ version: 1, key: normalizedkey, sourceid, sha256: optionalsha(options.sha256), targets: selectable(members, options.memberids).filter((member) => member.id !== sourceid).map((member) => member.id), action: "caller-executes" });
|
|
137
|
+
}
|
|
138
|
+
function restoreplan(key, options = {}) {
|
|
139
|
+
const normalizedkey = requiredkey(key);
|
|
140
|
+
const selected = selectable(members, options.memberids);
|
|
141
|
+
const evidence = new Map((options.replicas ?? []).map((value) => [String(value?.memberid ?? ""), value?.verified === true]));
|
|
142
|
+
const candidates = selected.map((member) => ({ memberid: member.id, verified: evidence.get(member.id) === true })).sort((left, right) => Number(right.verified) - Number(left.verified) || left.memberid.localeCompare(right.memberid));
|
|
143
|
+
return Object.freeze({ version: 1, key: normalizedkey, sha256: optionalsha(options.sha256), action: "caller-restores", candidates: Object.freeze(candidates) });
|
|
144
|
+
}
|
|
145
|
+
return Object.freeze({ read, readrange, put, repairplan, restoreplan, members: () => members.map(describe), capabilities: () => members.map((member) => ({ id: member.id, priority: member.priority, capabilities: storagecapabilities(member.storage) })), metrics: () => ({ ...metrics }) });
|
|
146
|
+
}
|
|
147
|
+
function normalizemembers(input) {
|
|
148
|
+
if (!Array.isArray(input) || input.length === 0)
|
|
149
|
+
throw new TypeError("storage pool members must be a non-empty array");
|
|
150
|
+
const ids = new Set();
|
|
151
|
+
const members = input.map((value, index) => {
|
|
152
|
+
const id = String(value?.id ?? "");
|
|
153
|
+
if (!id)
|
|
154
|
+
throw new TypeError("storage pool member id is required");
|
|
155
|
+
if (ids.has(id))
|
|
156
|
+
throw new TypeError(`storage pool member id is duplicated: ${id}`);
|
|
157
|
+
ids.add(id);
|
|
158
|
+
if (typeof value?.storage?.get !== "function" || typeof value?.storage?.put !== "function")
|
|
159
|
+
throw new TypeError(`storage pool member requires get and put: ${id}`);
|
|
160
|
+
const priority = Number(value.priority ?? index);
|
|
161
|
+
if (!Number.isFinite(priority))
|
|
162
|
+
throw new TypeError(`storage pool member priority is invalid: ${id}`);
|
|
163
|
+
return Object.freeze({ id, storage: value.storage, priority });
|
|
164
|
+
});
|
|
165
|
+
return Object.freeze(members.sort((left, right) => left.priority - right.priority || left.id.localeCompare(right.id)));
|
|
166
|
+
}
|
|
167
|
+
function selectable(members, ids) {
|
|
168
|
+
if (ids === undefined)
|
|
169
|
+
return members;
|
|
170
|
+
if (!Array.isArray(ids) || ids.length === 0)
|
|
171
|
+
throw new TypeError("storage pool memberids must be a non-empty array");
|
|
172
|
+
const expected = new Set(ids.map((id) => String(id)));
|
|
173
|
+
const selected = members.filter((member) => expected.has(member.id));
|
|
174
|
+
if (selected.length !== expected.size)
|
|
175
|
+
throw new TypeError("storage pool memberids include an unknown member");
|
|
176
|
+
return selected;
|
|
177
|
+
}
|
|
178
|
+
function writeselection(members, mode = "fanout") {
|
|
179
|
+
const normalized = String(mode);
|
|
180
|
+
if (!new Set(["primary", "mirror", "fanout"]).has(normalized))
|
|
181
|
+
throw new TypeError("storage pool write mode is invalid");
|
|
182
|
+
return normalized === "primary" ? members.slice(0, 1) : members;
|
|
183
|
+
}
|
|
184
|
+
async function optionalhead(storage, key) { return typeof storage.head === "function" ? await storage.head(key) : null; }
|
|
185
|
+
function describe(member) { return Object.freeze({ id: member.id, priority: member.priority }); }
|
|
186
|
+
function requiredkey(value) { const key = String(value ?? ""); if (!key)
|
|
187
|
+
throw new TypeError("storage pool key is required"); return key; }
|
|
188
|
+
function optionalsha(value) { if (value === undefined || value === null)
|
|
189
|
+
return null; const digest = String(value); if (!/^[a-f0-9]{64}$/i.test(digest))
|
|
190
|
+
throw new TypeError("storage pool sha256 is invalid"); return digest.toLowerCase(); }
|
|
191
|
+
function positiveinteger(value, name) { const numeric = Number(value); if (!Number.isInteger(numeric) || numeric < 1)
|
|
192
|
+
throw new TypeError(`${name} must be a positive integer`); return numeric; }
|
|
193
|
+
function operationbudget(input = {}, fallbackattempts) { const budget = input ?? {}; return Object.freeze({ maxattempts: positiveinteger(budget.maxattempts ?? fallbackattempts, "storage pool budget maxattempts"), maxbytes: nonnegativebudget(budget.maxbytes, "storage pool budget maxbytes"), maxmilliseconds: nonnegativebudget(budget.maxmilliseconds, "storage pool budget maxmilliseconds") }); }
|
|
194
|
+
function nonnegativebudget(value, name) { if (value === undefined)
|
|
195
|
+
return Infinity; const numeric = Number(value); if (!Number.isSafeInteger(numeric) || numeric < 0)
|
|
196
|
+
throw new TypeError(`${name} must be a non-negative safe integer`); return numeric; }
|
|
197
|
+
function elapsed(clock, startedat) { return Math.max(0, Number(clock()) - startedat); }
|
|
198
|
+
function validrange(start, end) { const from = nonnegativebudget(start, "storage pool range start"); const to = nonnegativebudget(end, "storage pool range end"); if (!Number.isFinite(from) || !Number.isFinite(to) || to < from)
|
|
199
|
+
throw new TypeError("storage pool range is invalid"); return Object.freeze({ start: from, end: to }); }
|
|
200
|
+
function attempt(memberid, error) { return { memberid, code: error?.code ?? "STORAGE_POOL_READ_FAILED", message: String(error?.message ?? error) }; }
|
|
201
|
+
function poolerror(code, message, detail) { const error = new Error(message); error.code = code; error.detail = detail; return error; }
|
|
202
|
+
//# sourceMappingURL=pool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool.js","sourceRoot":"","sources":["../../storage/pool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* application surface requirements describe Mini App, DNS, and bridge needs without owning credentials or infrastructure.
|
|
3
|
+
*/
|
|
4
|
+
/** Creates a Mini App plan that requires caller-owned origin and validation. */
|
|
5
|
+
export declare function miniappplan(input?: {}): Readonly<{
|
|
6
|
+
version: 1;
|
|
7
|
+
origin: any;
|
|
8
|
+
validation: string;
|
|
9
|
+
capabilities: readonly string[];
|
|
10
|
+
state: "caller-validates";
|
|
11
|
+
provider: string;
|
|
12
|
+
}>;
|
|
13
|
+
/** Creates a DNS and HTTPS requirement record without a registrar or DNS operation. */
|
|
14
|
+
export declare function dnsplan(input?: {}): Readonly<{
|
|
15
|
+
version: 1;
|
|
16
|
+
hostname: string;
|
|
17
|
+
dnssec: boolean;
|
|
18
|
+
https: boolean;
|
|
19
|
+
owner: string;
|
|
20
|
+
state: "caller-configures";
|
|
21
|
+
operations: readonly string[];
|
|
22
|
+
}>;
|
|
23
|
+
/** Maps declared application surfaces without selecting a runtime vendor. */
|
|
24
|
+
export declare function applicationbridge(input?: {}): Readonly<{
|
|
25
|
+
version: 1;
|
|
26
|
+
surfaces: any;
|
|
27
|
+
state: "caller-connects";
|
|
28
|
+
}>;
|
|
29
|
+
//# sourceMappingURL=requirements.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirements.d.ts","sourceRoot":"","sources":["../../surfaces/requirements.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,KAAK,KAAK;;;;;;;GAKrC;AAED,uFAAuF;AACvF,wBAAgB,OAAO,CAAC,KAAK,KAAK;;;;;;;;GAKjC;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,KAAK,KAAK;;;;GAY3C"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* application surface requirements describe Mini App, DNS, and bridge needs without owning credentials or infrastructure.
|
|
3
|
+
*/
|
|
4
|
+
/** Creates a Mini App plan that requires caller-owned origin and validation. */
|
|
5
|
+
export function miniappplan(input = {}) {
|
|
6
|
+
if ("token" in input || "bottoken" in input || "secret" in input)
|
|
7
|
+
throw new TypeError("Mini App credentials must not be supplied to the library plan");
|
|
8
|
+
const origin = publichttps(input.origin, "Mini App origin");
|
|
9
|
+
const validation = nonempty(input.validation, "Mini App validation");
|
|
10
|
+
return Object.freeze({ version: 1, origin, validation, capabilities: Object.freeze(unique(input.capabilities ?? [])), state: "caller-validates", provider: String(input.provider ?? "telegram") });
|
|
11
|
+
}
|
|
12
|
+
/** Creates a DNS and HTTPS requirement record without a registrar or DNS operation. */
|
|
13
|
+
export function dnsplan(input = {}) {
|
|
14
|
+
const hostname = hostnamevalue(input.hostname);
|
|
15
|
+
const dnssec = input.dnssec === true;
|
|
16
|
+
const https = input.https === true;
|
|
17
|
+
return Object.freeze({ version: 1, hostname, dnssec, https, owner: nonempty(input.owner, "DNS owner"), state: "caller-configures", operations: Object.freeze(["record", "certificate", ...(dnssec ? ["dnssec"] : [])]) });
|
|
18
|
+
}
|
|
19
|
+
/** Maps declared application surfaces without selecting a runtime vendor. */
|
|
20
|
+
export function applicationbridge(input = {}) {
|
|
21
|
+
if (!Array.isArray(input.surfaces) || input.surfaces.length === 0)
|
|
22
|
+
throw new TypeError("application bridge surfaces are required");
|
|
23
|
+
const ids = new Set();
|
|
24
|
+
const surfaces = input.surfaces.map((value) => {
|
|
25
|
+
const id = nonempty(value?.id, "application bridge surface id");
|
|
26
|
+
if (ids.has(id))
|
|
27
|
+
throw new TypeError(`application bridge surface id is duplicated: ${id}`);
|
|
28
|
+
ids.add(id);
|
|
29
|
+
const target = String(value.target ?? "");
|
|
30
|
+
if (!targets.has(target))
|
|
31
|
+
throw new TypeError(`application bridge target is invalid: ${target}`);
|
|
32
|
+
return Object.freeze({ id, target, capabilities: Object.freeze(unique(value.capabilities ?? [])) });
|
|
33
|
+
});
|
|
34
|
+
return Object.freeze({ version: 1, surfaces: Object.freeze(surfaces), state: "caller-connects" });
|
|
35
|
+
}
|
|
36
|
+
const targets = new Set(["browser", "desktop", "mobile", "extension", "miniapp"]);
|
|
37
|
+
function publichttps(value, name) { const output = String(value ?? ""); let url; try {
|
|
38
|
+
url = new URL(output);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
throw new TypeError(`${name} is invalid`);
|
|
42
|
+
} if (url.protocol !== "https:" || !url.hostname)
|
|
43
|
+
throw new TypeError(`${name} must use HTTPS`); return url.toString(); }
|
|
44
|
+
function hostnamevalue(value) { const output = String(value ?? "").toLowerCase(); if (!/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/.test(output))
|
|
45
|
+
throw new TypeError("DNS hostname is invalid"); return output; }
|
|
46
|
+
function nonempty(value, name) { const output = String(value ?? ""); if (!output)
|
|
47
|
+
throw new TypeError(`${name} is required`); return output; }
|
|
48
|
+
function unique(values) { if (!Array.isArray(values))
|
|
49
|
+
throw new TypeError("surface capabilities must be an array"); return [...new Set(values.map((value) => nonempty(value, "surface capability")))].sort(); }
|
|
50
|
+
//# sourceMappingURL=requirements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirements.js","sourceRoot":"","sources":["../../surfaces/requirements.ts"],"names":[],"mappings":"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"}
|
|
@@ -117,7 +117,7 @@ Each surface also emits `sha256.*.1.8.13`, `manifest.*.1.8.13.json` and, where e
|
|
|
117
117
|
|
|
118
118
|
## 1.8.14 release matrix
|
|
119
119
|
|
|
120
|
-
Version 1.8.14 keeps the release-tag-derived matrix and adds post-push container pull and smoke validation. The implementation records retention policy and keep/prune decisions but never removes caller-owned files. The release
|
|
120
|
+
Version 1.8.14 keeps the release-tag-derived matrix and adds post-push container pull and smoke validation. The implementation records retention policy and keep/prune decisions but never removes caller-owned files. The release contains 38 verified assets; iOS remains unavailable until caller-owned Apple signing and provisioning are configured.
|
|
121
121
|
|
|
122
122
|
| Surface | Architectures | Artifact naming contract |
|
|
123
123
|
| --- | --- | --- |
|
|
@@ -130,3 +130,5 @@ Version 1.8.14 keeps the release-tag-derived matrix and adds post-push container
|
|
|
130
130
|
| Browser extension | Manifest V3 | `saddle.extension.1.8.14.zip` |
|
|
131
131
|
|
|
132
132
|
Each surface also emits `sha256.*.1.8.14`, `manifest.*.1.8.14.json` and, where enabled by the release path, SBOM and provenance metadata. The Android manifest records `ci-test-key`, desktop manifests record `unsigned` and the container manifest records `caller-owned`. The container image additionally records `org.opencontainers.image.version=1.8.14`; the post-push workflow pulls that exact version and runs the CLI help smoke test.
|
|
133
|
+
|
|
134
|
+
The verified 1.8.14 release contains six Linux assets, six Windows assets, four macOS assets, two Android assets, one container archive, one browser extension, nine manifests and nine checksum files. The release-event mobile job did not bypass missing production credentials; the successful manual rerun used the explicit `ci-test-key` path.
|
package/docs/ecosystemplan.md
CHANGED
|
@@ -46,7 +46,7 @@ Each block follows the same loop:
|
|
|
46
46
|
3. Define the smallest transport-neutral contract.
|
|
47
47
|
4. Implement grouped logic in the domain folder without adding a vendor dependency unless required.
|
|
48
48
|
5. Add deterministic tests with fake transports and no real credentials.
|
|
49
|
-
6. Update API docs, README claims, changelog and `todo.md`.
|
|
49
|
+
6. Update API docs, README claims, changelog and `docs/todo.md`.
|
|
50
50
|
7. Run format, syntax, tests, package and security checks.
|
|
51
51
|
8. Commit and push the block before starting the next one.
|
|
52
52
|
|
|
@@ -32,11 +32,39 @@ The public contract uses plain objects and factory functions. The engine never r
|
|
|
32
32
|
| contract | responsibility | open choice |
|
|
33
33
|
|---|---|---|
|
|
34
34
|
| `storageadapter` | put, get, head, delete, and list artifacts | local, s3 compatible, webdav, hf, kaggle, or another backend |
|
|
35
|
+
| `storagepool` | read verified replicas, write to an explicit quorum, describe capabilities, and produce a repair plan | caller-authorized adapters with explicit priority and no background replication |
|
|
35
36
|
| `localmemory` | prepare, sync, and cleanup a working set | tmpfs, mmap, sqlite, r2, or a remote bridge |
|
|
37
|
+
| `workingbudget` / `workingadmission` / `bridgeplan` | plan bounded materialization and host-memory operations | caller-owned host adapter; the transport-neutral core never mounts, swaps, or executes a shell command |
|
|
38
|
+
| `providerchain` / `artifacthandoff` | select a declared eligible runner and prepare immutable transfer evidence | caller-authorized provider reports and a caller-owned dispatch or storage adapter |
|
|
39
|
+
| `deliverymanifest` / `verifydelivery` / `pwaplan` | verify immutable transport chunks and describe offline registration requirements | caller-owned CDN or web host; no dynamic import or service-worker registration from the core |
|
|
36
40
|
| `scheduler` | select the first available provider by stable priority | github, forgejo, gitea, gitlab, hf, kaggle, or custom |
|
|
37
41
|
| `engine` | coordinate the lifecycle and emit events | library, cli, browser, desktop, mobile, or service |
|
|
38
42
|
| `validatesession` | accept a versioned session record | browser capture, replay, or external event source |
|
|
39
43
|
|
|
44
|
+
`storagepool` is an additive storage contract. It selects members in stable caller-configured priority order, accepts only caller-owned adapters, verifies a returned digest when one is supplied by the caller or manifest, and returns per-member evidence. A quorum write reports partial outcomes and fails when the requested threshold is not met. `repairplan` is declarative: it identifies a source and candidate targets but never starts a background repair, probes an account, or mutates an adapter.
|
|
45
|
+
|
|
46
|
+
`workingadmission` selects serializable candidates against byte and entry budgets without reading data. `bridgeplan` can describe `temporaryfile`, `mmap`, `tmpfs`, `zram`, or `swap` only when a caller declares the capability. A returned `caller-executes` result contains preconditions and cleanup ownership; an unsupported capability is reported without a probe or side effect.
|
|
47
|
+
|
|
48
|
+
`materializationledger` records only validated materialization transitions and produces a `caller-cleans` plan. It does not unlink a file, unmount a volume, modify swap, or delete a remote replica.
|
|
49
|
+
|
|
50
|
+
`magicbytes`, `wasmplan`, `transformationkey`, `transformationcache`, and `executeisolated` define a separate binary boundary. The module classifies verified byte prefixes, plans bounded WASM work, invalidates cache reuse when source, compiler, key, or policy differ, and calls an injected isolated adapter only. It never creates a process, a container, a filesystem mount, or a network connection by itself.
|
|
51
|
+
|
|
52
|
+
`cacheeligibility` rejects reuse for outputs that are unverified, secret-bearing, private, environment-bound, or partial. It reports normalized reasons and never attempts to inspect, upload, or redact an artifact.
|
|
53
|
+
|
|
54
|
+
`archivelimits` and `archiveinspection` validate a caller-provided archive inventory before extraction. The contract rejects excess entry count, nested depth, output bytes, decompression ratio, absolute paths, and traversal paths. `extractarchive` requires an accepted inspection and an injected adapter, so the core neither opens an archive nor writes an extracted file.
|
|
55
|
+
|
|
56
|
+
`providerchain` consumes only explicit provider reports. It rejects unavailable, under-capacity, or capability-incompatible candidates with evidence, chooses the remaining candidate by stable priority, and emits a `caller-dispatches` plan rather than a remote request. `artifacthandoff` requires an artifact digest, size, provider identity, and retention choice before a caller transfers output to storage.
|
|
57
|
+
|
|
58
|
+
`renderdispatch` can serialize an existing dispatch plan only through an injected adapter. It does not post to a forge, create a workflow run, or own an authentication token.
|
|
59
|
+
|
|
60
|
+
`cancellationplan` represents a caller request to cancel a remote run. It deliberately reports the remote state as `unknown` until the selected provider adapter confirms an outcome, and it leaves any compensation decision to the caller.
|
|
61
|
+
|
|
62
|
+
`deliverymanifest` keeps ordered chunks immutable through content type, size, and SHA-256 metadata. `verifydelivery` checks received bytes without evaluating JavaScript or WASM. `pwaplan` only describes scope, offline intent, update policy, and declared service-worker support; the host decides whether to register anything.
|
|
63
|
+
|
|
64
|
+
`cdncapabilities` records only caller-reported delivery properties such as immutable caching, purge support, range delivery, integrity headers, CORS, and visibility. It never performs a CDN probe, purge, upload, or configuration mutation.
|
|
65
|
+
|
|
66
|
+
`miniappplan`, `dnsplan`, and `applicationbridge` add deployment-neutral application requirements. Mini App plans reject token-bearing input and require an HTTPS origin plus a caller-selected validation method. DNS records list ownership, DNSSEC and HTTPS requirements but cannot buy a domain, change a zone, or obtain a certificate. Surface bridges only report declared capabilities for browser, desktop, mobile, extension, and Mini App targets.
|
|
67
|
+
|
|
40
68
|
## execution lifecycle
|
|
41
69
|
|
|
42
70
|
```text
|
package/docs/plans/00.index.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Index
|
|
2
2
|
|
|
3
|
-
Project: **UKA** — computer use agent, sandbox for AI and captcha bypass. Super bot with computational memory. Package `@
|
|
3
|
+
Project: **UKA** — computer use agent, sandbox for AI and captcha bypass. Super bot with computational memory. Package `@wenathlan/saddle`. Domain acquired.
|
|
4
4
|
|
|
5
5
|
Theme: computer use, bypasses, captcha, sandbox for AI, container for AI, multi-platform bot, storage-to-compute memory transformation.
|
|
6
6
|
|
|
@@ -30,7 +30,7 @@ Theme: computer use, bypasses, captcha, sandbox for AI, container for AI, multi-
|
|
|
30
30
|
| 37 | [deploystrategy.md](./37.deploystrategy.md) | Deploy strategies (Netlify, Vercel, CI/CD, Docker, VM) |
|
|
31
31
|
| 36 | [computational.memory.md](./36.computational.memory.md) | Storage-to-compute memory transformation system |
|
|
32
32
|
| 39 | [multi.platform.bot.md](./39.multi.platform.bot.md) | Multi-platform bot (GitHub, GitLab, Forgejo, Gitea, Discord) |
|
|
33
|
-
| 40 | [npm.publish.md](./40.npm.publish.md) | NPM package publishing (`@
|
|
33
|
+
| 40 | [npm.publish.md](./40.npm.publish.md) | NPM package publishing (`@wenathlan/saddle`) |
|
|
34
34
|
| 46 | [scdnintegration.md](./46.scdnintegration.md) | SCDN integration for assets and deployment |
|
|
35
35
|
| 44 | [reference.md](./44.reference.md) | Reference index for all saddle documentation |
|
|
36
36
|
| 33 | [bots.codigo.revisao.md](./33.bots.codigo.revisao.md) | Best AI code review bots (research) |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 06 Dependencies
|
|
2
2
|
|
|
3
|
-
Dependency list of the `@
|
|
3
|
+
Dependency list of the `@wenathlan/UKA` package, grouped by function. Total: 65 packages (including the dev tooling set). The user asked for "50 to 60, or 60+. Counting 10 more", so this set covers browser automation, ai/vision, sandbox, server, db, storage and validation.
|
|
4
4
|
|
|
5
5
|
## Browser automation and mouse (8)
|
|
6
6
|
1. `playwright` — real brave/chromium automation via cdp.
|
|
@@ -396,8 +396,8 @@ OpenGraph (OG) e Twitter Card são metadados usados para social sharing. Menos c
|
|
|
396
396
|
|
|
397
397
|
<!-- Twitter Card -->
|
|
398
398
|
<meta name="twitter:card" content="summary_large_image">
|
|
399
|
-
<meta name="twitter:site" content="@
|
|
400
|
-
<meta name="twitter:creator" content="@
|
|
399
|
+
<meta name="twitter:site" content="@wenathlan">
|
|
400
|
+
<meta name="twitter:creator" content="@nasblor">
|
|
401
401
|
<meta name="twitter:title" content="Título da Página">
|
|
402
402
|
<meta name="twitter:description" content="Descrição da Página">
|
|
403
403
|
<meta name="twitter:image" content="https://example.com/image.jpg">
|
|
@@ -868,7 +868,7 @@ console.log(result.siteName);
|
|
|
868
868
|
|
|
869
869
|
### turndown 7.2.4 (Padrão)
|
|
870
870
|
|
|
871
|
-
`turndown` é o conversor HTML→Markdown mais popular. Usado pelo `@
|
|
871
|
+
`turndown` é o conversor HTML→Markdown mais popular. Usado pelo `@wenathlan/webscrape`.
|
|
872
872
|
|
|
873
873
|
```ts
|
|
874
874
|
import TurndownService from 'turndown';
|
|
@@ -189,7 +189,7 @@ export async function readFile(path: string): Promise<string | null> {
|
|
|
189
189
|
|
|
190
190
|
```json
|
|
191
191
|
{
|
|
192
|
-
"name": "@
|
|
192
|
+
"name": "@wenathlan/webscrape",
|
|
193
193
|
"exports": {
|
|
194
194
|
".": {
|
|
195
195
|
"types": "./dist/index.d.ts",
|
|
@@ -216,16 +216,16 @@ export async function readFile(path: string): Promise<string | null> {
|
|
|
216
216
|
|
|
217
217
|
```typescript
|
|
218
218
|
// Node.js
|
|
219
|
-
import { scrape } from '@
|
|
219
|
+
import { scrape } from '@wenathlan/webscrape/node';
|
|
220
220
|
|
|
221
221
|
// Browser
|
|
222
|
-
import { scrape } from '@
|
|
222
|
+
import { scrape } from '@wenathlan/webscrape/browser';
|
|
223
223
|
|
|
224
224
|
// Deno
|
|
225
|
-
import { scrape } from '@
|
|
225
|
+
import { scrape } from '@wenathlan/webscrape/deno';
|
|
226
226
|
|
|
227
227
|
// Universal (só APIs comuns)
|
|
228
|
-
import { scrape } from '@
|
|
228
|
+
import { scrape } from '@wenathlan/webscrape';
|
|
229
229
|
```
|
|
230
230
|
|
|
231
231
|
### 4.3. unenv polyfills
|
|
@@ -615,10 +615,10 @@ npx @arethetypeswrong/cli
|
|
|
615
615
|
|
|
616
616
|
**Exemplo de output:**
|
|
617
617
|
```
|
|
618
|
-
@
|
|
618
|
+
@wenathlan/webscrape
|
|
619
619
|
|
|
620
620
|
"import" - ESM
|
|
621
|
-
✅ @
|
|
621
|
+
✅ @wenathlan/webscrape → ./dist/index.js
|
|
622
622
|
✅ Types: ./dist/index.d.ts
|
|
623
623
|
|
|
624
624
|
"require" - CJS
|
|
@@ -626,7 +626,7 @@ npx @arethetypeswrong/cli
|
|
|
626
626
|
💡 Add a "require" condition
|
|
627
627
|
|
|
628
628
|
"browser" - Browser ESM
|
|
629
|
-
✅ @
|
|
629
|
+
✅ @wenathlan/webscrape → ./dist/browser.js
|
|
630
630
|
```
|
|
631
631
|
|
|
632
632
|
### 9.3. other tools
|
|
@@ -636,7 +636,7 @@ npx @arethetypeswrong/cli
|
|
|
636
636
|
npx arethetypeswrong --pack
|
|
637
637
|
|
|
638
638
|
# Verificar size do bundle
|
|
639
|
-
npx bundlephobia @
|
|
639
|
+
npx bundlephobia @wenathlan/webscrape
|
|
640
640
|
|
|
641
641
|
# Verificar dependências circulares
|
|
642
642
|
npx madge --circular src/
|
|
@@ -896,7 +896,7 @@ export async function loadConfig(root = '.'): Promise<Config | null> {
|
|
|
896
896
|
|
|
897
897
|
```json
|
|
898
898
|
{
|
|
899
|
-
"name": "@
|
|
899
|
+
"name": "@wenathlan/webscrape",
|
|
900
900
|
"exports": {
|
|
901
901
|
".": {
|
|
902
902
|
"types": "./dist/index.d.ts",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Phase: planning + research done
|
|
4
4
|
- [x] Folder structure (mirrors `cli`/`debonair`): `docs/plans`, `docs/talks`, `docs/logs`, `tests/{examples,output,scripts}`, `web`, `.github/workflows`.
|
|
5
|
-
- [x] Config files: `package.json` (`@
|
|
5
|
+
- [x] Config files: `package.json` (`@wenathlan/saddle`, 65 deps), `tsconfig.json`, `biome.json`, `vitest.config.ts`, `.github/workflows/saddle-tests.yml`, `.gitignore`, `.npmrc`, `.nvmrc`, `README.md`.
|
|
6
6
|
- [x] Research done (computer use, hcaptcha bypass, vercel sandbox, atlas agent browser).
|
|
7
7
|
- [x] Planning docs in `docs/plans/` (01 to 12 + index).
|
|
8
8
|
- [x] Applied skill arch: no `src/`, no vercel/netlify functions, mysql2, socket, no localhost, lowercase files, production = `web/`.
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
## Sumário Executivo
|
|
10
10
|
|
|
11
|
-
`@
|
|
11
|
+
`@wenathlan/webscrape` é um toolkit de scraping all-in-one que ocupa um nicho único: combina HTTP scraping, browser automation, serialização multi-formato, formatação para IA e um servidor HTTP — tudo em um único pacote TypeScript, sem depender de serviços em nuvem. A análise técnica revela que, enquanto competitors como Crawlee e Scrapy dominam em infraestrutura de produção (filas persistentes, Docker, anti-detection), webscrape supera em integração com IA, estimativa de tokens e chunking para RAG.
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -226,14 +226,14 @@ Nenhum outro competitor suporta Bun nativamente. Crawlee e Puppeteer são Node-o
|
|
|
226
226
|
|
|
227
227
|
```typescript
|
|
228
228
|
// Um pacote faz TUDO:
|
|
229
|
-
import { scrapeUrl } from '@
|
|
230
|
-
import { crawl } from '@
|
|
231
|
-
import { batchScrape } from '@
|
|
232
|
-
import { serializeResult } from '@
|
|
233
|
-
import { formatForAgent } from '@
|
|
234
|
-
import { chunkMarkdown } from '@
|
|
235
|
-
import { generateLlmsTxt } from '@
|
|
236
|
-
import { createServer } from '@
|
|
229
|
+
import { scrapeUrl } from '@wenathlan/webscrape/scrape';
|
|
230
|
+
import { crawl } from '@wenathlan/webscrape/crawler';
|
|
231
|
+
import { batchScrape } from '@wenathlan/webscrape/batch';
|
|
232
|
+
import { serializeResult } from '@wenathlan/webscrape/serialize';
|
|
233
|
+
import { formatForAgent } from '@wenathlan/webscrape/agent';
|
|
234
|
+
import { chunkMarkdown } from '@wenathlan/webscrape/chunking';
|
|
235
|
+
import { generateLlmsTxt } from '@wenathlan/webscrape/llms-txt';
|
|
236
|
+
import { createServer } from '@wenathlan/webscrape/server';
|
|
237
237
|
```
|
|
238
238
|
|
|
239
239
|
**Nenhum competitor combina:**
|
|
@@ -373,7 +373,7 @@ O Redis serialization (`JSON.SET` command) é exclusivo — permite popular Redi
|
|
|
373
373
|
|
|
374
374
|
```json
|
|
375
375
|
// webscrape: 1 package
|
|
376
|
-
@
|
|
376
|
+
@wenathlan/webscrape
|
|
377
377
|
|
|
378
378
|
// Crawlee: multi-package
|
|
379
379
|
crawlee
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# NPM Package Publishing for Saddle Robot
|
|
2
2
|
|
|
3
|
-
> Package `@
|
|
3
|
+
> Package `@wenathlan/saddle` published to NPM registry.
|
|
4
4
|
> Acts as both library and CLI binary.
|
|
5
5
|
|
|
6
6
|
## Overview
|
|
@@ -16,7 +16,7 @@ bypass, and memory engine capabilities.
|
|
|
16
16
|
|
|
17
17
|
```json
|
|
18
18
|
{
|
|
19
|
-
"name": "@
|
|
19
|
+
"name": "@wenathlan/saddle",
|
|
20
20
|
"version": "1.0.0",
|
|
21
21
|
"description": "Super bot: agent browser, captcha bypass, multi-platform GitHub/GitLab/Forgejo/Gitea automation with computational memory",
|
|
22
22
|
"main": "lib/index.js",
|
|
@@ -129,11 +129,11 @@ git push --follow-tags
|
|
|
129
129
|
### As Library
|
|
130
130
|
|
|
131
131
|
```bash
|
|
132
|
-
npm install @
|
|
132
|
+
npm install @wenathlan/saddle
|
|
133
133
|
```
|
|
134
134
|
|
|
135
135
|
```javascript
|
|
136
|
-
import { SaddleRobot } from '@
|
|
136
|
+
import { SaddleRobot } from '@wenathlan/saddle'
|
|
137
137
|
|
|
138
138
|
const robot = new SaddleRobot({
|
|
139
139
|
platform: 'github',
|
|
@@ -146,7 +146,7 @@ await robot.start()
|
|
|
146
146
|
### As CLI
|
|
147
147
|
|
|
148
148
|
```bash
|
|
149
|
-
npm install -g @
|
|
149
|
+
npm install -g @wenathlan/saddle
|
|
150
150
|
|
|
151
151
|
saddle --help
|
|
152
152
|
saddle capture --url https://example.com
|
|
@@ -200,7 +200,7 @@ main()
|
|
|
200
200
|
## Scoped Package Structure
|
|
201
201
|
|
|
202
202
|
```
|
|
203
|
-
@
|
|
203
|
+
@wenathlan/saddle/
|
|
204
204
|
├── lib/
|
|
205
205
|
│ ├── index.js main entry point
|
|
206
206
|
│ ├── index.cjs CommonJS entry point
|