@spendgraph/tools 0.6.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 (211) hide show
  1. package/README.md +3 -2
  2. package/dist/builtin/calculate/calculate.d.ts +2 -0
  3. package/dist/builtin/calculate/calculate.js +1 -1
  4. package/dist/builtin/calculate/index.d.ts +2 -1
  5. package/dist/builtin/calculate/index.js +1 -1
  6. package/dist/builtin/code-exec/code-exec.d.ts +14 -0
  7. package/dist/builtin/date/date.d.ts +1 -1
  8. package/dist/builtin/date/date.js +1 -1
  9. package/dist/builtin/date/index.d.ts +1 -0
  10. package/dist/builtin/date/index.js +1 -1
  11. package/dist/builtin/date/shift.d.ts +1 -1
  12. package/dist/builtin/date/shift.js +1 -1
  13. package/dist/builtin/date/words.d.ts +13 -0
  14. package/dist/builtin/date/words.js +1 -0
  15. package/dist/builtin/decline/decline.d.ts +49 -0
  16. package/dist/builtin/decline/decline.js +1 -0
  17. package/dist/builtin/decline/index.d.ts +1 -0
  18. package/dist/builtin/decline/index.js +1 -0
  19. package/dist/builtin/escalate/escalate.d.ts +19 -0
  20. package/dist/builtin/escalate/escalate.js +1 -1
  21. package/dist/builtin/escalate/index.d.ts +1 -1
  22. package/dist/builtin/escalate/index.js +1 -1
  23. package/dist/builtin/extract/extract.d.ts +25 -0
  24. package/dist/builtin/extract/extract.js +1 -0
  25. package/dist/builtin/extract/index.d.ts +3 -0
  26. package/dist/builtin/extract/index.js +1 -0
  27. package/dist/builtin/extract/kinds.d.ts +6 -0
  28. package/dist/builtin/extract/kinds.js +1 -0
  29. package/dist/builtin/extract/readers.d.ts +7 -0
  30. package/dist/builtin/extract/readers.js +9 -0
  31. package/dist/builtin/finish/finish.d.ts +4 -0
  32. package/dist/builtin/finish/finish.js +1 -1
  33. package/dist/builtin/http/allow.d.ts +2 -0
  34. package/dist/builtin/http/allow.js +1 -1
  35. package/dist/builtin/http/hops.d.ts +10 -0
  36. package/dist/builtin/http/hops.js +1 -0
  37. package/dist/builtin/http/http.d.ts +9 -1
  38. package/dist/builtin/http/http.js +1 -1
  39. package/dist/builtin/http/index.d.ts +2 -0
  40. package/dist/builtin/http/index.js +1 -1
  41. package/dist/builtin/http/retry-after.d.ts +14 -0
  42. package/dist/builtin/http/retry-after.js +1 -0
  43. package/dist/builtin/index.d.ts +11 -6
  44. package/dist/builtin/index.js +1 -1
  45. package/dist/builtin/json/index.d.ts +1 -0
  46. package/dist/builtin/json/index.js +1 -1
  47. package/dist/builtin/json/json.js +1 -1
  48. package/dist/builtin/json/parse.d.ts +15 -0
  49. package/dist/builtin/json/parse.js +1 -0
  50. package/dist/builtin/notes/index.d.ts +1 -0
  51. package/dist/builtin/notes/index.js +1 -0
  52. package/dist/builtin/notes/notes.d.ts +45 -0
  53. package/dist/builtin/notes/notes.js +2 -0
  54. package/dist/builtin/openalex/api.d.ts +26 -0
  55. package/dist/builtin/openalex/api.js +1 -0
  56. package/dist/builtin/openalex/index.d.ts +3 -0
  57. package/dist/builtin/openalex/index.js +1 -0
  58. package/dist/builtin/openalex/openalex.d.ts +36 -0
  59. package/dist/builtin/openalex/openalex.js +1 -0
  60. package/dist/builtin/paper-search/index.d.ts +1 -0
  61. package/dist/builtin/paper-search/index.js +1 -0
  62. package/dist/builtin/paper-search/paper-search.d.ts +38 -0
  63. package/dist/builtin/paper-search/paper-search.js +3 -0
  64. package/dist/builtin/polite.d.ts +15 -0
  65. package/dist/builtin/polite.js +1 -0
  66. package/dist/builtin/publish/index.d.ts +1 -0
  67. package/dist/builtin/publish/index.js +1 -0
  68. package/dist/builtin/publish/publish.d.ts +46 -0
  69. package/dist/builtin/publish/publish.js +1 -0
  70. package/dist/builtin/web-search/web-search.d.ts +10 -35
  71. package/dist/builtin/web-search/web-search.js +1 -1
  72. package/dist/builtin/wikidata/api.d.ts +40 -0
  73. package/dist/builtin/wikidata/api.js +1 -0
  74. package/dist/builtin/wikidata/index.d.ts +5 -0
  75. package/dist/builtin/wikidata/index.js +1 -0
  76. package/dist/builtin/wikidata/render.d.ts +13 -0
  77. package/dist/builtin/wikidata/render.js +2 -0
  78. package/dist/builtin/wikidata/wikidata.d.ts +23 -0
  79. package/dist/builtin/wikidata/wikidata.js +1 -0
  80. package/dist/bus/bus.d.ts +23 -1
  81. package/dist/bus/bus.js +1 -1
  82. package/dist/bus/group.d.ts +14 -1
  83. package/dist/bus/group.js +1 -1
  84. package/dist/bus/index.d.ts +4 -1
  85. package/dist/bus/index.js +1 -1
  86. package/dist/bus/invoke.d.ts +1 -1
  87. package/dist/bus/invoke.js +3 -1
  88. package/dist/bus/namespace.d.ts +21 -0
  89. package/dist/bus/namespace.js +1 -0
  90. package/dist/bus/once.d.ts +32 -0
  91. package/dist/bus/once.js +1 -0
  92. package/dist/bus/only.d.ts +29 -0
  93. package/dist/bus/options.d.ts +31 -0
  94. package/dist/bus/output.d.ts +0 -17
  95. package/dist/bus/output.js +2 -2
  96. package/dist/bus/select.d.ts +0 -16
  97. package/dist/bus/select.js +1 -1
  98. package/dist/bus/spent.d.ts +16 -0
  99. package/dist/bus/spent.js +1 -0
  100. package/dist/bus/trace.d.ts +14 -1
  101. package/dist/bus/trace.js +1 -1
  102. package/dist/index.d.ts +6 -4
  103. package/dist/index.js +1 -1
  104. package/dist/internals.d.ts +8 -1
  105. package/dist/internals.js +1 -1
  106. package/dist/memories/client.d.ts +91 -0
  107. package/dist/memories/client.js +0 -0
  108. package/dist/memories/context.d.ts +5 -0
  109. package/dist/memories/context.js +1 -0
  110. package/dist/{builtin → memories}/deep-recall/deep-recall.d.ts +3 -0
  111. package/dist/memories/deep-recall/deep-recall.js +1 -0
  112. package/dist/memories/explore/explore.d.ts +18 -0
  113. package/dist/memories/explore/explore.js +7 -0
  114. package/dist/memories/explore/subgraph.d.ts +12 -0
  115. package/dist/memories/explore/subgraph.js +3 -0
  116. package/dist/memories/index.d.ts +30 -0
  117. package/dist/memories/index.js +1 -0
  118. package/dist/memories/observe/observe.d.ts +7 -0
  119. package/dist/memories/observe/observe.js +1 -0
  120. package/dist/memories/recall/recall.d.ts +42 -0
  121. package/dist/memories/recall/recall.js +1 -0
  122. package/dist/memories/recall/render.d.ts +5 -0
  123. package/dist/memories/recall/render.js +3 -0
  124. package/dist/memories/remember/remember.d.ts +49 -0
  125. package/dist/memories/remember/remember.js +1 -0
  126. package/dist/papers/consensus/consensus.d.ts +12 -0
  127. package/dist/papers/consensus/consensus.js +1 -0
  128. package/dist/papers/consensus/index.d.ts +4 -0
  129. package/dist/papers/consensus/index.js +1 -0
  130. package/dist/papers/consensus/reply.d.ts +24 -0
  131. package/dist/papers/consensus/reply.js +1 -0
  132. package/dist/papers/every.d.ts +6 -0
  133. package/dist/papers/every.js +1 -0
  134. package/dist/papers/index.d.ts +11 -0
  135. package/dist/papers/index.js +1 -0
  136. package/dist/papers/openalex/index.d.ts +2 -0
  137. package/dist/papers/openalex/index.js +1 -0
  138. package/dist/papers/openalex/openalex.d.ts +8 -0
  139. package/dist/papers/openalex/openalex.js +1 -0
  140. package/dist/papers/papers.d.ts +54 -0
  141. package/dist/papers/papers.js +1 -0
  142. package/dist/papers/render.d.ts +2 -0
  143. package/dist/papers/render.js +4 -0
  144. package/dist/papers/semantic-scholar/index.d.ts +4 -0
  145. package/dist/papers/semantic-scholar/index.js +1 -0
  146. package/dist/papers/semantic-scholar/reply.d.ts +29 -0
  147. package/dist/papers/semantic-scholar/reply.js +1 -0
  148. package/dist/papers/semantic-scholar/semantic-scholar.d.ts +8 -0
  149. package/dist/papers/semantic-scholar/semantic-scholar.js +1 -0
  150. package/dist/search/every.d.ts +6 -0
  151. package/dist/search/every.js +4 -0
  152. package/dist/search/index.d.ts +7 -0
  153. package/dist/search/index.js +1 -0
  154. package/dist/search/retry.d.ts +6 -0
  155. package/dist/search/retry.js +1 -0
  156. package/dist/search/search.d.ts +69 -0
  157. package/dist/search/search.js +1 -0
  158. package/dist/search/searxng/index.d.ts +2 -0
  159. package/dist/search/searxng/index.js +1 -0
  160. package/dist/search/searxng/searxng.d.ts +14 -0
  161. package/dist/search/searxng/searxng.js +5 -0
  162. package/dist/search/searxng/text.d.ts +2 -0
  163. package/dist/search/searxng/text.js +3 -0
  164. package/dist/search/sonar/index.d.ts +2 -0
  165. package/dist/search/sonar/index.js +1 -0
  166. package/dist/search/sonar/sonar.d.ts +13 -0
  167. package/dist/search/sonar/sonar.js +1 -0
  168. package/dist/search/tavily/index.d.ts +4 -0
  169. package/dist/search/tavily/index.js +1 -0
  170. package/dist/search/tavily/reply.d.ts +22 -0
  171. package/dist/search/tavily/reply.js +5 -0
  172. package/dist/search/tavily/tavily.d.ts +14 -0
  173. package/dist/search/tavily/tavily.js +1 -0
  174. package/dist/testing/index.d.ts +2 -0
  175. package/dist/testing/index.js +1 -0
  176. package/dist/testing/replay.d.ts +55 -0
  177. package/dist/testing/replay.js +1 -0
  178. package/dist/testing/store.d.ts +35 -0
  179. package/dist/testing/store.js +4 -0
  180. package/dist/tool/tool.d.ts +8 -1
  181. package/dist/tool/tool.js +1 -1
  182. package/dist/types/index.d.ts +1 -1
  183. package/dist/types/result.d.ts +38 -0
  184. package/dist/types/tool.d.ts +74 -0
  185. package/docs/bogus.mdx +85 -0
  186. package/docs/builtins.mdx +217 -0
  187. package/docs/bus.mdx +90 -0
  188. package/docs/declaring.mdx +85 -0
  189. package/docs/effects.mdx +49 -0
  190. package/docs/overview.mdx +76 -0
  191. package/docs/selecting.mdx +79 -0
  192. package/docs/stored.mdx +83 -0
  193. package/docs/turns.mdx +57 -0
  194. package/package.json +28 -9
  195. package/dist/builtin/deep-recall/deep-recall.js +0 -1
  196. package/dist/builtin/write-document/commission.d.ts +0 -56
  197. package/dist/builtin/write-document/commission.js +0 -13
  198. package/dist/builtin/write-document/design.d.ts +0 -49
  199. package/dist/builtin/write-document/design.js +0 -5
  200. package/dist/builtin/write-document/http.d.ts +0 -34
  201. package/dist/builtin/write-document/http.js +0 -1
  202. package/dist/builtin/write-document/index.d.ts +0 -6
  203. package/dist/builtin/write-document/index.js +0 -1
  204. package/dist/builtin/write-document/types.d.ts +0 -33
  205. package/dist/builtin/write-document/write-document.d.ts +0 -69
  206. package/dist/builtin/write-document/write-document.js +0 -1
  207. /package/dist/{builtin/write-document/types.js → bus/only.js} +0 -0
  208. /package/dist/{builtin → memories}/deep-recall/index.d.ts +0 -0
  209. /package/dist/{builtin → memories}/deep-recall/index.js +0 -0
  210. /package/dist/{builtin/web-search → search/sonar}/reply.d.ts +0 -0
  211. /package/dist/{builtin/web-search → search/sonar}/reply.js +0 -0
@@ -0,0 +1,32 @@
1
+ import type { Tool, ToolResult } from "../types/index.js";
2
+ /**
3
+ * The same call again: the tool, and the arguments in a stable order.
4
+ *
5
+ * Sorted, because a model writing `{invoice, amount}` on one turn and
6
+ * `{amount, invoice}` on the next means the same call, and a key that said
7
+ * otherwise would let the second one through — which is the whole failure.
8
+ */
9
+ export declare const callKey: (name: string, args: Record<string, unknown>) => string;
10
+ /**
11
+ * Remembers what each destructive call already did, so a repeat does not do it twice.
12
+ *
13
+ * The agent runtime retries — after a timeout, a crash, a redelivery — and that
14
+ * is correct; the tool layer is where a repeat has to stop being a second
15
+ * refund. `effect` has always said which calls need this and nothing has ever
16
+ * read it: `destructive` is precisely the label for a call that is not safe to
17
+ * repeat, and `idempotent` is the label for one that is.
18
+ *
19
+ * Only completed calls are remembered. A failed one is exactly what a retry is
20
+ * for, and refusing to try again because the first attempt fell over would turn
21
+ * every transient error into a permanent one.
22
+ *
23
+ * A tool that declared no effect is not covered. Unset means nobody has said,
24
+ * which is not the same as safe — the package cannot invent the label, and
25
+ * quietly deduplicating an unlabelled call would be a guess about somebody
26
+ * else's API.
27
+ */
28
+ export declare function onceEach(): {
29
+ /** The earlier result for this exact destructive call, when there is one. */
30
+ earlier(tool: Tool<never> | undefined, name: string, args: Record<string, unknown>): ToolResult | undefined;
31
+ keep(tool: Tool<never> | undefined, result: ToolResult): void;
32
+ };
@@ -0,0 +1 @@
1
+ const r=t=>{if(t===null||typeof t!="object")return JSON.stringify(t)??"";if(Array.isArray(t))return`[${t.map(r).join(",")}]`;const n=t;return`{${Object.keys(n).sort().map(e=>`${JSON.stringify(e)}:${r(n[e])}`).join(",")}}`},c=(t,n)=>`${t}::${r(n)}`;function o(){const t=new Map;return{earlier(n,e,i){if(n?.effect==="destructive")return t.get(c(e,i))},keep(n,e){n?.effect!=="destructive"||e.status!=="completed"||t.set(c(e.name,e.args),e)}}}export{c as callKey,o as onceEach};
@@ -0,0 +1,29 @@
1
+ import type { Effect, Tool, ToolDeclaration, ToolResult } from "../types/index.js";
2
+ import type { AnthropicTool, OpenAITool } from "../wire/index.js";
3
+ import type { ToolTrace } from "./trace.js";
4
+ /**
5
+ * A bus narrowed to some of its tools.
6
+ *
7
+ * The declaring half is the half that changes: a model is shown these, and
8
+ * everything reaches the same `invoke` underneath. Written out rather than
9
+ * derived from `toolbus`, because a type that referred back to its own return
10
+ * would be circular — and because what a view promises is worth saying once.
11
+ */
12
+ export interface Offering {
13
+ /** The tools in this view, in declaration order. */
14
+ all(): Tool<never>[];
15
+ get(name: string): Tool<never> | undefined;
16
+ /** Names this view does not offer, whether or not the bus behind it has them. */
17
+ missing(names: string[]): string[];
18
+ effectOf(name: string): Effect | undefined;
19
+ declarations(names?: string[]): ToolDeclaration[];
20
+ anthropic(decls?: ToolDeclaration[]): AnthropicTool[];
21
+ openai(decls?: ToolDeclaration[]): OpenAITool[];
22
+ markdown(decls?: ToolDeclaration[], heading?: string): string;
23
+ select(query?: string, limit?: number): ToolDeclaration[];
24
+ /** Runs one, through the bus this view came from. */
25
+ invoke(name: string, args: Record<string, unknown>): Promise<ToolResult>;
26
+ /** How often each has been called on the bus behind this view. */
27
+ usage(): Record<string, number>;
28
+ trace(query?: string, limit?: number): ToolTrace;
29
+ }
@@ -19,4 +19,35 @@ export interface ToolBusOptions {
19
19
  * often, which is why it is worth saying at construction.
20
20
  */
21
21
  warnOnOverlap?: boolean;
22
+ /**
23
+ * Longest output a tool may return, in characters. No cap by default.
24
+ *
25
+ * One tool handing back a whole document fills a window on its own, and the
26
+ * failure is silent: no error, a clean call, a clean reply, and an answer
27
+ * that is wrong in the same tone as a right one. Nothing downstream can tell
28
+ * a tool that found three matches from one that found three hundred and was
29
+ * cut after three.
30
+ *
31
+ * Cut output says so, twice: a line the model reads at the end of the text,
32
+ * and `truncated` on the result for code that needs to count it. A model told
33
+ * it is looking at part of something asks again; one that is not, answers.
34
+ *
35
+ * No default, because a cap is a statement about your context window and your
36
+ * tools, and a number chosen here would be wrong for both. The builtins that
37
+ * fetch carry their own `maxChars` for the same reason.
38
+ */
39
+ maxOutputChars?: number;
40
+ /**
41
+ * Run each destructive call once, however many times it is asked for.
42
+ *
43
+ * A repeat of a call that already completed gets the first result back
44
+ * without the tool running again, marked `repeated` so an operator can count
45
+ * it. `readonly` and `idempotent` calls run every time, which is what those
46
+ * labels mean; a tool that declared no effect is not covered.
47
+ *
48
+ * Off by default. Deduplication is scoped to one bus, so what counts as "the
49
+ * same call again" is a decision about how long a bus lives — one per run, one
50
+ * per session, one per process — and the package cannot make it for you.
51
+ */
52
+ onceEach?: boolean;
22
53
  }
@@ -1,20 +1,3 @@
1
- /**
2
- * What a handler returned, as the string a result carries.
3
- *
4
- * A string is itself; anything else is JSON. `graph`'s `stringify` describes
5
- * this as "the same convention as a tool result" — it was not, and this is the
6
- * side that had drifted.
7
- *
8
- * `JSON.stringify` returns `undefined` for a function or an undefined value, so
9
- * a completed result carried `output: undefined` where its own type says
10
- * `string`, and the model was handed nothing while being told it was handed
11
- * something. And it *throws* on a circular object, a `BigInt`, or anything whose
12
- * `toJSON` throws — a circular object being any value with a parent backlink.
13
- *
14
- * What comes back when a value cannot be written is a note saying so, never
15
- * `""`: an empty output reads as a tool that produced nothing, and this is a
16
- * tool that produced something unwritable.
17
- */
18
1
  export declare function render(value: unknown): string;
19
2
  /**
20
3
  * Why a handler failed, from whatever it threw.
@@ -1,2 +1,2 @@
1
- function r(n){if(n==null)return"";if(typeof n=="string")return n;try{const t=JSON.stringify(n);return t===void 0?`[not recordable: ${typeof n}]`:t}catch(t){return`[not recordable: ${(t instanceof Error?t.message:String(t)).split(`
2
- `)[0]}]`}}function o(n){if(n instanceof Error&&n.message.trim())return n.message;if(typeof n=="string"&&n.trim())return n;const t=r(n);return t&&t!=="{}"?`Tool failed: ${t}`:"Tool failed."}export{o as reasonFor,r as render};
1
+ function t(n){const r=n;return typeof r?.answer=="string"&&r.answer.trim()!==""&&Array.isArray(r.results)}function e(n){if(n==null)return"";if(typeof n=="string")return n;if(t(n))return n.answer;try{const r=JSON.stringify(n);return r===void 0?`[not recordable: ${typeof n}]`:r}catch(r){return`[not recordable: ${(r instanceof Error?r.message:String(r)).split(`
2
+ `)[0]}]`}}function o(n){if(n instanceof Error&&n.message.trim())return n.message;if(typeof n=="string"&&n.trim())return n;const r=e(n);return r&&r!=="{}"?`Tool failed: ${r}`:"Tool failed."}export{o as reasonFor,e as render};
@@ -1,19 +1,3 @@
1
1
  import type { Tool, ToolDeclaration } from "../types/index.js";
2
2
  import type { Scorer } from "./score.js";
3
- /**
4
- * The working set for one request: pinned, then what the query matches, then
5
- * what actually gets used.
6
- *
7
- * Relevance before usage, which is the opposite of what this did first. At a
8
- * shortlist of twelve the order was harmless; at six, three previously-used
9
- * tools take half the slots and push out the tool the query needs.
10
- *
11
- * Usage still earns its place as the tiebreaker among equal matches, and as the
12
- * fallback when nothing matches — the case where an agent would otherwise be
13
- * handed nothing.
14
- *
15
- * How many come back depends on how clearly the query matched. A single strong
16
- * match needs no company; a flat spread means the ranking does not know, and a
17
- * wider net is worth the distraction.
18
- */
19
3
  export declare function selectTools(tools: Tool<never>[], calls: Map<string, number>, declare: (t: Tool<never>) => ToolDeclaration, scoreOf: Scorer, query: string, ceiling: number): ToolDeclaration[];
@@ -1 +1 @@
1
- import{termsIn as u}from"./terms.js";function v(m,e,h,a,p,f){const d=u(p),n=[],r=t=>{!n.includes(t)&&n.length<f&&n.push(t)};for(const t of m)t.pinned&&r(t);const i=m.filter(t=>!t.pinned),o=i.map(t=>({t,n:a(t,d)})).filter(t=>t.n>0).sort((t,s)=>s.n-t.n||(e.get(s.t.name)??0)-(e.get(t.t.name)??0)),c=f-n.length,k=o.length>1&&o[0].n>=o[1].n*2,g=n.length+(k?Math.min(3,c):c);for(const{t}of o){if(n.length>=g)break;r(t)}const b=[...i].sort((t,s)=>(e.get(s.name)??0)-(e.get(t.name)??0));for(const t of b){if(n.length>=g||(e.get(t.name)??0)===0)break;r(t)}if(o.length===0)for(const t of i){if(n.length>=f)break;r(t)}return n.map(h)}export{v as selectTools};
1
+ import{termsIn as l}from"./terms.js";function w(t,o,g){if(!t.some(f=>f.needs?.length))return t;const r=[];for(const f of t){if(r.includes(f))continue;const s=(f.needs??[]).map(i=>o.get(i)).filter(i=>i!==void 0&&!r.includes(i));r.length+1+s.length>g||r.push(f,...s)}return r}function M(t,o,g,r,f,s){const i=new Map(t.map(n=>[n.name,n])),p=l(f),e=[],m=n=>{!e.includes(n)&&e.length<s&&e.push(n)};for(const n of t)n.pinned&&m(n);const d=t.filter(n=>!n.pinned),c=d.map(n=>({t:n,n:r(n,p)})).filter(n=>n.n>0).sort((n,a)=>a.n-n.n||(o.get(a.t.name)??0)-(o.get(n.t.name)??0)),u=s-e.length,k=c.length>1&&c[0].n>=c[1].n*2,h=e.length+(k?Math.min(3,u):u);for(const{t:n}of c){if(e.length>=h)break;m(n)}const b=[...d].sort((n,a)=>(o.get(a.name)??0)-(o.get(n.name)??0));for(const n of b){if(e.length>=h||(o.get(n.name)??0)===0)break;m(n)}if(c.length===0)for(const n of d){if(e.length>=s)break;m(n)}return w(e,i,s).map(g)}export{M as selectTools};
@@ -0,0 +1,16 @@
1
+ import type { ToolResult } from "../types/index.js";
2
+ /**
3
+ * What the tools themselves cost, in micro-USD.
4
+ *
5
+ * A run's token counts are the outer model's. A tool that spends on its own —
6
+ * a deep recall, a judge, a sub-agent — is not in them, so a loop that called
7
+ * three of those reports a bill that is missing most of itself. Only results
8
+ * from tools that declared a `costOf` count; the rest are not free, they are
9
+ * unmeasured, and those are different claims.
10
+ */
11
+ export declare function spentOn(results: readonly ToolResult[]): number;
12
+ /** The calls that reported a price, so an unmeasured one is visible as an absence. */
13
+ export declare function priced(results: readonly ToolResult[]): {
14
+ name: string;
15
+ costMicros: number;
16
+ }[];
@@ -0,0 +1 @@
1
+ function c(o){let t=0;for(const r of o)t+=r.costMicros??0;return t}function e(o){return o.filter(t=>t.costMicros!==void 0).map(t=>({name:t.name,costMicros:t.costMicros}))}export{e as priced,c as spentOn};
@@ -18,7 +18,12 @@ export interface ToolTrace {
18
18
  * never said — and for one that was never offered.
19
19
  */
20
20
  effectOf(name: string): Effect | undefined;
21
- /** Runs a tool and records the step. Never throws, exactly as `invoke`. */
21
+ /**
22
+ * Runs a tool this turn offered and records the step. Never throws.
23
+ *
24
+ * A name that was not offered comes back as a failed result naming what was,
25
+ * without reaching the bus — see `newTrace`.
26
+ */
22
27
  invoke(name: string, args: Record<string, unknown>): Promise<ToolResult>;
23
28
  /** The steps so far, in call order. */
24
29
  steps(): RolloutStep[];
@@ -38,5 +43,13 @@ export interface ToolTrace {
38
43
  *
39
44
  * Selection happens once, here, and the same list is what gets reported. A trace
40
45
  * cannot disagree with itself about what the model saw.
46
+ *
47
+ * It also cannot run what it did not offer. A shortlist narrows the declarations
48
+ * and used to hand `invoke` the whole bus, so a name the model produced out of
49
+ * nowhere still ran if anything on the bus happened to be called that — and the
50
+ * rollout came back with a step that had no matching entry in `offeredTools`,
51
+ * which reads as impossible. The refusal is a failed result rather than a throw,
52
+ * carrying the names that were offered, because that is an observation the model
53
+ * can correct from on its next turn; an exception is one the run dies of.
41
54
  */
42
55
  export declare function newTrace(offered: ToolDeclaration[], invoke: (name: string, args: Record<string, unknown>) => Promise<ToolResult>): ToolTrace;
package/dist/bus/trace.js CHANGED
@@ -1 +1 @@
1
- import{toAnthropic as s,toMarkdown as a,toOpenAI as c}from"../wire/index.js";import{toStep as i}from"./step.js";function h(n,r){const o=[];return{offered:n,anthropic:()=>s(n),openai:()=>c(n),markdown:t=>a(n,t),effectOf:t=>n.find(e=>e.name===t)?.effect,invoke:async(t,e)=>{const p=await r(t,e);return o.push(i(p,o.length)),p},steps:()=>[...o],record:()=>({offeredTools:n.map(t=>t.name),steps:[...o]})}}export{h as newTrace};
1
+ import{toAnthropic as p,toMarkdown as c,toOpenAI as i}from"../wire/index.js";import{toStep as u}from"./step.js";function m(t,r,o){return{name:t,args:r,status:"failed",output:"",error:`No tool called "${t}" was offered this turn. Offered: ${o.map(n=>n.name).join(", ")}`,latencyMs:0}}function h(t,r){const o=[];return{offered:t,anthropic:()=>p(t),openai:()=>i(t),markdown:n=>c(t,n),effectOf:n=>t.find(e=>e.name===n)?.effect,invoke:async(n,e)=>{const s=t.some(a=>a.name===n)?await r(n,e):m(n,e,t);return o.push(u(s,o.length)),s},steps:()=>[...o],record:()=>({offeredTools:t.map(n=>n.name),steps:[...o]})}}export{h as newTrace};
package/dist/index.d.ts CHANGED
@@ -7,10 +7,12 @@
7
7
  * converters themselves, for a caller adapting a declaration by hand.
8
8
  */
9
9
  export type { RolloutStep } from "@spendgraph/sdk";
10
- export { type ArtifactFormat, answerOf, type ClockOptions, type CodeExecOptions, CommissionAbortedError, type CommissionClient, CommissionTimeoutError, calculate, codeExec, currentTime, DEFAULT_DESIGN, type DeepRecallOptions, type DesignGuide, dateMath, deepRecall, type EscalateOptions, type EscalationRequest, escalate, type Finished, finish, type HttpOptions, httpRequest, isFinished, type JsonQueryOptions, jsonQuery, mergeDesign, type RecalledFact, type Recaller, type RecallResult, renderDesign, type Sandbox, type SandboxRequest, type SandboxResult, type SearchDepth, think, type WebSearchOptions, type WriteDocumentOptions, webSearch, writeDocument, } from "./builtin/index.js";
11
- export type { BusMember, ToolBus, ToolBusOptions, ToolTrace } from "./bus/index.js";
12
- export { busgroup, toolbus } from "./bus/index.js";
10
+ export { answerOf, type ClockOptions, type CodeExecOptions, calculate, codeExec, currentTime, type Declined, dateMath, dates, decline, declinedFor, type EscalateOptions, type EscalationRequest, type ExtractOptions, escalate, escalationOf, extract, type Finished, finish, type HttpOptions, httpRequest, isDeclined, isEscalated, isFinished, type JsonQueryOptions, jsonFrom, jsonQuery, type NotesOptions, type NotesStore, notes, notesStore, type OpenAlexApi, type OpenAlexOptions, openalex, type PaperSearchOptions, type Publisher, type PublishOptions, paperSearch, publish, retryAfterMs, type Sandbox, type SandboxRequest, type SandboxResult, type SearchDepth, think, type Unanswerable, type WebSearchOptions, type WikidataApi, type WikidataOptions, webSearch, wikidata, } from "./builtin/index.js";
11
+ export type { BusGroupOptions, BusMember, Namespacing, Offering, ToolBus, ToolBusOptions, ToolTrace, } from "./bus/index.js";
12
+ export { busgroup, priced, spentOn, toolbus } from "./bus/index.js";
13
+ export { contextId, type DeepRecallOptions, deepRecall, type ExploreOptions, exploreMemory, type MemoriesOptions, type MemoryClient, type MemoryContext, type MemoryGraph, type MemoryKind, type MemorySet, type MemorySource, type Moment, type MomentSource, memories, type Observer, type ObserverOptions, observer, type RecalledFact, type Recaller, type RecallFormat, type RecallOptions, type RecallResult, type RememberOptions, recall, remember, } from "./memories/index.js";
14
+ export type { Source } from "./search/search.js";
13
15
  export type { BoundSpec, ToolSpec } from "./tool/index.js";
14
16
  export { bindTool, ToolDriftError, ToolNotStoredError, tool } from "./tool/index.js";
15
- export type { ArgSpec, ArgsOf, ArgValue, Effect, Tool, ToolDeclaration, ToolResult, } from "./types/index.js";
17
+ export type { ArgSpec, ArgsOf, ArgValue, Effect, Tool, ToolDeclaration, ToolResult, Trust, } from "./types/index.js";
16
18
  export type { AnthropicTool, JsonSchema, JsonSchemaProperty, OpenAITool, } from "./wire/index.js";
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{answerOf as r,CommissionAbortedError as t,CommissionTimeoutError as i,calculate as s,codeExec as n,currentTime as m,DEFAULT_DESIGN as l,dateMath as a,deepRecall as c,escalate as u,finish as d,httpRequest as E,isFinished as f,jsonQuery as h,mergeDesign as p,renderDesign as D,think as T,webSearch as b,writeDocument as g}from"./builtin/index.js";import{busgroup as w,toolbus as S}from"./bus/index.js";import{bindTool as C,ToolDriftError as F,ToolNotStoredError as N,tool as R}from"./tool/index.js";export{t as CommissionAbortedError,i as CommissionTimeoutError,l as DEFAULT_DESIGN,F as ToolDriftError,N as ToolNotStoredError,r as answerOf,C as bindTool,w as busgroup,s as calculate,n as codeExec,m as currentTime,a as dateMath,c as deepRecall,u as escalate,d as finish,E as httpRequest,f as isFinished,h as jsonQuery,p as mergeDesign,D as renderDesign,T as think,R as tool,S as toolbus,b as webSearch,g as writeDocument};
1
+ import{answerOf as o,calculate as t,codeExec as s,currentTime as a,dateMath as i,dates as l,decline as c,declinedFor as n,escalate as d,escalationOf as p,extract as m,finish as f,httpRequest as x,isDeclined as h,isEscalated as u,isFinished as b,jsonFrom as E,jsonQuery as S,notes as T,notesStore as w,openalex as y,paperSearch as F,publish as M,retryAfterMs as O,think as j,webSearch as k,wikidata as D}from"./builtin/index.js";import{busgroup as g,priced as q,spentOn as v,toolbus as A}from"./bus/index.js";import{contextId as N,deepRecall as Q,exploreMemory as z,memories as B,observer as C,recall as G,remember as H}from"./memories/index.js";import{bindTool as K,ToolDriftError as L,ToolNotStoredError as P,tool as U}from"./tool/index.js";export{L as ToolDriftError,P as ToolNotStoredError,o as answerOf,K as bindTool,g as busgroup,t as calculate,s as codeExec,N as contextId,a as currentTime,i as dateMath,l as dates,c as decline,n as declinedFor,Q as deepRecall,d as escalate,p as escalationOf,z as exploreMemory,m as extract,f as finish,x as httpRequest,h as isDeclined,u as isEscalated,b as isFinished,E as jsonFrom,S as jsonQuery,B as memories,T as notes,w as notesStore,C as observer,y as openalex,F as paperSearch,q as priced,M as publish,G as recall,H as remember,O as retryAfterMs,v as spentOn,j as think,U as tool,A as toolbus,k as webSearch,D as wikidata};
@@ -4,7 +4,14 @@
4
4
  * Not in the main entry: a bus already wires all of it, and a caller reaching
5
5
  * here is building their own. Kept exported so that stays possible.
6
6
  */
7
- export { evaluate } from "./builtin/calculate/index.js";
7
+ /**
8
+ * The arithmetic behind `calculate`, and the way it renders a result.
9
+ *
10
+ * Both, because either alone is half a comparison. A rail checking a model's
11
+ * sum has to render its own the way the tool did or it flags a correct answer:
12
+ * `evaluate("0.1 + 0.2")` is `0.30000000000000004` and the tool said `0.3`.
13
+ */
14
+ export { evaluate, exact } from "./builtin/calculate/index.js";
8
15
  export { between, parseDate, shift, type Unit } from "./builtin/date/index.js";
9
16
  export { checkUrl } from "./builtin/http/index.js";
10
17
  export { readPath } from "./builtin/json/index.js";
package/dist/internals.js CHANGED
@@ -1 +1 @@
1
- import{evaluate as e}from"./builtin/calculate/index.js";import{between as p,parseDate as f,shift as m}from"./builtin/date/index.js";import{checkUrl as a}from"./builtin/http/index.js";import{readPath as c}from"./builtin/json/index.js";import{invokeTool as s}from"./bus/invoke.js";import{warnOnOverlap as v}from"./bus/overlap.js";import{scorerFor as T}from"./bus/score.js";import{selectTools as k}from"./bus/select.js";import{toStep as b}from"./bus/step.js";import{newTrace as u}from"./bus/trace.js";export{p as between,a as checkUrl,e as evaluate,s as invokeTool,u as newTrace,f as parseDate,c as readPath,T as scorerFor,k as selectTools,m as shift,b as toStep,v as warnOnOverlap};
1
+ import{evaluate as o,exact as t}from"./builtin/calculate/index.js";import{between as f,parseDate as x,shift as a}from"./builtin/date/index.js";import{checkUrl as c}from"./builtin/http/index.js";import{readPath as n}from"./builtin/json/index.js";import{invokeTool as h}from"./bus/invoke.js";import{warnOnOverlap as w}from"./bus/overlap.js";import{scorerFor as i}from"./bus/score.js";import{selectTools as O}from"./bus/select.js";import{toStep as d}from"./bus/step.js";import{newTrace as D}from"./bus/trace.js";export{f as between,c as checkUrl,o as evaluate,t as exact,h as invokeTool,D as newTrace,x as parseDate,n as readPath,i as scorerFor,O as selectTools,a as shift,d as toStep,w as warnOnOverlap};
@@ -0,0 +1,91 @@
1
+ import type { RootContextId } from "./context.js";
2
+ import type { Recaller } from "./deep-recall/deep-recall.js";
3
+ export type MemorySource = "policy" | "verified" | "tool" | "document" | "user" | "assistant" | "derived" | "system";
4
+ export type MomentSource = "policy" | "verified" | "tool" | "turn";
5
+ export type MemoryKind = "fact" | "decision" | "constraint" | "feedback" | "observation";
6
+ export interface MemoryContext {
7
+ context_id: string;
8
+ context_type: string;
9
+ context_name: string;
10
+ reference_count: number;
11
+ }
12
+ export interface RecalledItem {
13
+ locus_id: string;
14
+ context_ids: string[];
15
+ text: string;
16
+ score: number;
17
+ source?: string;
18
+ kind?: string;
19
+ created?: number;
20
+ }
21
+ export interface MemoryClient extends Recaller {
22
+ retrieveMemories(query: {
23
+ query: string;
24
+ graphId?: string;
25
+ limit?: number;
26
+ contextIds?: string[];
27
+ boostContextIds?: string[];
28
+ sources?: string[];
29
+ format?: string;
30
+ }): Promise<{
31
+ items_found: number;
32
+ items?: RecalledItem[];
33
+ }>;
34
+ storeEventsBatch(items: {
35
+ event_kind: string;
36
+ context_id?: string;
37
+ source?: MemorySource;
38
+ extends?: string[];
39
+ related_to?: string[];
40
+ reinforces?: string[];
41
+ contradicts?: string[];
42
+ payload: Record<string, unknown>;
43
+ }[], graphId?: string): Promise<{
44
+ stored: number;
45
+ filtered: number;
46
+ failed: number;
47
+ results: {
48
+ status: "recorded" | "filtered" | "error";
49
+ event_id?: string;
50
+ relevance?: "high" | "medium" | "low";
51
+ error?: string;
52
+ }[];
53
+ }>;
54
+ searchContexts(query: string, graphId?: string, options?: {
55
+ context_type?: string;
56
+ page_size?: number;
57
+ include?: string;
58
+ format?: string;
59
+ }): Promise<{
60
+ contexts: MemoryContext[];
61
+ total: number;
62
+ relationships_text?: string;
63
+ }>;
64
+ listContextTypes(graphId?: string): Promise<{
65
+ context_types: {
66
+ context_type: string;
67
+ count: number;
68
+ }[];
69
+ total: number;
70
+ }>;
71
+ getContextGraph(options: {
72
+ graphId?: string;
73
+ contextType: string;
74
+ contextName: string;
75
+ depth?: number;
76
+ }): Promise<unknown>;
77
+ observe(request: {
78
+ graphId?: string;
79
+ source: MomentSource;
80
+ payload: string | Record<string, unknown>;
81
+ stream?: string;
82
+ observedAt?: number;
83
+ }): Promise<{
84
+ observed: boolean;
85
+ }>;
86
+ }
87
+ export interface MemoryGraph {
88
+ client: MemoryClient;
89
+ graphId?: string;
90
+ rootContextId?: RootContextId;
91
+ }
File without changes
@@ -0,0 +1,5 @@
1
+ export declare function contextId(raw: string, defaultType?: string): string;
2
+ export declare const contextIds: (raw: string[] | undefined, defaultType?: string) => string[] | undefined;
3
+ export type RootContextId = string | (() => string | undefined);
4
+ export declare function rootOf(rootContextId: RootContextId | undefined): string | undefined;
5
+ export declare const fixedRoot: (rootContextId: RootContextId | undefined) => string | undefined;
@@ -0,0 +1 @@
1
+ const r="topic",f=120,c=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"");function o(e,n=r){const t=e.indexOf(":"),i=c(t<0?n:e.slice(0,t)),s=c(t<0?e:e.slice(t+1));if(!s)throw new Error(`"${e}" names no context; write it as type:name, like person:alice.`);return`${i}:${s}`.slice(0,120)}const p=(e,n)=>e?.length?e.map(t=>o(t,n)):void 0;function u(e){if(e===void 0)return;const n=typeof e=="function"?e():e;if(!n)throw new Error("No root context id is set for this run, so memory stays closed.");return o(n)}const d=e=>typeof e=="string"?o(e):void 0;export{o as contextId,p as contextIds,d as fixedRoot,u as rootOf};
@@ -1,3 +1,4 @@
1
+ import { type RootContextId } from "../context.js";
1
2
  /** One piece of evidence, with where it came from. */
2
3
  export interface RecalledFact {
3
4
  text: string;
@@ -41,6 +42,8 @@ export interface DeepRecallOptions {
41
42
  client: Recaller;
42
43
  /** Graph the walk runs over. Unset, the client's own default is used. */
43
44
  graphId?: string;
45
+ /** Context the walk starts from, fixed or read from run state on each call. */
46
+ rootContextId?: RootContextId;
44
47
  /** Longest evidence list handed back. Default 20. */
45
48
  maxFacts?: number;
46
49
  }
@@ -0,0 +1 @@
1
+ import{tool as c}from"../../tool/index.js";import{rootOf as d}from"../context.js";const l=20;function h(t){const o=t.maxFacts??l;return c({name:"deep_recall",description:"Searches your own knowledge base and returns an answer with the evidence it rests on. A walker follows linked contexts, so it answers questions spread across several notes \u2014 what do we know about X, what was decided and why. Ask one focused thing. Prefer it over a web search whenever the answer could already be in your records.",effect:"readonly",needs:["recall"],args:[{name:"question",type:"string",required:!0,maxLength:1e3,description:"One focused question, not a conversation and not several at once."},{name:"context_ids",type:"list",required:!1,description:"Contexts to start the walk from, as type:name \u2014 take them from the contexts of an earlier result. A hint, not a filter; the walk may go elsewhere."}],costOf:a=>a.costMicroUsd,run:async({question:a,context_ids:r})=>{const n=d(t.rootContextId),s=n?[...new Set([n,...r??[]])]:r,e=await t.client.deepRecall({question:a,...t.graphId?{graphId:t.graphId}:{},...s?.length?{contextIds:s}:{}});return{summary:e.summary,facts:e.facts.slice(0,o),truncated:e.facts.length>o,contextsWalked:e.contexts_walked,coverage:e.coverage,fallback:e.fallback,costMicroUsd:Math.round(e.usage.cost_usd*1e6)}}})}export{h as deepRecall};
@@ -0,0 +1,18 @@
1
+ import type { MemoryGraph } from "../client.js";
2
+ export interface ExploreOptions extends MemoryGraph {
3
+ limit?: number;
4
+ depth?: number;
5
+ }
6
+ export declare function exploreMemory(opts: ExploreOptions): import("../../index.js").Tool<import("../../index.js").ArgsOf<readonly [{
7
+ readonly name: "query";
8
+ readonly type: "string";
9
+ readonly required: false;
10
+ readonly maxLength: 200;
11
+ readonly description: "Part of a context name, like pric or alice. Leave out to list what is there.";
12
+ }, {
13
+ readonly name: "type";
14
+ readonly type: "string";
15
+ readonly required: false;
16
+ readonly maxLength: 60;
17
+ readonly description: "Only contexts of this type, like person or decision.";
18
+ }]>>;
@@ -0,0 +1,7 @@
1
+ import{tool as f}from"../../tool/index.js";import{fixedRoot as g,rootOf as y}from"../context.js";import{drawSubgraph as w,readSubgraph as _}from"./subgraph.js";const d=20,$=3,L=t=>`${t} note${t===1?"":"s"}`,l=t=>t.length===0?"Memory is empty: no contexts yet.":`Context types: ${t.map(e=>`${e.context_type} (${e.count})`).join(", ")}.`,m=t=>t.map(e=>`- ${e.context_id} (${L(e.reference_count)})`).join(`
2
+ `),I=t=>{const e=new Map;for(const o of t)e.set(o.context_type,(e.get(o.context_type)??0)+1);return[...e].map(([o,r])=>({context_type:o,count:r}))},C=(t,e,o)=>t.filter(r=>!o||r.context_type===o).filter(r=>!e||r.context_id.toLowerCase().includes(e.toLowerCase())),p=t=>`No contexts match "${t}". Try a shorter stem, or no query to list the types.`;function M(t){const e=t.rootContextId!==void 0,o=g(t.rootContextId)??"your root",r=e?`Shows what is filed under ${o} and how it links up, without reading the notes themselves. With no query it lists the contexts in that subtree and their links. With a query it narrows to the contexts whose name contains it.`:"Shows what is filed in your own memory and how it links up, without reading the notes themselves. With no query it lists the context types in use, which is how to learn the filing scheme before you remember something. With a query it finds matching contexts and draws their relationships.",x=async(n,i,s)=>{const c=n.indexOf(":"),a=_(await t.client.getContextGraph({contextType:n.slice(0,c),contextName:n.slice(c+1),depth:t.depth??$,...t.graphId?{graphId:t.graphId}:{}})),h=C(a.nodes,i,s).slice(0,t.limit??d);return h.length===0?i?p(i):`Nothing is filed under ${n} yet.`:`${l(I(h))}
3
+
4
+ ${w(h,a.edges)}`},u=async(n,i)=>{if(!n?.trim()){const a=await t.client.listContextTypes(t.graphId);return l(a.context_types)}const s=await t.client.searchContexts(n,t.graphId,{page_size:t.limit??d,include:"relationships",format:"mindmap",...i?{context_type:i}:{}});if(s.contexts.length===0)return p(n);const c=s.relationships_text?.trim();return c?`${m(s.contexts)}
5
+
6
+ Links:
7
+ ${c}`:m(s.contexts)};return f({name:"explore_memory",effect:"readonly",description:r,args:[{name:"query",type:"string",required:!1,maxLength:200,description:"Part of a context name, like pric or alice. Leave out to list what is there."},{name:"type",type:"string",required:!1,maxLength:60,description:"Only contexts of this type, like person or decision."}],run:({query:n,type:i})=>{const s=y(t.rootContextId);return s?x(s,n?.trim(),i):u(n?.trim(),i)}})}export{M as exploreMemory};
@@ -0,0 +1,12 @@
1
+ import type { MemoryContext } from "../client.js";
2
+ export interface SubgraphEdge {
3
+ from: string;
4
+ to: string;
5
+ link_type: string;
6
+ }
7
+ export interface Subgraph {
8
+ nodes: MemoryContext[];
9
+ edges: SubgraphEdge[];
10
+ }
11
+ export declare function readSubgraph(raw: unknown): Subgraph;
12
+ export declare const drawSubgraph: (nodes: MemoryContext[], edges: SubgraphEdge[]) => string;
@@ -0,0 +1,3 @@
1
+ const c=t=>typeof t=="object"&&t!==null,o=t=>typeof t=="string"?t:"",s=t=>{if(!c(t)||typeof t.context_id!="string")return null;const n=t.context_id.indexOf(":");return{context_id:t.context_id,context_type:o(t.context_type)||t.context_id.slice(0,n),context_name:o(t.context_name)||t.context_id.slice(n+1),reference_count:typeof t.reference_count=="number"?t.reference_count:0}},d=t=>{if(!c(t))return null;const n=o(t.from)||o(t.from_context_id),e=o(t.to)||o(t.to_context_id);return n&&e?{from:n,to:e,link_type:o(t.link_type)||"related_to"}:null};function p(t){const n=c(t)&&c(t.graph)?t.graph:t;if(!c(n))return{nodes:[],edges:[]};const e=Array.isArray(n.nodes)?n.nodes.map(s):[],i=Array.isArray(n.edges)?n.edges.map(d):[];return{nodes:e.filter(r=>r!==null),edges:i.filter(r=>r!==null)}}const _={extends:"extended_by",reinforces:"reinforced_by",contradicts:"contradicted_by",related_to:"related_to"},f=(t,n)=>[...n.filter(e=>e.from===t).map(e=>`${e.link_type} \u2192 ${e.to}`),...n.filter(e=>e.to===t).map(e=>`${_[e.link_type]??e.link_type} \u2190 ${e.from}`)],l=t=>t.map((n,e)=>` ${e===t.length-1?"\u2514\u2500":"\u251C\u2500"} ${n}`),x=(t,n)=>t.map(e=>[e.context_id,...l(f(e.context_id,n))].join(`
2
+ `)).join(`
3
+ `);export{x as drawSubgraph,p as readSubgraph};
@@ -0,0 +1,30 @@
1
+ import type { Tool } from "../types/index.js";
2
+ import type { MemoryClient, MemorySource } from "./client.js";
3
+ import type { RootContextId } from "./context.js";
4
+ import { type Observer } from "./observe/observe.js";
5
+ import { type RecallFormat } from "./recall/recall.js";
6
+ export type { MemoryClient, MemoryContext, MemoryGraph, MemoryKind, MemorySource, MomentSource, } from "./client.js";
7
+ export { contextId, type RootContextId } from "./context.js";
8
+ export { type DeepRecallOptions, deepRecall, type RecalledFact, type Recaller, type RecallResult, } from "./deep-recall/index.js";
9
+ export { type ExploreOptions, exploreMemory } from "./explore/explore.js";
10
+ export { type Moment, type Observer, type ObserverOptions, observer, } from "./observe/observe.js";
11
+ export { type RecallFormat, type RecallOptions, recall } from "./recall/recall.js";
12
+ export { type RememberOptions, remember } from "./remember/remember.js";
13
+ export interface MemoriesOptions {
14
+ client: MemoryClient;
15
+ graphId?: string;
16
+ rootContextId?: RootContextId;
17
+ source?: MemorySource;
18
+ defaultContextType?: string;
19
+ recallFormat?: RecallFormat;
20
+ recallLimit?: number;
21
+ /** Let `recall` say which notes a later one superseded. See `RecallOptions`. */
22
+ supersede?: boolean;
23
+ stream?: string;
24
+ maxFacts?: number;
25
+ }
26
+ export interface MemorySet {
27
+ tools: Tool<never>[];
28
+ observe: Observer;
29
+ }
30
+ export declare function memories(opts: MemoriesOptions): MemorySet;
@@ -0,0 +1 @@
1
+ import{deepRecall as a}from"./deep-recall/index.js";import{exploreMemory as l}from"./explore/explore.js";import{observer as c}from"./observe/observe.js";import{recall as n}from"./recall/recall.js";import{remember as x}from"./remember/remember.js";import{contextId as C}from"./context.js";import{deepRecall as g}from"./deep-recall/index.js";import{exploreMemory as v}from"./explore/explore.js";import{observer as T}from"./observe/observe.js";import{recall as R}from"./recall/recall.js";import{remember as j}from"./remember/remember.js";function s(e){const r={client:e.client,...e.graphId?{graphId:e.graphId}:{},...e.rootContextId!==void 0?{rootContextId:e.rootContextId}:{}},o=e.defaultContextType,t=[n({...r,format:e.recallFormat,limit:e.recallLimit,...e.supersede?{supersede:!0}:{},defaultContextType:o}),a({...r,maxFacts:e.maxFacts}),x({...r,source:e.source,defaultContextType:o}),l(r)],m=c({...r,stream:e.stream});return{tools:t,observe:m}}export{C as contextId,g as deepRecall,v as exploreMemory,s as memories,T as observer,R as recall,j as remember};
@@ -0,0 +1,7 @@
1
+ import type { MemoryGraph, MomentSource } from "../client.js";
2
+ export type Moment = string | Record<string, unknown>;
3
+ export type Observer = (moment: Moment, source?: MomentSource) => Promise<boolean>;
4
+ export interface ObserverOptions extends MemoryGraph {
5
+ stream?: string;
6
+ }
7
+ export declare function observer(opts: ObserverOptions): Observer;
@@ -0,0 +1 @@
1
+ const t="turn";function c(r){return async(e,a=t)=>{const{observed:n}=await r.client.observe({source:a,payload:e,...r.graphId?{graphId:r.graphId}:{},...r.stream?{stream:r.stream}:{}});return n}}export{c as observer};
@@ -0,0 +1,42 @@
1
+ import type { MemoryGraph } from "../client.js";
2
+ import { type RecallFormat } from "./render.js";
3
+ export type { RecallFormat } from "./render.js";
4
+ export interface RecallOptions extends MemoryGraph {
5
+ format?: RecallFormat;
6
+ limit?: number;
7
+ sources?: string[];
8
+ defaultContextType?: string;
9
+ /**
10
+ * Say which notes a later one superseded, rather than returning both flat.
11
+ *
12
+ * `remember` takes a `contradicts` link, and without this nothing downstream
13
+ * ever reads it: a recall hands back the old plan and the new plan as two
14
+ * rows in score order, and the model answers with whichever scored higher.
15
+ * The graph knew which one won; the answer did not.
16
+ *
17
+ * Off by default because it costs a second read — the subtree under
18
+ * `rootContextId` — on every recall, and because it needs that root to have
19
+ * a subtree to read. Without a root there is nothing to fetch and the column
20
+ * is left off rather than filled with blanks.
21
+ */
22
+ supersede?: boolean;
23
+ }
24
+ export declare function recall(opts: RecallOptions): import("../../index.js").Tool<import("../../index.js").ArgsOf<readonly [{
25
+ readonly name: "question";
26
+ readonly type: "string";
27
+ readonly required: true;
28
+ readonly maxLength: 1000;
29
+ readonly description: "What you want to know, in a sentence.";
30
+ }, {
31
+ readonly name: "context_ids";
32
+ readonly type: "list";
33
+ readonly required: false;
34
+ readonly description: string;
35
+ }, {
36
+ readonly name: "limit";
37
+ readonly type: "number";
38
+ readonly required: false;
39
+ readonly min: 1;
40
+ readonly max: 50;
41
+ readonly description: `Most notes to return. Default ${number}.`;
42
+ }]>>;
@@ -0,0 +1 @@
1
+ import{tool as f}from"../../tool/index.js";import{contextIds as l,fixedRoot as h,rootOf as p}from"../context.js";import{readSubgraph as x}from"../explore/subgraph.js";import{rendered as y}from"./render.js";const g="toon",u=10,w=50,I=3;async function T(e,n){if(!e.supersede||!n)return;const o=n.indexOf(":"),s=x(await e.client.getContextGraph({contextType:n.slice(0,o),contextName:n.slice(o+1),depth:I,...e.graphId?{graphId:e.graphId}:{}})),a=new Map;for(const r of s.edges)r.link_type==="contradicts"&&a.set(r.to,r.from);return r=>r.context_ids.map(t=>a.get(t)).find(t=>t!==void 0)}function k(e){const n=e.rootContextId!==void 0,o=h(e.rootContextId)??"your root";return f({name:"recall",effect:"readonly",description:"Searches your own memory for what was recorded about something and returns the matching notes, one per row with the contexts each is filed under. Cheap, so try it before a web search and before deep_recall. Use deep_recall instead when the answer is spread across several notes or needs a why. Ask one focused thing.",args:[{name:"question",type:"string",required:!0,maxLength:1e3,description:"What you want to know, in a sentence."},{name:"context_ids",type:"list",required:!1,description:n?`Contexts under ${o} to favour, as type:name. Take them from an earlier result or from explore_memory.`:"Only search these contexts, as type:name. Take them from an earlier result or from explore_memory."},{name:"limit",type:"number",required:!1,min:1,max:w,description:`Most notes to return. Default ${e.limit??u}.`}],run:async({question:s,context_ids:a,limit:r})=>{const t=p(e.rootContextId),i=l(a,e.defaultContextType),d=t?[t]:i,c=t&&i?i:void 0,m=(await e.client.retrieveMemories({query:s,limit:r??e.limit??u,format:"json",...e.graphId?{graphId:e.graphId}:{},...d?{contextIds:d}:{},...c?{boostContextIds:c}:{},...e.sources?.length?{sources:e.sources}:{}})).items??[];return m.length===0?"Nothing recorded about that.":y(m,e.format??g,await T(e,t))}})}export{k as recall};
@@ -0,0 +1,5 @@
1
+ import type { RecalledItem } from "../client.js";
2
+ export type RecallFormat = "toon" | "markdown";
3
+ /** Which context superseded this note's, when one did. */
4
+ export type Superseded = (item: RecalledItem) => string | undefined;
5
+ export declare const rendered: (items: RecalledItem[], format: RecallFormat, by?: Superseded) => string;
@@ -0,0 +1,3 @@
1
+ const t=/[,:"\n\\]|^\s|\s$|^$/,d=n=>t.test(n)?`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}"`:n,c=n=>String(Math.round(n*100)),$=(n,o,e)=>[n.context_ids.join(";"),n.text,n.source??"",c(n.score),...e?[o??""]:[]],a=(n,o)=>{const e=o?"contexts,text,source,relevance,superseded_by":"contexts,text,source,relevance";return[`memories[${n.length}]{${e}}:`,...n.map(s=>` ${$(s,o?.(s),o!==void 0).map(d).join(",")}`)].join(`
2
+ `)},p=(n,o)=>n.map(e=>{const s=o?.(e),r=s?` \u2014 superseded by ${s}`:"";return`- [${e.context_ids.join(", ")}] ${e.text} (${e.source??"unknown"}, ${c(e.score)}%)${r}`}).join(`
3
+ `),u=(n,o,e)=>o==="toon"?a(n,e):p(n,e);export{u as rendered};
@@ -0,0 +1,49 @@
1
+ import type { MemoryGraph, MemorySource } from "../client.js";
2
+ export interface RememberOptions extends MemoryGraph {
3
+ source?: MemorySource;
4
+ defaultContextType?: string;
5
+ }
6
+ export declare function remember(opts: RememberOptions): import("../../index.js").Tool<import("../../index.js").ArgsOf<readonly [{
7
+ readonly name: "context";
8
+ readonly type: "string";
9
+ readonly required: true;
10
+ readonly maxLength: 200;
11
+ readonly description: "Where it is filed, as type:name.";
12
+ }, {
13
+ readonly name: "text";
14
+ readonly type: "string";
15
+ readonly required: true;
16
+ readonly maxLength: 4000;
17
+ readonly description: "The thing to remember, as a complete sentence or two.";
18
+ }, {
19
+ readonly name: "kind";
20
+ readonly type: "enum";
21
+ readonly required: false;
22
+ readonly options: readonly ["fact", "decision", "constraint", "feedback", "observation"];
23
+ readonly description: "What sort of thing it is. Default fact.";
24
+ }, {
25
+ readonly name: "details";
26
+ readonly type: "json";
27
+ readonly required: false;
28
+ readonly description: string;
29
+ }, {
30
+ readonly name: "extends";
31
+ readonly type: "list";
32
+ readonly required: false;
33
+ readonly description: "Contexts this is a more specific detail of, as type:name.";
34
+ }, {
35
+ readonly name: "related_to";
36
+ readonly type: "list";
37
+ readonly required: false;
38
+ readonly description: "Contexts this sits alongside, as type:name.";
39
+ }, {
40
+ readonly name: "reinforces";
41
+ readonly type: "list";
42
+ readonly required: false;
43
+ readonly description: "Contexts this backs up with more evidence, as type:name.";
44
+ }, {
45
+ readonly name: "contradicts";
46
+ readonly type: "list";
47
+ readonly required: false;
48
+ readonly description: "Contexts this supersedes, as type:name.";
49
+ }]>>;