@nxisai/agent-harness 0.7.0 → 0.8.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 (42) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +17 -5
  3. package/dist/harness/harness.d.ts +16 -0
  4. package/dist/harness/harness.d.ts.map +1 -1
  5. package/dist/harness/harness.js +44 -2
  6. package/dist/harness/harness.js.map +1 -1
  7. package/dist/harness/recommend.d.ts +46 -0
  8. package/dist/harness/recommend.d.ts.map +1 -0
  9. package/dist/harness/recommend.js +144 -0
  10. package/dist/harness/recommend.js.map +1 -0
  11. package/dist/harness/records.d.ts +70 -0
  12. package/dist/harness/records.d.ts.map +1 -0
  13. package/dist/harness/records.js +209 -0
  14. package/dist/harness/records.js.map +1 -0
  15. package/dist/harness/renderer.d.ts +11 -1
  16. package/dist/harness/renderer.d.ts.map +1 -1
  17. package/dist/harness/tools/action-tools.d.ts +10 -0
  18. package/dist/harness/tools/action-tools.d.ts.map +1 -1
  19. package/dist/harness/tools/action-tools.js +18 -0
  20. package/dist/harness/tools/action-tools.js.map +1 -1
  21. package/dist/harness/tools/site-pages.js +1 -1
  22. package/dist/index.d.ts +3 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +2 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/ui/agent-fullscreen.d.ts.map +1 -1
  27. package/dist/ui/agent-fullscreen.js +85 -73
  28. package/dist/ui/agent-fullscreen.js.map +1 -1
  29. package/dist/ui/result-pick.d.ts +52 -0
  30. package/dist/ui/result-pick.d.ts.map +1 -0
  31. package/dist/ui/result-pick.js +196 -0
  32. package/dist/ui/result-pick.js.map +1 -0
  33. package/package.json +1 -1
  34. package/src/harness/harness.ts +51 -2
  35. package/src/harness/recommend.ts +194 -0
  36. package/src/harness/records.ts +237 -0
  37. package/src/harness/renderer.ts +12 -1
  38. package/src/harness/tools/action-tools.ts +18 -0
  39. package/src/harness/tools/site-pages.ts +1 -1
  40. package/src/index.ts +3 -0
  41. package/src/ui/agent-fullscreen.ts +92 -63
  42. package/src/ui/result-pick.ts +233 -0
@@ -0,0 +1,144 @@
1
+ import { factLines, recordFacts } from './records.js';
2
+ /** The tool the model answers through. Never registered anywhere: offered for this one completion. */
3
+ export const RECOMMEND_TOOL = 'recommend';
4
+ const TOOL = {
5
+ name: RECOMMEND_TOOL,
6
+ description: 'Recommend the one result that best fits what the visitor asked, with reasons taken from that result.',
7
+ inputSchema: {
8
+ type: 'object',
9
+ properties: {
10
+ pick: { type: 'integer', description: 'The number of the result you recommend.' },
11
+ lead: { type: 'string', description: 'One short sentence for the visitor, naming it and saying why.' },
12
+ reasons: {
13
+ type: 'array',
14
+ items: { type: 'string' },
15
+ description: 'Two or three short reasons, each restating a fact listed for that result.',
16
+ },
17
+ },
18
+ required: ['pick', 'lead', 'reasons'],
19
+ },
20
+ };
21
+ const WEEKDAY = new Intl.DateTimeFormat('en-US', { weekday: 'long', hour: 'numeric', minute: '2-digit' });
22
+ /**
23
+ * Ask the model which result fits, and keep only what the record supports.
24
+ *
25
+ * @returns The pick, or null when the model gave none, picked a result that
26
+ * does not exist, or gave no reason the record backs.
27
+ */
28
+ export async function recommend(req) {
29
+ const now = req.now ?? new Date();
30
+ const records = req.records.slice(0, req.limit ?? 8);
31
+ if (records.length < 2)
32
+ return null;
33
+ const facts = records.map((r) => recordFacts(r, now));
34
+ const listing = facts.map((f, i) => `${i + 1}. ${f.name}\n${factLines(f).map((l) => ` - ${l}`).join('\n')}`).join('\n');
35
+ const messages = [
36
+ {
37
+ role: 'system',
38
+ content: [
39
+ 'You help a website visitor choose between search results.',
40
+ `Call ${RECOMMEND_TOOL} once: pick is the number of the result that best fits what they asked; lead is one short sentence that names it and says why; reasons are two or three short reasons.`,
41
+ 'Every reason must restate a fact listed for the result you pick. Do not add facts, prices, times or numbers that are not listed.',
42
+ 'If they need help now, prefer one that is open now.',
43
+ ].join(' '),
44
+ },
45
+ {
46
+ role: 'user',
47
+ content: `The visitor asked: "${req.goal}"\nIt is now ${WEEKDAY.format(now)}.\n\nResults:\n${listing}`,
48
+ },
49
+ ];
50
+ let completion;
51
+ try {
52
+ completion = await req.provider.complete({ messages, tools: [TOOL], signal: req.signal, maxTokens: 300 });
53
+ }
54
+ catch (err) {
55
+ if (req.signal?.aborted)
56
+ throw err;
57
+ console.warn('[nxis-agent] recommendation failed:', err);
58
+ return null;
59
+ }
60
+ if (req.transcribe)
61
+ completion = req.transcribe(completion);
62
+ const args = completion.call?.name === RECOMMEND_TOOL ? completion.call.args : readJson(completion.text);
63
+ if (!args)
64
+ return null;
65
+ const index = Number(args.pick) - 1;
66
+ const picked = facts[index];
67
+ if (!Number.isInteger(index) || !picked)
68
+ return null;
69
+ const others = facts.filter((_, i) => i !== index).map((f) => f.name.toLowerCase());
70
+ const reasons = (Array.isArray(args.reasons) ? args.reasons : [])
71
+ .map((r) => String(r ?? '').trim())
72
+ .filter((r) => r && r.length <= 200 && grounded(r, picked, others))
73
+ .slice(0, 3);
74
+ if (!reasons.length)
75
+ return null;
76
+ const said = String(args.lead ?? '').trim();
77
+ const lead = said && said.length <= 200 && mentions(said, picked.name) && grounded(said, picked, others) ? said : `I'd go with ${picked.name}.`;
78
+ return { index, key: picked.key, lead, reasons };
79
+ }
80
+ /** A call written as plain JSON: `{"pick": 1, …}`. */
81
+ function readJson(text) {
82
+ const m = text.match(/\{[\s\S]*\}/);
83
+ if (!m)
84
+ return null;
85
+ try {
86
+ const v = JSON.parse(m[0]);
87
+ return v && typeof v === 'object' ? v : null;
88
+ }
89
+ catch {
90
+ return null;
91
+ }
92
+ }
93
+ const STOP = new Set('about after also and are around been best both but can come does done each even from good great have here into just like more most much need only open other over same some than that their them then there these they this those very well were what when where which while will with would your'.split(' '));
94
+ /** The words worth matching: four letters or more, not filler, roughly stemmed. */
95
+ function words(text) {
96
+ return (text.toLowerCase().match(/[a-z][a-z'-]{3,}/g) ?? []).filter((w) => !STOP.has(w)).map(stem);
97
+ }
98
+ const stem = (w) => w.replace(/'s$/, '').replace(/(ing|ers|ed|es|s)$/, '').slice(0, 7);
99
+ /** The record's facts as one searchable text. */
100
+ function factText(f) {
101
+ return [f.name, ...factLines(f)].join(' ').toLowerCase();
102
+ }
103
+ /**
104
+ * Whether a sentence says only what the record says.
105
+ *
106
+ * Every number in it must appear in the record ("4.7", "412", "40", "24/7");
107
+ * it must share at least one meaningful word with the record; and it must
108
+ * not be about another result.
109
+ */
110
+ export function grounded(sentence, f, others = []) {
111
+ const text = factText(f);
112
+ const lower = sentence.toLowerCase();
113
+ if (others.some((name) => name && lower.includes(name)))
114
+ return false;
115
+ const numbers = lower.match(/\d+(?:[.:]\d+)?/g) ?? [];
116
+ const numberText = text.replace(/,/g, '');
117
+ if (!numbers.every((n) => numberText.includes(n)))
118
+ return false;
119
+ // Hours are claims about now, checked against the hours rather than the words:
120
+ // every record says "open" somewhere, closed ones too.
121
+ const always = ALWAYS.test(lower);
122
+ const now = OPEN_NOW.test(lower);
123
+ if (always && !(f.status?.always || /24\/7|24 hours/.test(text)))
124
+ return false;
125
+ if (now && !f.status?.open)
126
+ return false;
127
+ if (always || now)
128
+ return true;
129
+ const known = new Set(words(text));
130
+ return words(sentence).some((w) => known.has(w));
131
+ }
132
+ /** A claim that it never closes. */
133
+ const ALWAYS = /24\/7|24 hours|around the clock|day (?:or|and) night|any ?time/;
134
+ /** A claim that it is open at this moment. */
135
+ const OPEN_NOW = /\bopen (?:right )?now\b|\bright now\b|\bopen today\b|\bstill open\b/;
136
+ /** Whether a sentence names the record: its full name, or its first distinctive word. */
137
+ function mentions(sentence, name) {
138
+ const lower = sentence.toLowerCase();
139
+ if (lower.includes(name.toLowerCase()))
140
+ return true;
141
+ const first = words(name).find((w) => w.length >= 4);
142
+ return !!first && words(sentence).includes(first);
143
+ }
144
+ //# sourceMappingURL=recommend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recommend.js","sourceRoot":"","sources":["../../src/harness/recommend.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAoB,MAAM,cAAc,CAAC;AAExE,sGAAsG;AACtG,MAAM,CAAC,MAAM,cAAc,GAAG,WAAW,CAAC;AA8B1C,MAAM,IAAI,GAAyB;IACjC,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,sGAAsG;IACnH,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,yCAAyC,EAAE;YACjF,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+DAA+D,EAAE;YACtG,OAAO,EAAE;gBACP,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,WAAW,EAAE,2EAA2E;aACzF;SACF;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;KACtC;CACsB,CAAC;AAE1B,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;AAE1G;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAqB;IACnD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;IACrD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE1H,MAAM,QAAQ,GAAkB;QAC9B;YACE,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE;gBACP,2DAA2D;gBAC3D,QAAQ,cAAc,wKAAwK;gBAC9L,kIAAkI;gBAClI,qDAAqD;aACtD,CAAC,IAAI,CAAC,GAAG,CAAC;SACZ;QACD;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,uBAAuB,GAAG,CAAC,IAAI,gBAAgB,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,kBAAkB,OAAO,EAAE;SACvG;KACF,CAAC;IAEF,IAAI,UAAsB,CAAC;IAC3B,IAAI,CAAC;QACH,UAAU,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5G,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO;YAAE,MAAM,GAAG,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,qCAAqC,EAAE,GAAG,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,GAAG,CAAC,UAAU;QAAE,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACzG,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACrD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACpF,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;SAClC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;SAClE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACf,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEjC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,MAAM,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,MAAM,CAAC,IAAI,GAAG,CAAC;IAChJ,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACnD,CAAC;AAED,sDAAsD;AACtD,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACpC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3B,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,CAA6B,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,IAAI,GAAG,IAAI,GAAG,CAClB,mSAAmS,CAAC,KAAK,CACvS,GAAG,CACJ,CACF,CAAC;AAEF,mFAAmF;AACnF,SAAS,KAAK,CAAC,IAAY;IACzB,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrG,CAAC;AAED,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAEvG,iDAAiD;AACjD,SAAS,QAAQ,CAAC,CAAc;IAC9B,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;AAC3D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,QAAgB,EAAE,CAAc,EAAE,SAAmB,EAAE;IAC9E,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC;IACtD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAChE,+EAA+E;IAC/E,uDAAuD;IACvD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/E,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,MAAM,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACnC,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,oCAAoC;AACpC,MAAM,MAAM,GAAG,gEAAgE,CAAC;AAChF,8CAA8C;AAC9C,MAAM,QAAQ,GAAG,qEAAqE,CAAC;AAEvF,yFAAyF;AACzF,SAAS,QAAQ,CAAC,QAAgB,EAAE,IAAY;IAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * The records a read tool returned, and what each one says as plain facts.
3
+ *
4
+ * A typed-retrieval result reaches the harness in many wrappings: structured
5
+ * content, JSON text, or the whole response serialized again by an extension
6
+ * in the loop. {@link extractRecords} digs the record list out of any of them.
7
+ * {@link recordFacts} then reads one schema.org record into the facts a
8
+ * person compares businesses by: whether it is open now, its rating, what it
9
+ * does, what reviewers said. Those facts are what a recommendation may cite,
10
+ * and nothing else.
11
+ *
12
+ * @module
13
+ */
14
+ import type { ModelContextToolResponse } from '../types.js';
15
+ type Obj = Record<string, unknown>;
16
+ /**
17
+ * The records in a read tool's response, wherever they are.
18
+ *
19
+ * @param res - The response, or its text.
20
+ * @returns The records, as the server sent them; empty when there are none.
21
+ */
22
+ export declare function extractRecords(res: ModelContextToolResponse | string | null | undefined): Obj[];
23
+ /** Whether a business is open at a time, and how a visitor should read it. */
24
+ export interface OpenStatus {
25
+ open: boolean;
26
+ /** "Open now · 24/7", "Open now · until 5pm", "Opens 7am", "Opens Mon 7am". */
27
+ label: string;
28
+ /** Open every hour of every day. */
29
+ always: boolean;
30
+ }
31
+ /**
32
+ * Whether a record's business is open at `now`, read from its opening hours.
33
+ *
34
+ * @returns Null when the record states no hours this can read.
35
+ */
36
+ export declare function openStatus(entity: Obj, now?: Date): OpenStatus | null;
37
+ /** One record, as the facts a visitor compares by. */
38
+ export interface RecordFacts {
39
+ /** Its `@id`, else its name: what a pick refers to. */
40
+ key: string;
41
+ name: string;
42
+ type?: string;
43
+ status?: OpenStatus;
44
+ rating?: number;
45
+ reviewCount?: number;
46
+ phone?: string;
47
+ /** Services it offers, by name, with their one-line descriptions. */
48
+ services: {
49
+ name: string;
50
+ description?: string;
51
+ }[];
52
+ /** What it says it specializes in. */
53
+ knows: string[];
54
+ description?: string;
55
+ /** What reviewers wrote, with who wrote it. */
56
+ reviews: {
57
+ text: string;
58
+ author?: string;
59
+ }[];
60
+ /** The year it was founded. */
61
+ since?: number;
62
+ /** ZIP codes or places it serves. */
63
+ area: string[];
64
+ }
65
+ /** A schema.org record as plain facts. */
66
+ export declare function recordFacts(entity: Obj, now?: Date): RecordFacts;
67
+ /** The facts as lines a model reads, and a recommendation is checked against. */
68
+ export declare function factLines(f: RecordFacts): string[];
69
+ export {};
70
+ //# sourceMappingURL=records.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../../src/harness/records.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAE5D,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAInC;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,wBAAwB,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,GAAG,EAAE,CA8B/F;AAwED,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,+EAA+E;IAC/E,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,GAAE,IAAiB,GAAG,UAAU,GAAG,IAAI,CAkBjF;AAID,sDAAsD;AACtD,MAAM,WAAW,WAAW;IAC1B,uDAAuD;IACvD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACnD,sCAAsC;IACtC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAKD,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,GAAE,IAAiB,GAAG,WAAW,CA8B5E;AAED,iFAAiF;AACjF,wBAAgB,SAAS,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,EAAE,CAalD"}
@@ -0,0 +1,209 @@
1
+ const isObj = (v) => !!v && typeof v === 'object' && !Array.isArray(v);
2
+ /**
3
+ * The records in a read tool's response, wherever they are.
4
+ *
5
+ * @param res - The response, or its text.
6
+ * @returns The records, as the server sent them; empty when there are none.
7
+ */
8
+ export function extractRecords(res) {
9
+ const sources = [];
10
+ // Every candidate payload, unwrapping response envelopes: structured
11
+ // content and each text part, parsed as JSON, possibly encoded twice.
12
+ const visit = (raw, depth = 0) => {
13
+ if (raw == null || depth > 5)
14
+ return;
15
+ if (typeof raw === 'string') {
16
+ const t = raw.trim();
17
+ if (!t)
18
+ return;
19
+ try {
20
+ visit(JSON.parse(t), depth + 1);
21
+ }
22
+ catch {
23
+ // Plain text: nothing to extract.
24
+ }
25
+ return;
26
+ }
27
+ if (typeof raw !== 'object')
28
+ return;
29
+ sources.push(raw);
30
+ const v = raw;
31
+ if (v.structuredContent != null)
32
+ visit(v.structuredContent, depth + 1);
33
+ if (Array.isArray(v.content)) {
34
+ for (const c of v.content)
35
+ if (isObj(c))
36
+ visit(c.text, depth + 1);
37
+ }
38
+ };
39
+ visit(res);
40
+ for (const data of sources) {
41
+ const items = itemsFrom(data);
42
+ if (items.length)
43
+ return items;
44
+ }
45
+ return [];
46
+ }
47
+ /** The record array within one parsed payload. */
48
+ function itemsFrom(data) {
49
+ const objs = (arr) => arr.filter(isObj);
50
+ if (Array.isArray(data))
51
+ return objs(data);
52
+ if (!isObj(data))
53
+ return [];
54
+ for (const key of ['results', 'types', 'items', 'entities', 'data']) {
55
+ if (Array.isArray(data[key]))
56
+ return objs(data[key]);
57
+ }
58
+ if (isObj(data.result))
59
+ return [data.result];
60
+ if (data['@id'] != null || data['@type'] != null || data.name != null)
61
+ return [data];
62
+ return [];
63
+ }
64
+ // ── Opening hours ───────────────────────────────────────────────────────────
65
+ const DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
66
+ const SHORT = { su: 0, mo: 1, tu: 2, we: 3, th: 4, fr: 5, sa: 6 };
67
+ /** Minutes after midnight: "07:30" → 450. */
68
+ function minutes(hhmm) {
69
+ const m = String(hhmm ?? '').match(/^(\d{1,2}):(\d{2})/);
70
+ return m ? Number(m[1]) * 60 + Number(m[2]) : null;
71
+ }
72
+ /** "7am", "5:30pm", "noon". */
73
+ function clock(mins) {
74
+ const h = Math.floor(mins / 60) % 24;
75
+ const m = mins % 60;
76
+ if (h === 12 && m === 0)
77
+ return 'noon';
78
+ const suffix = h < 12 ? 'am' : 'pm';
79
+ const h12 = h % 12 || 12;
80
+ return m ? `${h12}:${String(m).padStart(2, '0')}${suffix}` : `${h12}${suffix}`;
81
+ }
82
+ /** Each day's opening spans, [opens, closes] in minutes; index 0 is Sunday. */
83
+ function weekOf(entity) {
84
+ const week = DAYS.map(() => []);
85
+ let any = false;
86
+ const spec = entity.openingHoursSpecification;
87
+ for (const s of Array.isArray(spec) ? spec : spec ? [spec] : []) {
88
+ if (!isObj(s))
89
+ continue;
90
+ const opens = minutes(s.opens);
91
+ const closes = minutes(s.closes);
92
+ if (opens === null || closes === null)
93
+ continue;
94
+ const days = Array.isArray(s.dayOfWeek) ? s.dayOfWeek : [s.dayOfWeek];
95
+ for (const d of days) {
96
+ const i = DAYS.findIndex((name) => String(d ?? '').replace(/^.*[/#]/, '').toLowerCase() === name.toLowerCase());
97
+ if (i >= 0) {
98
+ week[i].push([opens, closes]);
99
+ any = true;
100
+ }
101
+ }
102
+ }
103
+ // The compact form: "Mo-Fr 07:00-17:00", "Sa 08:00-13:00", "Mo-Su 00:00-23:59".
104
+ const compact = entity.openingHours;
105
+ for (const line of Array.isArray(compact) ? compact : compact ? String(compact).split(/[;,](?=\s*[A-Z][a-z])/) : []) {
106
+ const m = String(line).trim().match(/^([A-Za-z]{2})(?:-([A-Za-z]{2}))?\s+(\d{1,2}:\d{2})-(\d{1,2}:\d{2})$/);
107
+ if (!m)
108
+ continue;
109
+ const from = SHORT[m[1].toLowerCase()];
110
+ const to = m[2] ? SHORT[m[2].toLowerCase()] : from;
111
+ if (from === undefined || to === undefined)
112
+ continue;
113
+ for (let d = from;; d = (d + 1) % 7) {
114
+ week[d].push([minutes(m[3]), minutes(m[4])]);
115
+ any = true;
116
+ if (d === to)
117
+ break;
118
+ }
119
+ }
120
+ return any ? week : null;
121
+ }
122
+ /**
123
+ * Whether a record's business is open at `now`, read from its opening hours.
124
+ *
125
+ * @returns Null when the record states no hours this can read.
126
+ */
127
+ export function openStatus(entity, now = new Date()) {
128
+ const week = weekOf(entity);
129
+ if (!week)
130
+ return null;
131
+ const always = week.every((spans) => spans.some(([o, c]) => o === 0 && c >= 23 * 60 + 59));
132
+ if (always)
133
+ return { open: true, label: 'Open now · 24/7', always: true };
134
+ const day = now.getDay();
135
+ const at = now.getHours() * 60 + now.getMinutes();
136
+ const current = week[day].find(([o, c]) => at >= o && at < c);
137
+ if (current)
138
+ return { open: true, label: `Open now · until ${clock(current[1])}`, always: false };
139
+ // The next opening, today later or on a following day.
140
+ for (let ahead = 0; ahead < 7; ahead++) {
141
+ const d = (day + ahead) % 7;
142
+ const next = week[d].filter(([o]) => ahead > 0 || o > at).sort((a, b) => a[0] - b[0])[0];
143
+ if (!next)
144
+ continue;
145
+ // Today or tomorrow reads as a time alone; further off, with the day.
146
+ return { open: false, label: ahead <= 1 ? `Opens ${clock(next[0])}` : `Opens ${DAYS[d].slice(0, 3)} ${clock(next[0])}`, always: false };
147
+ }
148
+ return { open: false, label: 'Closed', always: false };
149
+ }
150
+ const str = (v) => (v == null ? '' : String(Array.isArray(v) ? v[0] : v)).trim();
151
+ const list = (v) => (Array.isArray(v) ? v : v == null ? [] : [v]);
152
+ /** A schema.org record as plain facts. */
153
+ export function recordFacts(entity, now = new Date()) {
154
+ const name = str(entity.name ?? entity.title ?? entity.headline) || 'This result';
155
+ const rating = isObj(entity.aggregateRating) ? Number(entity.aggregateRating.ratingValue) : NaN;
156
+ const count = isObj(entity.aggregateRating) ? Number(entity.aggregateRating.reviewCount ?? entity.aggregateRating.ratingCount) : NaN;
157
+ const services = list(entity.makesOffer)
158
+ .map((o) => (isObj(o) && isObj(o.itemOffered) ? o.itemOffered : isObj(o) ? o : null))
159
+ .filter(isObj)
160
+ .map((s) => ({ name: str(s.name), description: str(s.description) || undefined }))
161
+ .filter((s) => s.name);
162
+ const reviews = list(entity.review)
163
+ .filter(isObj)
164
+ .map((r) => ({ text: str(r.reviewBody ?? r.description), author: isObj(r.author) ? str(r.author.name) || undefined : str(r.author) || undefined }))
165
+ .filter((r) => r.text);
166
+ const founded = str(entity.foundingDate).match(/^(\d{4})/);
167
+ const status = openStatus(entity, now) ?? undefined;
168
+ return {
169
+ key: str(entity['@id']) || name,
170
+ name,
171
+ type: str(entity['@type']).replace(/^.*[/#]/, '') || undefined,
172
+ ...(status ? { status } : {}),
173
+ ...(Number.isFinite(rating) ? { rating } : {}),
174
+ ...(Number.isFinite(count) ? { reviewCount: count } : {}),
175
+ ...(str(entity.telephone) ? { phone: str(entity.telephone) } : {}),
176
+ services,
177
+ knows: list(entity.knowsAbout).map(str).filter(Boolean),
178
+ ...(str(entity.description) ? { description: str(entity.description) } : {}),
179
+ reviews,
180
+ ...(founded ? { since: Number(founded[1]) } : {}),
181
+ area: list(entity.areaServed).map((a) => (isObj(a) ? str(a.name ?? a.postalCode) : str(a))).filter(Boolean),
182
+ };
183
+ }
184
+ /** The facts as lines a model reads, and a recommendation is checked against. */
185
+ export function factLines(f) {
186
+ const lines = [];
187
+ if (f.type)
188
+ lines.push(f.type);
189
+ if (f.status)
190
+ lines.push(f.status.label);
191
+ if (f.rating !== undefined)
192
+ lines.push(`Rated ${f.rating}${f.reviewCount !== undefined ? ` from ${f.reviewCount} reviews` : ''}`);
193
+ if (f.since)
194
+ lines.push(`In business since ${f.since}`);
195
+ if (f.services.length)
196
+ lines.push(`Services: ${f.services.map((s) => (s.description ? `${s.name} (${s.description})` : s.name)).join('; ')}`);
197
+ if (f.knows.length)
198
+ lines.push(`Specializes in: ${f.knows.join(', ')}`);
199
+ if (f.description)
200
+ lines.push(f.description);
201
+ for (const r of f.reviews.slice(0, 2))
202
+ lines.push(`Review: "${r.text}"${r.author ? ` (${r.author})` : ''}`);
203
+ if (f.area.length)
204
+ lines.push(`Serves: ${f.area.join(', ')}`);
205
+ if (f.phone)
206
+ lines.push(`Phone: ${f.phone}`);
207
+ return lines;
208
+ }
209
+ //# sourceMappingURL=records.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/harness/records.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@ import type { ModelContextToolInfo, ModelContextToolResponse } from '../types.js
12
12
  import type { ClarificationPlan } from './plan.js';
13
13
  import type { Resolution, Slot } from './slots.js';
14
14
  import type { AgentStep } from './steps.js';
15
+ import type { ResultPick } from './recommend.js';
15
16
  /** One tool call and its response, for renderers that show their work. */
16
17
  export interface TraceEntry {
17
18
  /** The tool that was called. */
@@ -75,6 +76,15 @@ export interface StreamingBubble {
75
76
  */
76
77
  finalize(text: string): void;
77
78
  }
79
+ /** What the harness adds to a search's results. */
80
+ export interface ResultsExtra {
81
+ /**
82
+ * The record the model recommends, with reasons the record backs. Absent
83
+ * when there was one result, the model gave no backed reason, or
84
+ * recommendations are off: show the results as a list.
85
+ */
86
+ pick?: ResultPick;
87
+ }
78
88
  /** A write tool with every value resolved, awaiting a human press. */
79
89
  export interface ConfirmRequest {
80
90
  /** The tool about to be called. */
@@ -150,7 +160,7 @@ export interface HarnessRenderer {
150
160
  /** Present a write for confirmation. Nothing is missing. */
151
161
  confirm(req: ConfirmRequest): void;
152
162
  /** A read tool returned records. */
153
- results(tool: ModelContextToolInfo, res: ModelContextToolResponse): void;
163
+ results(tool: ModelContextToolInfo, res: ModelContextToolResponse, extra?: ResultsExtra): void;
154
164
  /** A write tool succeeded. */
155
165
  detail(tool: ModelContextToolInfo, values: Record<string, unknown>, text: string): void;
156
166
  /** A tool failed, or returned something that cannot be rendered. */
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/harness/renderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/harness/renderer.ts"],"names":[],"mappings":"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"}
@@ -139,6 +139,16 @@ export declare function chooserOf(tool: ModelContextToolInfo): string | null;
139
139
  * tool built on this page, or the call does not yet say which form.
140
140
  */
141
141
  export declare function formOptions(tool: ModelContextToolInfo, values: Record<string, unknown>): Record<string, string[]>;
142
+ /**
143
+ * The site forms that can be sent to a business, by its name: the site tools
144
+ * on this page whose choices include it.
145
+ *
146
+ * @returns Each form's tool name and what it is called ("quote form").
147
+ */
148
+ export declare function formsFor(name: string): {
149
+ tool: string;
150
+ noun: string;
151
+ }[];
142
152
  /** An option that only asks to choose: "Select…", "Choose a service…". */
143
153
  export declare const isPlaceholder: (value: string) => boolean;
144
154
  /** Which page tool to look for: the action's id, and the name it would have. */
@@ -1 +1 @@
1
- {"version":3,"file":"action-tools.d.ts","sourceRoot":"","sources":["../../../src/harness/tools/action-tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"action-tools.d.ts","sourceRoot":"","sources":["../../../src/harness/tools/action-tools.ts"],"names":[],"mappings":"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"}
@@ -441,6 +441,24 @@ export function formOptions(tool, values) {
441
441
  }
442
442
  return out;
443
443
  }
444
+ /**
445
+ * The site forms that can be sent to a business, by its name: the site tools
446
+ * on this page whose choices include it.
447
+ *
448
+ * @returns Each form's tool name and what it is called ("quote form").
449
+ */
450
+ export function formsFor(name) {
451
+ const wanted = name.trim().toLowerCase();
452
+ if (!wanted)
453
+ return [];
454
+ const out = [];
455
+ for (const [toolName, t] of built) {
456
+ if (t.choices?.some((c) => c.toLowerCase() === wanted)) {
457
+ out.push({ tool: toolName, noun: withoutSiteSuffix(toolName).replace(/[_-]+/g, ' ').trim().toLowerCase() });
458
+ }
459
+ }
460
+ return out;
461
+ }
444
462
  /** An option that only asks to choose: "Select…", "Choose a service…". */
445
463
  export const isPlaceholder = (value) => /^\s*(select|choose|pick)\b/i.test(value) || /…\s*$|\.\.\.\s*$/.test(value);
446
464
  /** The reference for an action. */