@naulon/wayfarer 0.1.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.
- package/README.md +39 -0
- package/dist/agent.d.ts +77 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +235 -0
- package/dist/agent.js.map +1 -0
- package/dist/allocation.d.ts +36 -0
- package/dist/allocation.d.ts.map +1 -0
- package/dist/allocation.js +45 -0
- package/dist/allocation.js.map +1 -0
- package/dist/appraise.d.ts +3 -0
- package/dist/appraise.d.ts.map +1 -0
- package/dist/appraise.js +60 -0
- package/dist/appraise.js.map +1 -0
- package/dist/buyer.d.ts +195 -0
- package/dist/buyer.d.ts.map +1 -0
- package/dist/buyer.js +254 -0
- package/dist/buyer.js.map +1 -0
- package/dist/decide.d.ts +115 -0
- package/dist/decide.d.ts.map +1 -0
- package/dist/decide.js +206 -0
- package/dist/decide.js.map +1 -0
- package/dist/discover.d.ts +10 -0
- package/dist/discover.d.ts.map +1 -0
- package/dist/discover.js +5 -0
- package/dist/discover.js.map +1 -0
- package/dist/discovery.d.ts +26 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +93 -0
- package/dist/discovery.js.map +1 -0
- package/dist/gateway.d.ts +117 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +187 -0
- package/dist/gateway.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/lib.d.ts +40 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +44 -0
- package/dist/lib.js.map +1 -0
- package/dist/licenseStore.d.ts +56 -0
- package/dist/licenseStore.d.ts.map +1 -0
- package/dist/licenseStore.js +79 -0
- package/dist/licenseStore.js.map +1 -0
- package/dist/memo.d.ts +43 -0
- package/dist/memo.d.ts.map +1 -0
- package/dist/memo.js +102 -0
- package/dist/memo.js.map +1 -0
- package/dist/origin-policy.d.ts +74 -0
- package/dist/origin-policy.d.ts.map +1 -0
- package/dist/origin-policy.js +88 -0
- package/dist/origin-policy.js.map +1 -0
- package/dist/paidFetch.d.ts +14 -0
- package/dist/paidFetch.d.ts.map +1 -0
- package/dist/paidFetch.js +93 -0
- package/dist/paidFetch.js.map +1 -0
- package/dist/pay.d.ts +3 -0
- package/dist/pay.d.ts.map +1 -0
- package/dist/pay.js +82 -0
- package/dist/pay.js.map +1 -0
- package/dist/pop.d.ts +8 -0
- package/dist/pop.d.ts.map +1 -0
- package/dist/pop.js +25 -0
- package/dist/pop.js.map +1 -0
- package/dist/rail.d.ts +18 -0
- package/dist/rail.d.ts.map +1 -0
- package/dist/rail.js +73 -0
- package/dist/rail.js.map +1 -0
- package/dist/rss.d.ts +38 -0
- package/dist/rss.d.ts.map +1 -0
- package/dist/rss.js +110 -0
- package/dist/rss.js.map +1 -0
- package/dist/sign.d.ts +13 -0
- package/dist/sign.d.ts.map +1 -0
- package/dist/sign.js +52 -0
- package/dist/sign.js.map +1 -0
- package/dist/types.d.ts +75 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/wallet.d.ts +12 -0
- package/dist/wallet.d.ts.map +1 -0
- package/dist/wallet.js +46 -0
- package/dist/wallet.js.map +1 -0
- package/package.json +42 -0
package/dist/rss.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
const ENTITIES = {
|
|
2
|
+
amp: "&",
|
|
3
|
+
lt: "<",
|
|
4
|
+
gt: ">",
|
|
5
|
+
quot: '"',
|
|
6
|
+
apos: "'",
|
|
7
|
+
"#39": "'",
|
|
8
|
+
};
|
|
9
|
+
/** Decode the handful of XML entities a feed actually emits (+ numeric refs). */
|
|
10
|
+
function decodeEntities(s) {
|
|
11
|
+
return s.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (whole, code) => {
|
|
12
|
+
if (code[0] === "#") {
|
|
13
|
+
const cp = code[1] === "x" || code[1] === "X"
|
|
14
|
+
? Number.parseInt(code.slice(2), 16)
|
|
15
|
+
: Number.parseInt(code.slice(1), 10);
|
|
16
|
+
return Number.isFinite(cp) ? String.fromCodePoint(cp) : whole;
|
|
17
|
+
}
|
|
18
|
+
return ENTITIES[code] ?? whole;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/** Strip a `<![CDATA[ ... ]]>` wrapper if present, then trim. */
|
|
22
|
+
function unwrap(raw) {
|
|
23
|
+
const cdata = raw.match(/^\s*<!\[CDATA\[([\s\S]*?)\]\]>\s*$/);
|
|
24
|
+
return (cdata ? cdata[1] : raw).trim();
|
|
25
|
+
}
|
|
26
|
+
/** Inner text of the first `<tag …>…</tag>` in `block`, decoded. "" if absent. */
|
|
27
|
+
function tag(block, name) {
|
|
28
|
+
const re = new RegExp(`<${name}(?:\\s[^>]*)?>([\\s\\S]*?)</${name}>`, "i");
|
|
29
|
+
const m = block.match(re);
|
|
30
|
+
if (!m)
|
|
31
|
+
return "";
|
|
32
|
+
const inner = unwrap(m[1]);
|
|
33
|
+
// CDATA content is literal; only decode entities outside a CDATA section.
|
|
34
|
+
return /^\s*<!\[CDATA\[/.test(m[1]) ? inner : decodeEntities(inner);
|
|
35
|
+
}
|
|
36
|
+
/** `href` of a self-closing `<link … href="…"/>` (Atom-style), decoded. "" if absent. */
|
|
37
|
+
function linkHref(block) {
|
|
38
|
+
const m = block.match(/<link\b[^>]*\bhref=["']([^"']+)["'][^>]*\/?>/i);
|
|
39
|
+
return m ? decodeEntities(m[1]) : "";
|
|
40
|
+
}
|
|
41
|
+
/** Parse an RSS 2.0 (or Atom-ish) document into its items. Lenient by design. */
|
|
42
|
+
export function parseRss(xml) {
|
|
43
|
+
const items = [];
|
|
44
|
+
for (const m of xml.matchAll(/<(?:item|entry)\b[\s\S]*?<\/(?:item|entry)>/gi)) {
|
|
45
|
+
const block = m[0];
|
|
46
|
+
const link = tag(block, "link") || linkHref(block);
|
|
47
|
+
const item = {
|
|
48
|
+
title: tag(block, "title"),
|
|
49
|
+
link,
|
|
50
|
+
description: tag(block, "description") || tag(block, "summary"),
|
|
51
|
+
guid: tag(block, "guid") || undefined,
|
|
52
|
+
};
|
|
53
|
+
const body = tag(block, "content:encoded");
|
|
54
|
+
if (body)
|
|
55
|
+
item.contentEncoded = body;
|
|
56
|
+
items.push(item);
|
|
57
|
+
}
|
|
58
|
+
return items;
|
|
59
|
+
}
|
|
60
|
+
/** Slug = the last non-empty path segment of the item's link (or guid). */
|
|
61
|
+
export function slugFromLink(link) {
|
|
62
|
+
if (!link)
|
|
63
|
+
return "";
|
|
64
|
+
let path = link;
|
|
65
|
+
try {
|
|
66
|
+
path = new URL(link).pathname;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Relative or malformed — fall back to the raw string, sans query/hash.
|
|
70
|
+
path = link.split(/[?#]/)[0];
|
|
71
|
+
}
|
|
72
|
+
const segs = path.split("/").filter(Boolean);
|
|
73
|
+
const last = segs[segs.length - 1] ?? "";
|
|
74
|
+
try {
|
|
75
|
+
return decodeURIComponent(last);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return last;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The teaser boundary — what the agent may read for FREE, pre-payment.
|
|
83
|
+
*
|
|
84
|
+
* This is a product decision, not a parsing detail: a feed that ships the full
|
|
85
|
+
* body in `<content:encoded>` would let the agent bypass the toll at discovery.
|
|
86
|
+
* So we read the teaser field only and never the body, regardless of what the
|
|
87
|
+
* feed includes. Keeping it a named function makes that line explicit and easy
|
|
88
|
+
* to retune per publisher.
|
|
89
|
+
*/
|
|
90
|
+
export function extractTeaser(item) {
|
|
91
|
+
return item.description.trim();
|
|
92
|
+
}
|
|
93
|
+
/** Map a parsed item to a free-teaser Candidate (slug + title + teaser). */
|
|
94
|
+
export function rssItemToCandidate(item) {
|
|
95
|
+
return {
|
|
96
|
+
slug: slugFromLink(item.link || item.guid || ""),
|
|
97
|
+
title: item.title,
|
|
98
|
+
summary: extractTeaser(item),
|
|
99
|
+
// Carry the real feed link so pay/quote hit the publisher's actual URL shape
|
|
100
|
+
// (e.g. /articles/<slug>) instead of reconstructing /essays/<slug>.
|
|
101
|
+
url: item.link || undefined,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/** Full feed → candidates, dropping anything with no usable slug. */
|
|
105
|
+
export function rssToCandidates(xml) {
|
|
106
|
+
return parseRss(xml)
|
|
107
|
+
.map(rssItemToCandidate)
|
|
108
|
+
.filter((c) => c.slug.length > 0);
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=rss.js.map
|
package/dist/rss.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rss.js","sourceRoot":"","sources":["../src/rss.ts"],"names":[],"mappings":"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"}
|
package/dist/sign.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Test seam: forget the cached identity (pairs with shared's resetConfig). */
|
|
2
|
+
export declare function resetAgentIdentity(): void;
|
|
3
|
+
/** The three Web Bot Auth headers for a request to `url`, or null when the
|
|
4
|
+
* signing identity isn't configured. Signed per call — the ~1-minute validity
|
|
5
|
+
* window means a signature is never reusable across a slow run. */
|
|
6
|
+
export declare function botAuthHeadersFor(url: string): Record<string, string> | null;
|
|
7
|
+
/**
|
|
8
|
+
* fetch with the wayfarer's Web Bot Auth identity attached (when configured).
|
|
9
|
+
* Caller headers win on collision — not that anything else sets these — and an
|
|
10
|
+
* unconfigured agent falls through to the exact fetch it always made.
|
|
11
|
+
*/
|
|
12
|
+
export declare function agentFetch(url: string, init?: RequestInit): Promise<Response>;
|
|
13
|
+
//# sourceMappingURL=sign.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sign.d.ts","sourceRoot":"","sources":["../src/sign.ts"],"names":[],"mappings":"AAgCA,+EAA+E;AAC/E,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;oEAEoE;AACpE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAK5E;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAKnF"}
|
package/dist/sign.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web Bot Auth request signing (WBA slice 3) — the wayfarer as a signing agent.
|
|
3
|
+
*
|
|
4
|
+
* When the operator configures a signing identity (BOT_AUTH_SIGNING_KEY) and a
|
|
5
|
+
* directory host to advertise (BOT_AUTH_SIGNATURE_AGENT), every outbound
|
|
6
|
+
* wayfarer request carries the three RFC 9421 headers, so ANY Web-Bot-Auth
|
|
7
|
+
* verifier — our own gate, or a Cloudflare-fronted publisher — can prove who
|
|
8
|
+
* is calling instead of trusting the UA string. Unconfigured, `agentFetch` is
|
|
9
|
+
* a plain fetch: byte-identical headers, the same regression bar the gate's
|
|
10
|
+
* verifier holds for unsigned traffic.
|
|
11
|
+
*/
|
|
12
|
+
import { botAuthKeyFromSeed, getConfig, signBotAuth } from "@naulon/shared";
|
|
13
|
+
/** Lazily resolved once per process; `undefined` = not yet looked at,
|
|
14
|
+
* `null` = signing not configured. */
|
|
15
|
+
let identity;
|
|
16
|
+
function resolveIdentity() {
|
|
17
|
+
if (identity !== undefined)
|
|
18
|
+
return identity;
|
|
19
|
+
const cfg = getConfig();
|
|
20
|
+
identity =
|
|
21
|
+
cfg.BOT_AUTH_SIGNING_KEY && cfg.BOT_AUTH_SIGNATURE_AGENT
|
|
22
|
+
? { key: botAuthKeyFromSeed(cfg.BOT_AUTH_SIGNING_KEY), agent: cfg.BOT_AUTH_SIGNATURE_AGENT }
|
|
23
|
+
: null;
|
|
24
|
+
return identity;
|
|
25
|
+
}
|
|
26
|
+
/** Test seam: forget the cached identity (pairs with shared's resetConfig). */
|
|
27
|
+
export function resetAgentIdentity() {
|
|
28
|
+
identity = undefined;
|
|
29
|
+
}
|
|
30
|
+
/** The three Web Bot Auth headers for a request to `url`, or null when the
|
|
31
|
+
* signing identity isn't configured. Signed per call — the ~1-minute validity
|
|
32
|
+
* window means a signature is never reusable across a slow run. */
|
|
33
|
+
export function botAuthHeadersFor(url) {
|
|
34
|
+
const id = resolveIdentity();
|
|
35
|
+
if (!id)
|
|
36
|
+
return null;
|
|
37
|
+
const authority = new URL(url).host;
|
|
38
|
+
return { ...signBotAuth({ key: id.key, authority, tag: "web-bot-auth", agent: id.agent }) };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* fetch with the wayfarer's Web Bot Auth identity attached (when configured).
|
|
42
|
+
* Caller headers win on collision — not that anything else sets these — and an
|
|
43
|
+
* unconfigured agent falls through to the exact fetch it always made.
|
|
44
|
+
*/
|
|
45
|
+
export async function agentFetch(url, init) {
|
|
46
|
+
const signed = botAuthHeadersFor(url);
|
|
47
|
+
if (!signed)
|
|
48
|
+
return fetch(url, init);
|
|
49
|
+
const headers = { ...signed, ...(init?.headers ?? {}) };
|
|
50
|
+
return fetch(url, { ...init, headers });
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=sign.js.map
|
package/dist/sign.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sign.js","sourceRoot":"","sources":["../src/sign.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,WAAW,EAAmB,MAAM,gBAAgB,CAAC;AAO7F;uCACuC;AACvC,IAAI,QAA0C,CAAC;AAE/C,SAAS,eAAe;IACtB,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC5C,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,QAAQ;QACN,GAAG,CAAC,oBAAoB,IAAI,GAAG,CAAC,wBAAwB;YACtD,CAAC,CAAC,EAAE,GAAG,EAAE,kBAAkB,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,wBAAwB,EAAE;YAC5F,CAAC,CAAC,IAAI,CAAC;IACX,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,kBAAkB;IAChC,QAAQ,GAAG,SAAS,CAAC;AACvB,CAAC;AAED;;oEAEoE;AACpE,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,EAAE,GAAG,eAAe,EAAE,CAAC;IAC7B,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IACrB,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;IACpC,OAAO,EAAE,GAAG,WAAW,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;AAC9F,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,IAAkB;IAC9D,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,CAAE,IAAI,EAAE,OAA8C,IAAI,EAAE,CAAC,EAAE,CAAC;IAChG,OAAO,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAC1C,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/** Wayfarer domain types — the shapes that flow through discover → … → ground. */
|
|
2
|
+
import type { Usdc } from "@naulon/shared";
|
|
3
|
+
/** An essay the agent could pay to read, before it has decided anything. */
|
|
4
|
+
export interface Candidate {
|
|
5
|
+
slug: string;
|
|
6
|
+
title: string;
|
|
7
|
+
/** Public teaser the agent reads for free to judge relevance. */
|
|
8
|
+
summary: string;
|
|
9
|
+
/**
|
|
10
|
+
* Publisher host this candidate is served from (e.g. `example.com`). Optional:
|
|
11
|
+
* the single-gate pipeline leaves it unset (one configured origin). Multi-gate
|
|
12
|
+
* discovery (the fleet directory) populates it, and the policy engine uses it
|
|
13
|
+
* for domain allow/deny + per-domain caps.
|
|
14
|
+
*/
|
|
15
|
+
host?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Canonical URL this candidate is served from — the real link a discovery source
|
|
18
|
+
* (RSS `<link>`, sitemap `<loc>`, catalog/directory `url`) already knows. When
|
|
19
|
+
* present, quote/pay use it VERBATIM. Absent ⇒ the pipeline falls back to
|
|
20
|
+
* `articleUrl(base, slug)` (the single-gate `/essays/<slug>` convention). Carrying
|
|
21
|
+
* the real URL is what lets one buyer pay any publisher's URL shape — `/articles/`,
|
|
22
|
+
* a custom domain, a query string — instead of reconstructing a fixed template.
|
|
23
|
+
*/
|
|
24
|
+
url?: string;
|
|
25
|
+
/** Indicative read price (USDC) a fleet catalog may carry. Advisory — the 402 is the truth. */
|
|
26
|
+
priceUsdc?: number;
|
|
27
|
+
/** Indicative citation price (USDC). Advisory — the 402 is the truth. */
|
|
28
|
+
citationPriceUsdc?: number;
|
|
29
|
+
}
|
|
30
|
+
/** A candidate after the tollgate has quoted a price for it. The author split is
|
|
31
|
+
* the seller's concern (recorded on the event); the buyer only needs the price. */
|
|
32
|
+
export interface PricedCandidate extends Candidate {
|
|
33
|
+
price: Usdc;
|
|
34
|
+
}
|
|
35
|
+
/** A candidate after appraisal — how useful it looks for the topic. */
|
|
36
|
+
export interface AppraisedCandidate extends PricedCandidate {
|
|
37
|
+
/** 0..1 estimate of relevance/value to the research topic. */
|
|
38
|
+
relevance: number;
|
|
39
|
+
/** Human-readable justification (shown in the decision log + demo). */
|
|
40
|
+
rationale: string;
|
|
41
|
+
}
|
|
42
|
+
export type Action = "pay" | "skip" | "cache" | "approve";
|
|
43
|
+
/** The agent's verdict on one candidate, with a visible reason. */
|
|
44
|
+
export interface Decision {
|
|
45
|
+
slug: string;
|
|
46
|
+
title: string;
|
|
47
|
+
/** Canonical URL carried from the candidate (see `Candidate.url`) so the pay
|
|
48
|
+
* step targets the real link, not a reconstructed `/essays/<slug>` path. */
|
|
49
|
+
url?: string;
|
|
50
|
+
action: Action;
|
|
51
|
+
reason: string;
|
|
52
|
+
relevance: number;
|
|
53
|
+
price: number;
|
|
54
|
+
/** value density = relevance / price, the ranking key. */
|
|
55
|
+
density: number;
|
|
56
|
+
}
|
|
57
|
+
/** A source the agent actually obtained (paid or from cache) and can cite. */
|
|
58
|
+
export interface Source {
|
|
59
|
+
slug: string;
|
|
60
|
+
title: string;
|
|
61
|
+
content: string;
|
|
62
|
+
paidUsdc: number;
|
|
63
|
+
settlementRef?: string;
|
|
64
|
+
/** Citation License `jti` proving this read was paid for (verifiable at the gate). */
|
|
65
|
+
licenseId?: string;
|
|
66
|
+
}
|
|
67
|
+
export interface RunResult {
|
|
68
|
+
topic: string;
|
|
69
|
+
budget: number;
|
|
70
|
+
spent: number;
|
|
71
|
+
decisions: Decision[];
|
|
72
|
+
sources: Source[];
|
|
73
|
+
answer: string;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE3C,4EAA4E;AAC5E,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+FAA+F;IAC/F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;mFACmF;AACnF,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,KAAK,EAAE,IAAI,CAAC;CACb;AAED,uEAAuE;AACvE,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAE1D,mEAAmE;AACnE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd;iFAC6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,8EAA8E;AAC9E,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/wallet.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface AgentWallet {
|
|
2
|
+
address: string;
|
|
3
|
+
mock: boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Sign an EIP-191 personal_sign message (a holder-of-key proof). Present
|
|
6
|
+
* whenever a private key is available (always, on the dev path). Absent only
|
|
7
|
+
* when BUYER_ADDRESS is set without a key — then PoP re-reads can't be proven.
|
|
8
|
+
*/
|
|
9
|
+
signMessage?: (message: string) => Promise<string>;
|
|
10
|
+
}
|
|
11
|
+
export declare function getWallet(): AgentWallet;
|
|
12
|
+
//# sourceMappingURL=wallet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACpD;AAiBD,wBAAgB,SAAS,IAAI,WAAW,CAqBvC"}
|
package/dist/wallet.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The agent's wallet. With BUYER_PRIVATE_KEY set, derives the real Arc address
|
|
3
|
+
* via viem and can sign holder-of-key proofs. Without it, falls back to a
|
|
4
|
+
* deterministic DEV key (derived from a fixed non-secret seed, so it's stable
|
|
5
|
+
* across processes) so the full loop — including the proof-of-possession re-read
|
|
6
|
+
* across the two demo runs — works offline against the mock tollgate.
|
|
7
|
+
* BUYER_ADDRESS still overrides the address for legacy/no-sign demos, but then
|
|
8
|
+
* proofs won't match the dev key (re-read safely falls back to paying).
|
|
9
|
+
*/
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
11
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
12
|
+
import { getConfig } from "@naulon/shared";
|
|
13
|
+
/**
|
|
14
|
+
* A deterministic, non-secret DEV key derived from a fixed seed — never used with
|
|
15
|
+
* real funds. It gives the offline mock agent a consistent address+key (stable
|
|
16
|
+
* across the two demo runs) so it can sign PoP proofs without any real wallet.
|
|
17
|
+
* Derived at runtime so no key material is committed to the repo.
|
|
18
|
+
*/
|
|
19
|
+
function devDemoKey() {
|
|
20
|
+
const bytes = createHash("sha256").update("naulon:dev-wallet:v1").digest();
|
|
21
|
+
return `0x${bytes.toString("hex")}`;
|
|
22
|
+
}
|
|
23
|
+
function normalizeKey(raw) {
|
|
24
|
+
return (raw.startsWith("0x") ? raw : `0x${raw}`);
|
|
25
|
+
}
|
|
26
|
+
export function getWallet() {
|
|
27
|
+
const cfg = getConfig();
|
|
28
|
+
if (cfg.BUYER_PRIVATE_KEY) {
|
|
29
|
+
const account = privateKeyToAccount(normalizeKey(cfg.BUYER_PRIVATE_KEY));
|
|
30
|
+
return {
|
|
31
|
+
address: account.address,
|
|
32
|
+
mock: false,
|
|
33
|
+
signMessage: (message) => account.signMessage({ message }),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// No real key: use the derived dev key so the agent has a consistent signable
|
|
37
|
+
// identity. A caller-supplied BUYER_ADDRESS still wins for the address (legacy
|
|
38
|
+
// demos), but the dev key signs — only matching when BUYER_ADDRESS is unset.
|
|
39
|
+
const account = privateKeyToAccount(devDemoKey());
|
|
40
|
+
return {
|
|
41
|
+
address: cfg.BUYER_ADDRESS ?? account.address,
|
|
42
|
+
mock: true,
|
|
43
|
+
signMessage: (message) => account.signMessage({ message }),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=wallet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet.js","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAa3C;;;;;GAKG;AACH,SAAS,UAAU;IACjB,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3E,OAAO,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AACtC,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAkB,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IAExB,IAAI,GAAG,CAAC,iBAAiB,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,mBAAmB,CAAC,YAAY,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACzE,OAAO;YACL,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,IAAI,EAAE,KAAK;YACX,WAAW,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;SAC3D,CAAC;IACJ,CAAC;IAED,8EAA8E;IAC9E,+EAA+E;IAC/E,6EAA6E;IAC7E,MAAM,OAAO,GAAG,mBAAmB,CAAC,UAAU,EAAE,CAAC,CAAC;IAClD,OAAO;QACL,OAAO,EAAE,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,OAAO;QAC7C,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;KAC3D,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@naulon/wayfarer",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "The naulon paying agent: discover → quote → appraise → decide → pay → ground. Budgeted x402 buying over Circle Gateway on Arc, with reusable Citation Licenses (pay once, re-read free).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/naulonapp/naulon.git",
|
|
9
|
+
"directory": "packages/wayfarer"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "./dist/lib.js",
|
|
13
|
+
"types": "./dist/lib.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/lib.d.ts",
|
|
17
|
+
"import": "./dist/lib.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"dev": "tsx watch src/index.ts",
|
|
25
|
+
"start": "tsx src/index.ts",
|
|
26
|
+
"build": "tsc -p tsconfig.json",
|
|
27
|
+
"prepublishOnly": "npm run build",
|
|
28
|
+
"test": "node --import tsx --test \"src/**/*.test.ts\""
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@naulon/shared": "^0.1.2",
|
|
32
|
+
"@circle-fin/x402-batching": "^3.2.0",
|
|
33
|
+
"@langchain/core": "^1.1.48",
|
|
34
|
+
"@langchain/openai": "^1.4.7",
|
|
35
|
+
"@x402/core": "^2.6.0",
|
|
36
|
+
"@x402/evm": "^2.6.0",
|
|
37
|
+
"viem": "^2.52.2"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=22"
|
|
41
|
+
}
|
|
42
|
+
}
|