@unfenced-ai/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/LICENSE +30 -0
  2. package/README.md +171 -0
  3. package/dist/client.d.ts +385 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +349 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/credentials.d.ts +14 -0
  8. package/dist/credentials.d.ts.map +1 -0
  9. package/dist/credentials.js +17 -0
  10. package/dist/credentials.js.map +1 -0
  11. package/dist/fetch.d.ts +16 -0
  12. package/dist/fetch.d.ts.map +1 -0
  13. package/dist/fetch.js +387 -0
  14. package/dist/fetch.js.map +1 -0
  15. package/dist/http.d.ts +76 -0
  16. package/dist/http.d.ts.map +1 -0
  17. package/dist/http.js +250 -0
  18. package/dist/http.js.map +1 -0
  19. package/dist/index.d.ts +53 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +41 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/library.d.ts +17 -0
  24. package/dist/library.d.ts.map +1 -0
  25. package/dist/library.js +25 -0
  26. package/dist/library.js.map +1 -0
  27. package/dist/memory.d.ts +13 -0
  28. package/dist/memory.d.ts.map +1 -0
  29. package/dist/memory.js +45 -0
  30. package/dist/memory.js.map +1 -0
  31. package/dist/permissions.d.ts +29 -0
  32. package/dist/permissions.d.ts.map +1 -0
  33. package/dist/permissions.js +69 -0
  34. package/dist/permissions.js.map +1 -0
  35. package/dist/protocol.d.ts +296 -0
  36. package/dist/protocol.d.ts.map +1 -0
  37. package/dist/protocol.js +89 -0
  38. package/dist/protocol.js.map +1 -0
  39. package/dist/session.d.ts +97 -0
  40. package/dist/session.d.ts.map +1 -0
  41. package/dist/session.js +88 -0
  42. package/dist/session.js.map +1 -0
  43. package/dist/sessions.d.ts +131 -0
  44. package/dist/sessions.d.ts.map +1 -0
  45. package/dist/sessions.js +197 -0
  46. package/dist/sessions.js.map +1 -0
  47. package/dist/token-usage.d.ts +11 -0
  48. package/dist/token-usage.d.ts.map +1 -0
  49. package/dist/token-usage.js +34 -0
  50. package/dist/token-usage.js.map +1 -0
  51. package/dist/types.d.ts +1409 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +2 -0
  54. package/dist/types.js.map +1 -0
  55. package/dist/url-identity.d.ts +8 -0
  56. package/dist/url-identity.d.ts.map +1 -0
  57. package/dist/url-identity.js +18 -0
  58. package/dist/url-identity.js.map +1 -0
  59. package/package.json +44 -0
package/dist/http.js ADDED
@@ -0,0 +1,250 @@
1
+ /** Sent as x-unfenced-client unless the caller overrides it. */
2
+ const SDK_CLIENT = "unfenced-sdk";
3
+ /** Keep unbudgeted session and account calls inside a normal client request window. */
4
+ const DEFAULT_REQUEST_BUDGET_MS = 45_000;
5
+ /**
6
+ * Raised for any non-2xx response, carrying the server's status and detail.
7
+ *
8
+ * `code` and `remedy` exist because the server's refusals are structured and the
9
+ * actionable half was being thrown away. The body arrives as
10
+ * `{error, detail, remedy}`; this used to store the raw text truncated to 300
11
+ * characters, which cut a longer refusal mid-string — so the JSON no longer
12
+ * parsed downstream, the caller got a blob of half-JSON as its "detail", and the
13
+ * `remedy` that says how to proceed was simply gone. A refusal an agent cannot
14
+ * read its way out of is an infinite loop, which is the failure the act-guard in
15
+ * core already paid for once.
16
+ */
17
+ export class UnfencedError extends Error {
18
+ status;
19
+ detail;
20
+ /** The server's error code, e.g. `use-fetch`, when the body carried one. */
21
+ code;
22
+ /** What the server said to do instead. The half worth keeping. */
23
+ remedy;
24
+ /** Validated server delay in milliseconds; does not authorize retrying a write. */
25
+ retryAfterMs;
26
+ /** Original HTTP Retry-After value (delay-seconds or HTTP-date), when present. */
27
+ retryAfter;
28
+ constructor(status, detail, parts = {}) {
29
+ super(`unfenced ${status}: ${detail}${parts.remedy ? ` - ${parts.remedy}` : ""}`, {
30
+ ...(parts.cause !== undefined ? { cause: parts.cause } : {}),
31
+ });
32
+ this.status = status;
33
+ this.detail = detail;
34
+ this.name = "UnfencedError";
35
+ this.code = parts.code;
36
+ this.remedy = parts.remedy;
37
+ this.retryAfterMs = parts.retryAfterMs;
38
+ this.retryAfter = parts.retryAfter;
39
+ }
40
+ }
41
+ /**
42
+ * One signal from up to two, without needing `AbortSignal.any`.
43
+ *
44
+ * `AbortSignal.any` landed in Node 20 and is still absent from some runtimes
45
+ * this client is meant to run in, and a client whose whole pitch is "platform
46
+ * fetch, runs anywhere that has one" should not acquire a floor for a
47
+ * convenience. Returns the single signal when there is only one, so the common
48
+ * case allocates nothing.
49
+ */
50
+ function combineSignals(a, b) {
51
+ const nothing = () => { };
52
+ if (!a)
53
+ return { signal: b, release: nothing };
54
+ if (!b)
55
+ return { signal: a, release: nothing };
56
+ const controller = new AbortController();
57
+ for (const s of [a, b]) {
58
+ if (s.aborted) {
59
+ controller.abort(s.reason);
60
+ return { signal: controller.signal, release: nothing };
61
+ }
62
+ }
63
+ // A controller whose only job is to take the two listeners off again.
64
+ //
65
+ // WHY IT HAS TO. `{once: true}` fires a listener once and removes it only
66
+ // when it FIRES; a request that succeeds never aborts, so both listeners
67
+ // stayed registered forever. One of the two signals is the per-request
68
+ // `AbortSignal.timeout`, which is garbage the moment the call returns — the
69
+ // other is the CLIENT's, which lives as long as the caller's task. So using
70
+ // the documented feature as documented ("Cancel every request this client
71
+ // makes") grew that signal's listener array by two per request and retained
72
+ // a closure with each: measured at 80 listeners after 40 successful calls,
73
+ // with nothing reporting it, because Node emits no MaxListenersExceeded
74
+ // warning for a bare AbortSignal.
75
+ //
76
+ // `signal` on addEventListener is the removal that cannot be forgotten: one
77
+ // `cleanup.abort()` in the request's `finally` detaches both.
78
+ const cleanup = new AbortController();
79
+ for (const s of [a, b]) {
80
+ s.addEventListener("abort", () => controller.abort(s.reason), {
81
+ once: true,
82
+ signal: cleanup.signal,
83
+ });
84
+ }
85
+ return { signal: controller.signal, release: () => cleanup.abort() };
86
+ }
87
+ export function parseErrorBody(text) {
88
+ try {
89
+ const body = JSON.parse(text);
90
+ if (!body || typeof body !== "object" || Array.isArray(body))
91
+ return null;
92
+ const fields = body;
93
+ return {
94
+ ...(typeof fields["error"] === "string" ? { error: fields["error"] } : {}),
95
+ ...(typeof fields["detail"] === "string" ? { detail: fields["detail"] } : {}),
96
+ ...(typeof fields["remedy"] === "string" ? { remedy: fields["remedy"] } : {}),
97
+ ...(typeof fields["retryAfterMs"] === "number" &&
98
+ Number.isSafeInteger(fields["retryAfterMs"]) &&
99
+ fields["retryAfterMs"] >= 0
100
+ ? { retryAfterMs: fields["retryAfterMs"] }
101
+ : {}),
102
+ };
103
+ }
104
+ catch {
105
+ return null;
106
+ }
107
+ }
108
+ /** Keep durations inside the timer range shared by supported runtimes. */
109
+ export function validateDuration(value, name) {
110
+ if (!Number.isInteger(value) || value < 0 || value > 2_147_483_647) {
111
+ throw new RangeError(`${name} must be an integer from 0 to 2147483647 milliseconds`);
112
+ }
113
+ }
114
+ /** Sends requests; identity headers remain live by reference until submission. */
115
+ export class Transport {
116
+ baseUrl;
117
+ apiKey;
118
+ /** Narrowed to what this client calls: a string URL and an init object. */
119
+ doFetch;
120
+ extraHeaders;
121
+ /** A caller's cancel for the whole client, combined with each call's budget. */
122
+ clientSignal;
123
+ constructor(options = {}) {
124
+ this.baseUrl = (options.baseUrl ?? "http://127.0.0.1:8787").replace(/\/$/, "");
125
+ this.apiKey = options.apiKey;
126
+ // Held BY REFERENCE, not copied. An MCP server passes an object it fills in
127
+ // later, once its peer identifies itself in `initialize` — copying here
128
+ // would freeze it empty and lose the client's name.
129
+ this.extraHeaders = options.headers ?? {};
130
+ this.clientSignal = options.signal;
131
+ const f = options.fetch ?? globalThis.fetch;
132
+ if (!f)
133
+ throw new Error("no fetch available - pass options.fetch");
134
+ this.doFetch = f.bind(globalThis);
135
+ }
136
+ /**
137
+ * Make a request, bounded.
138
+ *
139
+ * `budgetMs` is what is LEFT of the caller's `timeoutMs`, not a per-request
140
+ * allowance: `fetch()` computes a deadline once and hands each request the
141
+ * remainder, so ten polls cannot each take the whole budget. Nothing on this
142
+ * path carried a signal at all before — `grep -n AbortSignal packages/sdk`
143
+ * returned nothing — so `timeoutMs` bounded only the check between polls and
144
+ * a stalled connection wedged the call until the OS gave up.
145
+ */
146
+ async request(method, path, body, budgetMs, requestHeaders) {
147
+ const requestBudgetMs = budgetMs ?? DEFAULT_REQUEST_BUDGET_MS;
148
+ if (requestBudgetMs <= 0)
149
+ throw new UnfencedError(0, "request budget expired before submission", { code: "timeout" });
150
+ validateDuration(requestBudgetMs, "request budget");
151
+ // The default identity is applied per request, so a caller's object that
152
+ // gains a name after construction still overrides it. Node's fetch sends
153
+ // `user-agent: node`, so without this every SDK caller was anonymous.
154
+ const headers = {
155
+ "x-unfenced-client": SDK_CLIENT,
156
+ ...this.extraHeaders,
157
+ ...requestHeaders,
158
+ };
159
+ if (this.apiKey)
160
+ headers["authorization"] = `Bearer ${this.apiKey}`;
161
+ if (body !== undefined)
162
+ headers["content-type"] = "application/json";
163
+ const { signal, release } = combineSignals(this.clientSignal,
164
+ // A budget already spent is a request that must not be made at all.
165
+ AbortSignal.timeout(requestBudgetMs));
166
+ // `release` runs once this call is completely done — after the body, not
167
+ // after the headers. Releasing at `doFetch`'s resolve would leave a client
168
+ // cancel unable to interrupt a slow body read, which is most of the wait on
169
+ // a large page.
170
+ try {
171
+ return await this.send(method, path, headers, body, signal);
172
+ }
173
+ finally {
174
+ release();
175
+ }
176
+ }
177
+ /** The request itself, so the listener teardown above is one `finally`. */
178
+ async send(method, path, headers, body, signal) {
179
+ let response;
180
+ try {
181
+ // Cancellation is our boundary too: an injected fetch implementation
182
+ // may ignore an already-aborted signal and still submit a write.
183
+ if (signal?.aborted)
184
+ throw signal.reason;
185
+ response = await this.doFetch(`${this.baseUrl}${path}`, {
186
+ method,
187
+ headers,
188
+ ...(signal ? { signal } : {}),
189
+ ...(body !== undefined ? { body: JSON.stringify(body) } : {}),
190
+ });
191
+ }
192
+ catch (cause) {
193
+ // The commonest runtime failure for a hosted-service client — DNS gone,
194
+ // the worker down, a tunnel dropped, the deadline reached — reached the
195
+ // caller as a bare `TypeError: fetch failed` with no status, no code and
196
+ // no remedy, so the `catch (e) { if (e instanceof UnfencedError) }` shape
197
+ // the README teaches missed it entirely. Status 0 because nothing
198
+ // answered; `cause` is kept so the platform error is still readable.
199
+ const timedOut = signal?.aborted ||
200
+ (cause instanceof Error && (cause.name === "TimeoutError" || cause.name === "AbortError"));
201
+ throw new UnfencedError(0, cause instanceof Error ? cause.message : String(cause), timedOut
202
+ ? {
203
+ code: "timeout",
204
+ remedy: "No response arrived within the request budget. The request may already have been accepted; check its state before retrying a write, and verify service availability or timeoutMs.",
205
+ cause,
206
+ }
207
+ : {
208
+ code: "unreachable",
209
+ remedy: "No response was received. Check baseUrl, the network, and service availability. The request may already have been accepted; check its state before retrying a write.",
210
+ cause,
211
+ });
212
+ }
213
+ const retryAfter = response.headers?.get("retry-after") ?? undefined;
214
+ try {
215
+ if (!response.ok && response.status !== 202) {
216
+ const text = await response.text();
217
+ // Parse BEFORE truncating. Truncating first cut a structured refusal
218
+ // mid-JSON, so nothing downstream could read it back and the `remedy` —
219
+ // the only part that tells the caller what to do instead — was lost.
220
+ const body = parseErrorBody(text);
221
+ throw new UnfencedError(response.status, body?.detail ?? text.slice(0, 300), {
222
+ ...(body?.error ? { code: body.error } : {}),
223
+ ...(body?.remedy ? { remedy: body.remedy } : {}),
224
+ ...(body?.retryAfterMs !== undefined ? { retryAfterMs: body.retryAfterMs } : {}),
225
+ ...(retryAfter !== undefined ? { retryAfter } : {}),
226
+ });
227
+ }
228
+ return (await response.json());
229
+ }
230
+ catch (cause) {
231
+ if (cause instanceof UnfencedError)
232
+ throw cause;
233
+ // Headers do not complete the request. A stalled/truncated body must
234
+ // follow the same structured failure contract as a failed connection.
235
+ const timedOut = signal?.aborted ||
236
+ (cause instanceof Error && (cause.name === "TimeoutError" || cause.name === "AbortError"));
237
+ throw new UnfencedError(response.status, "The response body could not be read", {
238
+ ...(retryAfter !== undefined ? { retryAfter } : {}),
239
+ code: timedOut
240
+ ? "timeout"
241
+ : cause instanceof SyntaxError
242
+ ? "invalid-response"
243
+ : "unreachable",
244
+ remedy: "The request may already have been accepted. Check its state before retrying a write; verify service availability and the response format.",
245
+ cause,
246
+ });
247
+ }
248
+ }
249
+ }
250
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The unfenced SDK — a typed client for the unfenced server.
3
+ *
4
+ * unfenced fetches any page as clean, agent-ready content and drives a real
5
+ * browser (observe, click, type, extract) from the machine the server runs on,
6
+ * using that machine's IP and logged-in cookies. This client is how code talks
7
+ * to it: point it at a running server, and you get fetch, live sessions, and
8
+ * the recorded-session library, all typed. Zero dependencies — it uses the
9
+ * platform `fetch`.
10
+ *
11
+ * Node 22.12 or newer. This comment shipped inside the published `.d.ts` saying
12
+ * "Node 20+ and in the browser alike", which is what a customer's editor showed
13
+ * on hover, and both halves were false: the manifest has never been tested
14
+ * below 22, and `exports` now declares a `require` condition that Node loads
15
+ * through require(esm) only from 22.12. The browser half is contradicted by the
16
+ * README two paragraphs down — every request carries an `x-unfenced-client`
17
+ * header, which is not CORS-safelisted, so a cross-origin call preflights and
18
+ * the worker does not answer it.
19
+ *
20
+ * const ac = new Unfenced({ baseUrl: "http://127.0.0.1:8787", apiKey });
21
+ * const page = await ac.fetch("https://example.com"); // clean markdown
22
+ * const s = await ac.open("https://news.ycombinator.com"); // a live browser
23
+ * const snap = await s.observe(); // what's on it
24
+ * await s.click(snap.controls[0].ref); // do things
25
+ * await s.close();
26
+ *
27
+ * This file is the package entry and now a thin barrel: the client class lives
28
+ * in `./client.ts`, the `Session` handle in `./session.ts`, the domain and wire
29
+ * types in `./types.ts` and `./protocol.ts`, and the request bodies in the
30
+ * per-concern modules those two classes call (`fetch`, `sessions`, `library`,
31
+ * `permissions`, `memory`, `credentials`, over a shared `http` transport). Every
32
+ * name below was exported from here before the split and is re-exported from
33
+ * here unchanged — no consumer import needs to move.
34
+ */
35
+ /**
36
+ * The wire shapes live in `./protocol.js` and are re-exported here.
37
+ *
38
+ * They were declared inline until three copies of `ExtractedDoc` had drifted
39
+ * apart across this package, `@unfenced/extract` and the dashboard. `protocol`
40
+ * imports nothing and holds no runtime code beyond two field lists, so a client
41
+ * that only wants the types — the dashboard, which may not take a runtime
42
+ * dependency on any `@unfenced/*` package — can `import type` from it without
43
+ * pulling this class in behind it.
44
+ */
45
+ export type { Alternate, AlternateKind, ContentConfidence, Cost, EscalationRecord, ExtractedDoc, ExtractionMethod, FetchFailureMeta, FetchMeta, ImageRef, LinkRef, Meter, OutputFormat, PageType, StructuredDataKind, StructuredDatum, Tier, TokenEstimate, } from "./protocol.js";
46
+ export { WIRE_DOC_FIELDS, WIRE_META_FIELDS } from "./protocol.js";
47
+ export type { AccountPrefs, ActCode, ActEvidence, ActEvidenceKind, ActExpectation, Action, ActResult, AtAction, CredentialName, DownloadInfo, Fault, FetchOptions, FetchResult, Format, FormField, FormFillResult, InterruptKind, MediaItem, MemoryEntry, MemoryRecallOptions, Offer, OnAction, PageChanges, PageSnapshot, PendingApproval, PermissionsAnswer, ProviderSessionReason, ReadPage, SeenPage, SessionDetail, SessionInfo, SessionStep, SessionSummary, ConnectionSnapshot, SitePref, SnapshotElement, Spot, UnfencedOptions, } from "./types.js";
48
+ export { UnfencedError } from "./http.js";
49
+ export { Unfenced } from "./client.js";
50
+ export { urlIdentity } from "./url-identity.js";
51
+ export { toolTokenUsage, type TokenUsage } from "./token-usage.js";
52
+ export { Session, type SessionActOptions } from "./session.js";
53
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH;;;;;;;;;GASG;AACH,YAAY,EACV,SAAS,EACT,aAAa,EACb,iBAAiB,EACjB,IAAI,EACJ,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,SAAS,EACT,QAAQ,EACR,OAAO,EACP,KAAK,EACL,YAAY,EACZ,QAAQ,EACR,kBAAkB,EAClB,eAAe,EACf,IAAI,EACJ,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAElE,YAAY,EACV,YAAY,EACZ,OAAO,EACP,WAAW,EACX,eAAe,EACf,cAAc,EACd,MAAM,EACN,SAAS,EACT,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,KAAK,EACL,YAAY,EACZ,WAAW,EACX,MAAM,EACN,SAAS,EACT,cAAc,EACd,aAAa,EACb,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,KAAK,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,WAAW,EACX,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,QAAQ,EACR,eAAe,EACf,IAAI,EACJ,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * The unfenced SDK — a typed client for the unfenced server.
3
+ *
4
+ * unfenced fetches any page as clean, agent-ready content and drives a real
5
+ * browser (observe, click, type, extract) from the machine the server runs on,
6
+ * using that machine's IP and logged-in cookies. This client is how code talks
7
+ * to it: point it at a running server, and you get fetch, live sessions, and
8
+ * the recorded-session library, all typed. Zero dependencies — it uses the
9
+ * platform `fetch`.
10
+ *
11
+ * Node 22.12 or newer. This comment shipped inside the published `.d.ts` saying
12
+ * "Node 20+ and in the browser alike", which is what a customer's editor showed
13
+ * on hover, and both halves were false: the manifest has never been tested
14
+ * below 22, and `exports` now declares a `require` condition that Node loads
15
+ * through require(esm) only from 22.12. The browser half is contradicted by the
16
+ * README two paragraphs down — every request carries an `x-unfenced-client`
17
+ * header, which is not CORS-safelisted, so a cross-origin call preflights and
18
+ * the worker does not answer it.
19
+ *
20
+ * const ac = new Unfenced({ baseUrl: "http://127.0.0.1:8787", apiKey });
21
+ * const page = await ac.fetch("https://example.com"); // clean markdown
22
+ * const s = await ac.open("https://news.ycombinator.com"); // a live browser
23
+ * const snap = await s.observe(); // what's on it
24
+ * await s.click(snap.controls[0].ref); // do things
25
+ * await s.close();
26
+ *
27
+ * This file is the package entry and now a thin barrel: the client class lives
28
+ * in `./client.ts`, the `Session` handle in `./session.ts`, the domain and wire
29
+ * types in `./types.ts` and `./protocol.ts`, and the request bodies in the
30
+ * per-concern modules those two classes call (`fetch`, `sessions`, `library`,
31
+ * `permissions`, `memory`, `credentials`, over a shared `http` transport). Every
32
+ * name below was exported from here before the split and is re-exported from
33
+ * here unchanged — no consumer import needs to move.
34
+ */
35
+ export { WIRE_DOC_FIELDS, WIRE_META_FIELDS } from "./protocol.js";
36
+ export { UnfencedError } from "./http.js";
37
+ export { Unfenced } from "./client.js";
38
+ export { urlIdentity } from "./url-identity.js";
39
+ export { toolTokenUsage } from "./token-usage.js";
40
+ export { Session } from "./session.js";
41
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAgCH,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AA2ClE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAmB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,OAAO,EAA0B,MAAM,cAAc,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The recorded-session library and the two raw logs beside it.
3
+ *
4
+ * The bodies of the `Unfenced` methods under `// ---- library & memory`, moved
5
+ * out unchanged save for `this.request` becoming `http.request`.
6
+ */
7
+ import { Transport } from "./http.js";
8
+ import type { SessionDetail, SessionSummary } from "./types.js";
9
+ export declare function sessions(http: Transport, query?: {
10
+ kind?: string;
11
+ q?: string;
12
+ limit?: number;
13
+ }): Promise<SessionSummary[]>;
14
+ export declare function recordedSession(http: Transport, id: string): Promise<SessionDetail>;
15
+ export declare function history(http: Transport, limit?: number): Promise<unknown[]>;
16
+ export declare function domains(http: Transport): Promise<unknown[]>;
17
+ //# sourceMappingURL=library.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"library.d.ts","sourceRoot":"","sources":["../src/library.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEhE,wBAAgB,QAAQ,CACtB,IAAI,EAAE,SAAS,EACf,KAAK,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACxD,OAAO,CAAC,cAAc,EAAE,CAAC,CAS3B;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAEnF;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAIvE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAE3D"}
@@ -0,0 +1,25 @@
1
+ export function sessions(http, query = {}) {
2
+ const p = new URLSearchParams();
3
+ if (query.kind)
4
+ p.set("kind", query.kind);
5
+ if (query.q)
6
+ p.set("q", query.q);
7
+ if (query.limit)
8
+ p.set("limit", String(query.limit));
9
+ const qs = p.toString();
10
+ return http
11
+ .request("GET", `/sessions${qs ? `?${qs}` : ""}`)
12
+ .then((r) => r.sessions);
13
+ }
14
+ export function recordedSession(http, id) {
15
+ return http.request("GET", `/sessions/${id}`).then((r) => r.session);
16
+ }
17
+ export function history(http, limit = 50) {
18
+ return http
19
+ .request("GET", `/history?limit=${limit}`)
20
+ .then((r) => r.entries);
21
+ }
22
+ export function domains(http) {
23
+ return http.request("GET", "/domains").then((r) => r.domains);
24
+ }
25
+ //# sourceMappingURL=library.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"library.js","sourceRoot":"","sources":["../src/library.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,QAAQ,CACtB,IAAe,EACf,QAAuD,EAAE;IAEzD,MAAM,CAAC,GAAG,IAAI,eAAe,EAAE,CAAC;IAChC,IAAI,KAAK,CAAC,IAAI;QAAE,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,KAAK,CAAC,CAAC;QAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,KAAK;QAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;IACxB,OAAO,IAAI;SACR,OAAO,CAAiC,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;SAChF,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAe,EAAE,EAAU;IACzD,OAAO,IAAI,CAAC,OAAO,CAA6B,KAAK,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AACnG,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAe,EAAE,KAAK,GAAG,EAAE;IACjD,OAAO,IAAI;SACR,OAAO,CAAyB,KAAK,EAAE,kBAAkB,KAAK,EAAE,CAAC;SACjE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAe;IACrC,OAAO,IAAI,CAAC,OAAO,CAAyB,KAAK,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AACxF,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The agent's task-memory scratchpad: remember, recall, forget.
3
+ *
4
+ * The bodies of the `Unfenced` methods under `// ---- task memory`, moved out
5
+ * with only `this.request` -> `http.request`. `recall` is one function here; the
6
+ * two public overloads stay declared on the `Unfenced` class.
7
+ */
8
+ import { Transport } from "./http.js";
9
+ import type { MemoryEntry, MemoryRecallOptions } from "./types.js";
10
+ export declare function remember(http: Transport, key: string, value: string): Promise<MemoryEntry>;
11
+ export declare function recall(http: Transport, keyOrOptions?: string | MemoryRecallOptions): Promise<MemoryEntry | MemoryEntry[] | undefined>;
12
+ export declare function forget(http: Transport, key: string): Promise<boolean>;
13
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,SAAS,EAAiB,MAAM,WAAW,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEnE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAI1F;AAED,wBAAgB,MAAM,CACpB,IAAI,EAAE,SAAS,EACf,YAAY,CAAC,EAAE,MAAM,GAAG,mBAAmB,GAC1C,OAAO,CAAC,WAAW,GAAG,WAAW,EAAE,GAAG,SAAS,CAAC,CAsBlD;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAIrE"}
package/dist/memory.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The agent's task-memory scratchpad: remember, recall, forget.
3
+ *
4
+ * The bodies of the `Unfenced` methods under `// ---- task memory`, moved out
5
+ * with only `this.request` -> `http.request`. `recall` is one function here; the
6
+ * two public overloads stay declared on the `Unfenced` class.
7
+ */
8
+ import { UnfencedError } from "./http.js";
9
+ export function remember(http, key, value) {
10
+ return http
11
+ .request("POST", "/memory", { key, value })
12
+ .then((r) => r.entry);
13
+ }
14
+ export function recall(http, keyOrOptions) {
15
+ if (keyOrOptions === undefined || typeof keyOrOptions === "object") {
16
+ const options = keyOrOptions;
17
+ const query = new URLSearchParams();
18
+ if (options?.prefix)
19
+ query.set("prefix", options.prefix);
20
+ if (options?.limit !== undefined)
21
+ query.set("limit", String(options.limit));
22
+ const suffix = query.toString() ? `?${query.toString()}` : "";
23
+ return http
24
+ .request("GET", `/memory${suffix}`)
25
+ .then((r) => r.entries);
26
+ }
27
+ const key = keyOrOptions;
28
+ return http
29
+ .request("GET", `/memory/${encodeURIComponent(key)}`)
30
+ .then((r) => r.entry)
31
+ .catch((error) => {
32
+ // A missing key is a 404 — an absence, not an error. Answer `undefined`
33
+ // so a caller can ask "do I have this?" without a try/catch, the same
34
+ // way `get` does on the store.
35
+ if (error instanceof UnfencedError && error.status === 404)
36
+ return undefined;
37
+ throw error;
38
+ });
39
+ }
40
+ export function forget(http, key) {
41
+ return http
42
+ .request("DELETE", `/memory/${encodeURIComponent(key)}`)
43
+ .then((r) => r.removed);
44
+ }
45
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAa,aAAa,EAAE,MAAM,WAAW,CAAC;AAGrD,MAAM,UAAU,QAAQ,CAAC,IAAe,EAAE,GAAW,EAAE,KAAa;IAClE,OAAO,IAAI;SACR,OAAO,CAAyB,MAAM,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;SAClE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,MAAM,CACpB,IAAe,EACf,YAA2C;IAE3C,IAAI,YAAY,KAAK,SAAS,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACnE,MAAM,OAAO,GAAG,YAAY,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,IAAI,OAAO,EAAE,MAAM;YAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACzD,IAAI,OAAO,EAAE,KAAK,KAAK,SAAS;YAAE,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5E,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,OAAO,IAAI;aACR,OAAO,CAA6B,KAAK,EAAE,UAAU,MAAM,EAAE,CAAC;aAC9D,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IACD,MAAM,GAAG,GAAG,YAAY,CAAC;IACzB,OAAO,IAAI;SACR,OAAO,CAAyB,KAAK,EAAE,WAAW,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;SAC5E,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;SACpB,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACf,wEAAwE;QACxE,sEAAsE;QACtE,+BAA+B;QAC/B,IAAI,KAAK,YAAY,aAAa,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,SAAS,CAAC;QAC7E,MAAM,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,IAAe,EAAE,GAAW;IACjD,OAAO,IAAI;SACR,OAAO,CAAuB,QAAQ,EAAE,WAAW,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;SAC7E,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The act-allowlist tier: what the agent may act on, and links to change it.
3
+ *
4
+ * The bodies of the `Unfenced` methods under `// ---- act-allowlist`, moved out
5
+ * with only `this.request` -> `http.request`. `unreadableAllowlist` lives here
6
+ * because these are its only callers.
7
+ */
8
+ import { Transport } from "./http.js";
9
+ export declare function permissions(http: Transport): Promise<string[]>;
10
+ export declare function permissionScope(http: Transport): Promise<{
11
+ entries: Array<{
12
+ host: string;
13
+ mode: "free" | "approve" | "read";
14
+ }>;
15
+ anySite: boolean;
16
+ excludedSites: string[];
17
+ allowSiteRequests?: boolean;
18
+ }>;
19
+ export declare function permissionEntries(http: Transport): Promise<Array<{
20
+ host: string;
21
+ mode: "free" | "approve" | "read";
22
+ }>>;
23
+ export declare function connectLink(http: Transport, host: string, opts?: {
24
+ label?: string;
25
+ mode?: "credential" | "permission";
26
+ }): Promise<string>;
27
+ export declare function allow(http: Transport, site: string): Promise<string>;
28
+ export declare function deny(http: Transport, site: string): Promise<boolean>;
29
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAatC,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAS9D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IACxD,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;IACpE,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC,CAuBD;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;CAAE,CAAC,CAAC,CAcrE;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,CAAA;CAAO,GAChE,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEpE;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAIpE"}
@@ -0,0 +1,69 @@
1
+ /** Why the list could not be read, in words a caller can hand to a person. */
2
+ function unreadableAllowlist(detail) {
3
+ return ("the act-allowlist could not be read, so which sites the agent may act on is unknown" +
4
+ (detail ? `: ${detail}` : "") +
5
+ ". This is NOT a refusal by the owner - acting fails closed until it can be read again, " +
6
+ "so treat it as a transient fault and retry, not as policy.");
7
+ }
8
+ export function permissions(http) {
9
+ // THROWS when the list could not be read, deliberately. The route omits
10
+ // `allowed` rather than sending [] when the store is unreachable, because an
11
+ // empty array is indistinguishable from "you granted nothing" — and an agent
12
+ // that reads an outage as policy stops asking for the grant it needs.
13
+ return http.request("GET", "/permissions").then((r) => {
14
+ if (!r.allowed)
15
+ throw new Error(unreadableAllowlist(r.detail));
16
+ return r.allowed;
17
+ });
18
+ }
19
+ export function permissionScope(http) {
20
+ return http
21
+ .request("GET", "/permissions")
22
+ .then((r) => {
23
+ const anySite = r.anySite === true;
24
+ const excludedSites = r.excludedSites ?? [];
25
+ const policy = r.allowSiteRequests === false ? { allowSiteRequests: false } : {};
26
+ if (r.entries)
27
+ return { entries: r.entries, anySite, excludedSites, ...policy };
28
+ if (!r.allowed)
29
+ throw new Error(unreadableAllowlist(r.detail));
30
+ return {
31
+ entries: r.allowed.map((host) => ({ host, mode: "free" })),
32
+ anySite,
33
+ excludedSites,
34
+ ...policy,
35
+ };
36
+ });
37
+ }
38
+ export function permissionEntries(http) {
39
+ return http
40
+ .request("GET", "/permissions")
41
+ .then((r) => {
42
+ // Same refusal as permissions(). Without it this line is `undefined.map`,
43
+ // which is loud but tells the caller nothing it can act on.
44
+ if (r.entries)
45
+ return r.entries;
46
+ if (!r.allowed)
47
+ throw new Error(unreadableAllowlist(r.detail));
48
+ return r.allowed.map((host) => ({ host, mode: "free" }));
49
+ });
50
+ }
51
+ export function connectLink(http, host, opts = {}) {
52
+ const q = new URLSearchParams({ host });
53
+ if (opts.label)
54
+ q.set("label", opts.label);
55
+ if (opts.mode)
56
+ q.set("mode", opts.mode);
57
+ return http
58
+ .request("GET", `/connect-link?${q.toString()}`)
59
+ .then((r) => r.setupUrl);
60
+ }
61
+ export function allow(http, site) {
62
+ return http.request("POST", "/permissions", { site }).then((r) => r.allowed);
63
+ }
64
+ export function deny(http, site) {
65
+ return http
66
+ .request("DELETE", `/permissions/${encodeURIComponent(site)}`)
67
+ .then((r) => r.removed);
68
+ }
69
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}