@bolloon/bolloon-agent 0.3.1 → 0.3.4

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.
@@ -0,0 +1,87 @@
1
+ /**
2
+ * judgeness / dual-mode.ts
3
+ *
4
+ * Accept 协商 + JSON-LD 生成.
5
+ * - 默认 `application/ld+json` 给 agent (头等公民)
6
+ * - `text/html` 或 `?view=human` 给人类
7
+ *
8
+ * 复用 bolloon 现有 src/web/util/safe-name.ts (兜底防 undefined/null/NaN 渲染).
9
+ */
10
+ const HEARTH_LD_CONTEXT = 'https://judgeness.bolloon.com/schema/v1';
11
+ /** 最简 UA 检测: 已知 agent 名 / 字符串里含 'bot'/'agent' 视为 agent.
12
+ * 防御期 placeholder — 反攻期可接 allowlist UA detection. */
13
+ function isLikelyAgentUA(ua) {
14
+ if (!ua)
15
+ return false;
16
+ const s = ua.toLowerCase();
17
+ return /bot|agent|crawler|spider/.test(s);
18
+ }
19
+ export function negotiateAudience(input) {
20
+ // ?view=human 显式
21
+ const v = input.query?.['view'];
22
+ if (typeof v === 'string' && v.toLowerCase() === 'human')
23
+ return 'human';
24
+ const accept = (input.accept ?? '').toLowerCase();
25
+ // text/html 优先
26
+ if (accept.includes('text/html') && !accept.includes('application/ld+json'))
27
+ return 'human';
28
+ // UA 启发式
29
+ if (isLikelyAgentUA(input.userAgent) && !accept.includes('text/html'))
30
+ return 'agent';
31
+ // 缺省: agent (头等公民)
32
+ return 'agent';
33
+ }
34
+ export function descriptionToJsonLd(d) {
35
+ return {
36
+ '@context': HEARTH_LD_CONTEXT,
37
+ '@type': 'JudgenessDescription',
38
+ '@id': `urn:judgeness:description:${d.descriptionId}`,
39
+ name: `Description ${d.descriptionId}`,
40
+ description: `Judgment ref: ${d.judgmentRef}`,
41
+ facets: d.facets,
42
+ scope: d.scope,
43
+ visibility: d.visibility,
44
+ openState: d.openState,
45
+ by: d.by,
46
+ createdAt: d.createdAt,
47
+ };
48
+ }
49
+ // ---------------------------------------------------------------------------
50
+ // HTML 渲染 (人类视图, 极简, 防 XSS escape)
51
+ // ---------------------------------------------------------------------------
52
+ function escapeHtml(s) {
53
+ return s
54
+ .replace(/&/g, '&')
55
+ .replace(/</g, '&lt;')
56
+ .replace(/>/g, '&gt;')
57
+ .replace(/"/g, '&quot;')
58
+ .replace(/'/g, '&#39;');
59
+ }
60
+ export function renderHumanHtml(title, body) {
61
+ return `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>${escapeHtml(title)}</title></head><body><h1>${escapeHtml(title)}</h1>${body}</body></html>`;
62
+ }
63
+ export function descriptionToHumanHtml(d) {
64
+ const facetsLines = d.facets
65
+ ? Object.entries(d.facets)
66
+ .filter(([, v]) => v !== undefined)
67
+ .map(([k, v]) => `<li>${escapeHtml(k)}: ${escapeHtml(String(v))}</li>`)
68
+ .join('')
69
+ : '<li>(no facets visible at your access level)</li>';
70
+ const body = `<section><h2>Description ${escapeHtml(d.descriptionId)}</h2><p>Judgment ref: <code>${escapeHtml(d.judgmentRef)}</code></p><ul>${facetsLines}</ul><p>visibility: <strong>${escapeHtml(d.visibility)}</strong> · openState: <strong>${escapeHtml(d.openState)}</strong></p></section>`;
71
+ return renderHumanHtml(`Hearth · ${d.descriptionId}`, body);
72
+ }
73
+ export function dualRender(input, humanHtml, jsonLdProducer) {
74
+ const aud = negotiateAudience(input);
75
+ if (aud === 'human') {
76
+ return { status: 200, contentType: 'text/html; charset=utf-8', body: humanHtml() };
77
+ }
78
+ const obj = jsonLdProducer();
79
+ return {
80
+ status: 200,
81
+ contentType: 'application/ld+json; charset=utf-8',
82
+ body: JSON.stringify(obj),
83
+ };
84
+ }
85
+ export function dualRenderList(input, humanHtmlProducer, jsonLdProducer) {
86
+ return dualRender(input, humanHtmlProducer, () => jsonLdProducer());
87
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bolloon/bolloon-agent",
3
- "version": "0.3.1",
3
+ "version": "0.3.4",
4
4
  "type": "module",
5
5
  "description": "P2P AI Document Agent - 全局安装后执行 `bolloon` 启动产品",
6
6
  "main": "dist/cli-entry.js",
@@ -48,7 +48,7 @@
48
48
  "src/constraint-runtime"
49
49
  ],
50
50
  "dependencies": {
51
- "@bolloon/bolloon-agent": "^0.3.1",
51
+ "@bolloon/bolloon-agent": "^0.3.3",
52
52
  "@bolloon/constraint-runtime": "0.1.0",
53
53
  "@capacitor/core": "^8.4.1",
54
54
  "@capacitor/ios": "^8.4.1",