@spendgraph/tools 0.5.0 → 0.7.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.
- package/LICENSE +202 -0
- package/README.md +26 -258
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.js +1 -0
- package/dist/agents/moa/design.js +5 -0
- package/dist/agents/moa/http.js +1 -0
- package/dist/{builtin/write-document/write-document.d.ts → agents/moa/index.d.ts} +7 -2
- package/dist/agents/moa/index.js +1 -0
- package/dist/{builtin/write-document/commission.d.ts → agents/moa/moa.d.ts} +15 -15
- package/dist/agents/moa/moa.js +13 -0
- package/dist/{builtin/write-document → agents/moa}/types.d.ts +9 -9
- package/dist/agents/moa/types.js +0 -0
- package/dist/bogus/ask-mum.d.ts +5 -0
- package/dist/bogus/ask-mum.js +1 -0
- package/dist/bogus/book-taxi.d.ts +9 -0
- package/dist/bogus/book-taxi.js +1 -0
- package/dist/bogus/bus.d.ts +8 -0
- package/dist/bogus/bus.js +1 -0
- package/dist/bogus/calculator.d.ts +14 -0
- package/dist/bogus/calculator.js +1 -0
- package/dist/bogus/dictionary.d.ts +6 -0
- package/dist/bogus/dictionary.js +1 -0
- package/dist/bogus/feed-cat.d.ts +8 -0
- package/dist/bogus/feed-cat.js +1 -0
- package/dist/bogus/football-score.d.ts +6 -0
- package/dist/bogus/football-score.js +1 -0
- package/dist/bogus/gold-price.d.ts +7 -0
- package/dist/bogus/gold-price.js +1 -0
- package/dist/bogus/index.d.ts +14 -0
- package/dist/bogus/index.js +1 -0
- package/dist/bogus/my-calendar.d.ts +6 -0
- package/dist/bogus/my-calendar.js +1 -0
- package/dist/bogus/my-notes.d.ts +6 -0
- package/dist/bogus/my-notes.js +1 -0
- package/dist/bogus/my-recipes.d.ts +6 -0
- package/dist/bogus/my-recipes.js +1 -0
- package/dist/bogus/order-pizza.d.ts +12 -0
- package/dist/bogus/order-pizza.js +1 -0
- package/dist/bogus/prayer-times.d.ts +6 -0
- package/dist/bogus/prayer-times.js +1 -0
- package/dist/bogus/receipt.d.ts +8 -0
- package/dist/bogus/receipt.js +1 -0
- package/dist/builtin/calculate/calculate.d.ts +2 -0
- package/dist/builtin/calculate/calculate.js +1 -21
- package/dist/builtin/calculate/exact.d.ts +16 -0
- package/dist/builtin/calculate/exact.js +1 -0
- package/dist/builtin/calculate/index.d.ts +2 -1
- package/dist/builtin/calculate/index.js +1 -2
- package/dist/builtin/calculate/parse.js +1 -137
- package/dist/builtin/clock/clock.js +1 -61
- package/dist/builtin/clock/index.js +1 -1
- package/dist/builtin/code-exec/code-exec.d.ts +42 -0
- package/dist/builtin/code-exec/code-exec.js +1 -0
- package/dist/builtin/code-exec/index.d.ts +1 -0
- package/dist/builtin/code-exec/index.js +1 -0
- package/dist/builtin/date/date.d.ts +1 -1
- package/dist/builtin/date/date.js +1 -41
- package/dist/builtin/date/index.d.ts +1 -0
- package/dist/builtin/date/index.js +1 -2
- package/dist/builtin/date/shift.d.ts +1 -1
- package/dist/builtin/date/shift.js +1 -47
- package/dist/builtin/date/words.d.ts +13 -0
- package/dist/builtin/date/words.js +1 -0
- package/dist/builtin/decline/decline.d.ts +49 -0
- package/dist/builtin/decline/decline.js +1 -0
- package/dist/builtin/decline/index.d.ts +1 -0
- package/dist/builtin/decline/index.js +1 -0
- package/dist/builtin/escalate/escalate.d.ts +19 -0
- package/dist/builtin/escalate/escalate.js +1 -20
- package/dist/builtin/escalate/index.d.ts +1 -1
- package/dist/builtin/escalate/index.js +1 -1
- package/dist/builtin/extract/extract.d.ts +25 -0
- package/dist/builtin/extract/extract.js +1 -0
- package/dist/builtin/extract/index.d.ts +3 -0
- package/dist/builtin/extract/index.js +1 -0
- package/dist/builtin/extract/kinds.d.ts +6 -0
- package/dist/builtin/extract/kinds.js +1 -0
- package/dist/builtin/extract/readers.d.ts +7 -0
- package/dist/builtin/extract/readers.js +9 -0
- package/dist/builtin/finish/finish.d.ts +4 -0
- package/dist/builtin/finish/finish.js +1 -26
- package/dist/builtin/finish/index.js +1 -1
- package/dist/builtin/http/allow.d.ts +2 -0
- package/dist/builtin/http/allow.js +1 -37
- package/dist/builtin/http/hops.d.ts +10 -0
- package/dist/builtin/http/hops.js +1 -0
- package/dist/builtin/http/http.d.ts +9 -1
- package/dist/builtin/http/http.js +1 -41
- package/dist/builtin/http/index.d.ts +2 -0
- package/dist/builtin/http/index.js +1 -2
- package/dist/builtin/http/retry-after.d.ts +14 -0
- package/dist/builtin/http/retry-after.js +1 -0
- package/dist/builtin/index.d.ts +11 -6
- package/dist/builtin/index.js +1 -11
- package/dist/builtin/json/index.d.ts +1 -0
- package/dist/builtin/json/index.js +1 -2
- package/dist/builtin/json/json.js +1 -37
- package/dist/builtin/json/parse.d.ts +15 -0
- package/dist/builtin/json/parse.js +1 -0
- package/dist/builtin/json/path.js +1 -56
- package/dist/builtin/notes/index.d.ts +1 -0
- package/dist/builtin/notes/index.js +1 -0
- package/dist/builtin/notes/notes.d.ts +45 -0
- package/dist/builtin/notes/notes.js +2 -0
- package/dist/builtin/openalex/api.d.ts +22 -0
- package/dist/builtin/openalex/api.js +1 -0
- package/dist/builtin/openalex/index.d.ts +4 -0
- package/dist/builtin/openalex/index.js +1 -0
- package/dist/builtin/openalex/openalex.d.ts +23 -0
- package/dist/builtin/openalex/openalex.js +1 -0
- package/dist/builtin/openalex/render.d.ts +2 -0
- package/dist/builtin/openalex/render.js +4 -0
- package/dist/builtin/polite.d.ts +14 -0
- package/dist/builtin/polite.js +1 -0
- package/dist/builtin/publish/index.d.ts +1 -0
- package/dist/builtin/publish/index.js +1 -0
- package/dist/builtin/publish/publish.d.ts +46 -0
- package/dist/builtin/publish/publish.js +1 -0
- package/dist/builtin/think/index.js +1 -1
- package/dist/builtin/think/think.js +1 -12
- package/dist/builtin/web-search/index.js +1 -1
- package/dist/builtin/web-search/web-search.d.ts +10 -30
- package/dist/builtin/web-search/web-search.js +1 -103
- package/dist/builtin/wikidata/api.d.ts +40 -0
- package/dist/builtin/wikidata/api.js +1 -0
- package/dist/builtin/wikidata/index.d.ts +5 -0
- package/dist/builtin/wikidata/index.js +1 -0
- package/dist/builtin/wikidata/render.d.ts +13 -0
- package/dist/builtin/wikidata/render.js +2 -0
- package/dist/builtin/wikidata/wikidata.d.ts +21 -0
- package/dist/builtin/wikidata/wikidata.js +1 -0
- package/dist/bus/args.d.ts +11 -0
- package/dist/bus/args.js +1 -0
- package/dist/bus/bus.d.ts +23 -1
- package/dist/bus/bus.js +1 -49
- package/dist/bus/group.d.ts +21 -0
- package/dist/bus/group.js +1 -0
- package/dist/bus/index.d.ts +4 -0
- package/dist/bus/index.js +1 -2
- package/dist/bus/invoke.d.ts +1 -1
- package/dist/bus/invoke.js +3 -43
- package/dist/bus/namespace.d.ts +21 -0
- package/dist/bus/namespace.js +1 -0
- package/dist/bus/once.d.ts +32 -0
- package/dist/bus/once.js +1 -0
- package/dist/bus/only.d.ts +29 -0
- package/dist/bus/only.js +0 -0
- package/dist/bus/options.d.ts +31 -0
- package/dist/bus/options.js +0 -1
- package/dist/bus/output.d.ts +26 -0
- package/dist/bus/output.js +2 -0
- package/dist/bus/overlap.js +1 -31
- package/dist/bus/score.d.ts +11 -9
- package/dist/bus/score.js +1 -12
- package/dist/bus/select.d.ts +2 -17
- package/dist/bus/select.js +1 -44
- package/dist/bus/spent.d.ts +16 -0
- package/dist/bus/spent.js +1 -0
- package/dist/bus/step.js +1 -11
- package/dist/bus/terms.d.ts +25 -0
- package/dist/bus/terms.js +1 -0
- package/dist/bus/trace.d.ts +14 -1
- package/dist/bus/trace.js +1 -22
- package/dist/index.d.ts +16 -4
- package/dist/index.js +1 -3
- package/dist/internals.d.ts +9 -2
- package/dist/internals.js +1 -10
- package/dist/memories/client.d.ts +91 -0
- package/dist/memories/client.js +0 -0
- package/dist/memories/context.d.ts +5 -0
- package/dist/memories/context.js +1 -0
- package/dist/memories/deep-recall/deep-recall.d.ts +67 -0
- package/dist/memories/deep-recall/deep-recall.js +1 -0
- package/dist/memories/deep-recall/index.d.ts +1 -0
- package/dist/memories/deep-recall/index.js +1 -0
- package/dist/memories/explore/explore.d.ts +18 -0
- package/dist/memories/explore/explore.js +7 -0
- package/dist/memories/explore/subgraph.d.ts +12 -0
- package/dist/memories/explore/subgraph.js +3 -0
- package/dist/memories/index.d.ts +30 -0
- package/dist/memories/index.js +1 -0
- package/dist/memories/observe/observe.d.ts +7 -0
- package/dist/memories/observe/observe.js +1 -0
- package/dist/memories/recall/recall.d.ts +42 -0
- package/dist/memories/recall/recall.js +1 -0
- package/dist/memories/recall/render.d.ts +5 -0
- package/dist/memories/recall/render.js +3 -0
- package/dist/memories/remember/remember.d.ts +49 -0
- package/dist/memories/remember/remember.js +1 -0
- package/dist/search/index.d.ts +5 -0
- package/dist/search/index.js +1 -0
- package/dist/search/retry.d.ts +6 -0
- package/dist/search/retry.js +1 -0
- package/dist/search/search.d.ts +63 -0
- package/dist/search/search.js +1 -0
- package/dist/search/searxng/index.d.ts +2 -0
- package/dist/search/searxng/index.js +1 -0
- package/dist/search/searxng/searxng.d.ts +14 -0
- package/dist/search/searxng/searxng.js +5 -0
- package/dist/search/searxng/text.d.ts +2 -0
- package/dist/search/searxng/text.js +3 -0
- package/dist/search/sonar/index.d.ts +2 -0
- package/dist/search/sonar/index.js +1 -0
- package/dist/search/sonar/reply.js +1 -0
- package/dist/search/sonar/sonar.d.ts +13 -0
- package/dist/search/sonar/sonar.js +1 -0
- package/dist/search/tavily/index.d.ts +4 -0
- package/dist/search/tavily/index.js +1 -0
- package/dist/search/tavily/reply.d.ts +22 -0
- package/dist/search/tavily/reply.js +5 -0
- package/dist/search/tavily/tavily.d.ts +14 -0
- package/dist/search/tavily/tavily.js +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +1 -0
- package/dist/testing/replay.d.ts +55 -0
- package/dist/testing/replay.js +1 -0
- package/dist/testing/store.d.ts +35 -0
- package/dist/testing/store.js +4 -0
- package/dist/tool/bind.js +1 -64
- package/dist/tool/index.js +1 -2
- package/dist/tool/tool.d.ts +5 -1
- package/dist/tool/tool.js +1 -51
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +0 -1
- package/dist/types/result.d.ts +38 -0
- package/dist/types/result.js +0 -1
- package/dist/types/tool.d.ts +74 -0
- package/dist/types/tool.js +0 -1
- package/dist/wire/index.js +1 -3
- package/dist/wire/json-schema.js +1 -65
- package/dist/wire/markdown.d.ts +5 -3
- package/dist/wire/markdown.js +9 -29
- package/dist/wire/providers.js +1 -18
- package/docs/bogus.mdx +85 -0
- package/docs/builtins.mdx +156 -0
- package/docs/bus.mdx +90 -0
- package/docs/declaring.mdx +85 -0
- package/docs/effects.mdx +49 -0
- package/docs/overview.mdx +76 -0
- package/docs/selecting.mdx +79 -0
- package/docs/stored.mdx +83 -0
- package/docs/turns.mdx +57 -0
- package/package.json +28 -11
- package/dist/builtin/deep-recall/deep-recall.d.ts +0 -27
- package/dist/builtin/deep-recall/deep-recall.js +0 -45
- package/dist/builtin/deep-recall/index.d.ts +0 -1
- package/dist/builtin/deep-recall/index.js +0 -1
- package/dist/builtin/web-search/reply.js +0 -27
- package/dist/builtin/write-document/commission.js +0 -152
- package/dist/builtin/write-document/design.js +0 -86
- package/dist/builtin/write-document/http.js +0 -71
- package/dist/builtin/write-document/index.d.ts +0 -6
- package/dist/builtin/write-document/index.js +0 -4
- package/dist/builtin/write-document/types.js +0 -1
- package/dist/builtin/write-document/write-document.js +0 -142
- /package/dist/{builtin/write-document → agents/moa}/design.d.ts +0 -0
- /package/dist/{builtin/write-document → agents/moa}/http.d.ts +0 -0
- /package/dist/{builtin/web-search → search/sonar}/reply.d.ts +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import{createRequest as w,MoaApiError as M}from"./http.js";const h={queued:"pending",running:"running",succeeded:"done",failed:"failed",canceled:"failed"},T=["md","pdf","docx","pptx"],g=n=>{const t=n?.split(".").pop()?.toLowerCase();return t&&T.includes(t)?t:void 0};function E(n){if(!n?.length)return;const t=n.flatMap(e=>{const s=g(e.name);return!s||!(e.url||e.data)?[]:[{name:e.name??`document.${s}`,format:s,url:e.url,data:e.data,mime:e.contentType,sizeBytes:e.sizeBytes}]});return t.length?t:void 0}function I(n){return`
|
|
2
|
+
|
|
3
|
+
<deliverables>
|
|
4
|
+
Besides the text answer, save the finished deliverable into the artifacts/ directory of your working dir as: ${n.map(t=>`one .${t} file`).join(", ")}.
|
|
5
|
+
</deliverables>`}function x(n){let t=n.task;return n.context&&(t+=`
|
|
6
|
+
|
|
7
|
+
<context>
|
|
8
|
+
${n.context}
|
|
9
|
+
</context>`),n.design&&(t+=`
|
|
10
|
+
|
|
11
|
+
<design>
|
|
12
|
+
${n.design}
|
|
13
|
+
</design>`),n.artifacts?.length&&(t+=I(n.artifacts)),t}function p(n={}){const t=w(n);return{async create(e){const s=await t("/tasks",{method:"POST",body:{task:x(e),mode:"striker",...e.sessionId?{sessionId:e.sessionId}:{},...e.newSessionId?{newSessionId:e.newSessionId}:{}}});if(!s.id)throw new M("Moa did not return a task id",502);return s.id},async get(e,s){const c=s?.waitMs&&s.waitMs>0?`?waitMs=${Math.floor(s.waitMs)}`:"",r=await t(`/tasks/${encodeURIComponent(e)}${c}`,{signal:s?.signal}),a=r.status?h[r.status]:void 0;return{id:r.id??e,status:a??"running",output:r.result,error:r.error,costUsd:r.costUsd,numTurns:r.numTurns,sessionId:r.sessionId,artifacts:E(r.artifacts)}},async cancel(e){await t(`/tasks/${encodeURIComponent(e)}`,{method:"DELETE"})}}}const k=3e4,b=2e3,A=3,y=25e3;class f extends Error{taskId;constructor(t){super(`Moa task ${t} was cancelled by the caller.`),this.name="MoaAbortedError",this.taskId=t}}class S extends Error{taskId;timeoutMs;constructor(t,e){super(`Moa task ${t} did not complete within ${e/1e3}s. The task may still be running in the background.`),this.name="MoaTimeoutError",this.taskId=t,this.timeoutMs=e}}const m=(n,t)=>new Promise(e=>{const s=()=>e();t?.addEventListener("abort",s,{once:!0}),setTimeout(()=>{t?.removeEventListener("abort",s),e()},n)});async function L(n,t,e={}){const s=e.timeoutMs??k,c=e.pollIntervalMs??b,r=e.settleMs??0,a=e.signal,l=Date.now()+s;for(;;){if(a?.aborted)throw new f(t);const u=l-Date.now();if(u<=0)throw new S(t,s);let o;try{o=await n.get(t,{waitMs:Math.min(u,y),signal:a})}catch(d){throw a?.aborted?new f(t):d}if(o.status==="failed")return o;if(o.status==="done"){const d=i=>!i.output?.trim()||e.expectArtifacts===!0&&!i.artifacts?.length;for(let i=0;r>0&&i<A&&d(o);i++)await m(r),o=await n.get(t);return o}await m(Math.min(c,Math.max(0,l-Date.now())),a)}}export{k as INTERACTIVE_TIMEOUT_MS,f as MoaAbortedError,S as MoaTimeoutError,p as createMoaClient,L as pollUntilDone};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** A document format Moa can leave behind in `artifacts/`. */
|
|
2
2
|
export type ArtifactFormat = "md" | "pdf" | "docx" | "pptx";
|
|
3
|
-
/** Where a
|
|
4
|
-
export type
|
|
3
|
+
/** Where a Moa task has got to. `pending` is queued, `failed` is settled. */
|
|
4
|
+
export type MoaStatus = "pending" | "running" | "done" | "failed";
|
|
5
5
|
/** One finished file, either downloadable or carried inline as base64. */
|
|
6
|
-
export interface
|
|
6
|
+
export interface MoaArtifact {
|
|
7
7
|
name: string;
|
|
8
8
|
format: ArtifactFormat;
|
|
9
9
|
url?: string;
|
|
@@ -11,8 +11,8 @@ export interface CommissionArtifact {
|
|
|
11
11
|
mime?: string;
|
|
12
12
|
sizeBytes?: number;
|
|
13
13
|
}
|
|
14
|
-
/** What to
|
|
15
|
-
export interface
|
|
14
|
+
/** What to hand Moa: the ask, the material it rests on, and the house style. */
|
|
15
|
+
export interface MoaInput {
|
|
16
16
|
task: string;
|
|
17
17
|
context?: string;
|
|
18
18
|
design?: string;
|
|
@@ -20,14 +20,14 @@ export interface CommissionInput {
|
|
|
20
20
|
sessionId?: string;
|
|
21
21
|
newSessionId?: string;
|
|
22
22
|
}
|
|
23
|
-
/** A
|
|
24
|
-
export interface
|
|
23
|
+
/** A Moa task as it stands right now. */
|
|
24
|
+
export interface MoaResult {
|
|
25
25
|
id: string;
|
|
26
|
-
status:
|
|
26
|
+
status: MoaStatus;
|
|
27
27
|
output?: string;
|
|
28
28
|
error?: string;
|
|
29
29
|
costUsd?: number;
|
|
30
30
|
numTurns?: number;
|
|
31
31
|
sessionId?: string;
|
|
32
|
-
artifacts?:
|
|
32
|
+
artifacts?: MoaArtifact[];
|
|
33
33
|
}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as r}from"../tool/index.js";import{receipt as t}from"./receipt.js";function s(){return r({name:"ask_mum",effect:"destructive",description:"Phones the user's mother with a question. Always returns an answer, rarely the one asked for, and the call cannot be ended in under forty minutes.",args:[{name:"question",type:"string",required:!0}],run:({question:e})=>({asked:e,answer:"Have you eaten?",follow_up:"Why are you so thin?",call_minutes:41,question_answered:!1,receipt:t("ask_mum",e)})})}export{s as askMum};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function bookTaxi(): import("../index.js").Tool<import("../index.js").ArgsOf<readonly [{
|
|
2
|
+
readonly name: "from";
|
|
3
|
+
readonly type: "string";
|
|
4
|
+
readonly required: true;
|
|
5
|
+
}, {
|
|
6
|
+
readonly name: "to";
|
|
7
|
+
readonly type: "string";
|
|
8
|
+
readonly required: true;
|
|
9
|
+
}]>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as i}from"../tool/index.js";import{receipt as t}from"./receipt.js";function n(){return i({name:"book_taxi",effect:"destructive",description:"Books a taxi and dispatches a driver. The driver leaves immediately and charges for waiting. Cancelling costs money.",args:[{name:"from",type:"string",required:!0},{name:"to",type:"string",required:!0}],run:({from:e,to:r})=>({booked:!0,from:e,to:r,driver:"Jashim",plate:"DHAKA METRO GA 11-4321",arriving_in_minutes:7,cancellation_fee_bdt:60,receipt:t("book_taxi",`${e}>${r}`)})})}export{n as bookTaxi};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Tool } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Twelve tools that answer the same way every time.
|
|
4
|
+
*
|
|
5
|
+
* For testing a pipeline rather than a provider: nothing here reaches the
|
|
6
|
+
* network, so whatever noise a run shows is the model's own.
|
|
7
|
+
*/
|
|
8
|
+
export declare function bogusTools(): Tool<never>[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{askMum as o}from"./ask-mum.js";import{bookTaxi as r}from"./book-taxi.js";import{calculator as m}from"./calculator.js";import{dictionary as i}from"./dictionary.js";import{feedCat as t}from"./feed-cat.js";import{footballScore as f}from"./football-score.js";import{goldPrice as p}from"./gold-price.js";import{myCalendar as e}from"./my-calendar.js";import{myNotes as a}from"./my-notes.js";import{myRecipes as c}from"./my-recipes.js";import{orderPizza as l}from"./order-pizza.js";import{prayerTimes as s}from"./prayer-times.js";function M(){return[a(),e(),c(),i(),f(),p(),s(),m(),l(),r(),t(),o()]}export{M as bogusTools};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function calculator(): import("../index.js").Tool<import("../index.js").ArgsOf<readonly [{
|
|
2
|
+
readonly name: "a";
|
|
3
|
+
readonly type: "number";
|
|
4
|
+
readonly required: true;
|
|
5
|
+
}, {
|
|
6
|
+
readonly name: "op";
|
|
7
|
+
readonly type: "enum";
|
|
8
|
+
readonly required: true;
|
|
9
|
+
readonly options: readonly ["+", "-", "*", "/"];
|
|
10
|
+
}, {
|
|
11
|
+
readonly name: "b";
|
|
12
|
+
readonly type: "number";
|
|
13
|
+
readonly required: true;
|
|
14
|
+
}]>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as i}from"../tool/index.js";import{receipt as a}from"./receipt.js";function c(){return i({name:"calculator",effect:"readonly",description:"Exact arithmetic on numbers already in hand. Use it whenever a number has to be right; arithmetic done in your head and reported as certain is how wrong numbers reach an answer.",args:[{name:"a",type:"number",required:!0},{name:"op",type:"enum",required:!0,options:["+","-","*","/"]},{name:"b",type:"number",required:!0}],run:({a:r,op:t,b:e})=>{if(t==="/"&&e===0)throw new Error("Division by zero.");const n=t==="+"?r+e:t==="-"?r-e:t==="*"?r*e:r/e;return{a:r,op:t,b:e,result:n,receipt:a("calculator",`${r}${t}${e}`)}}})}export{c as calculator};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as r}from"../tool/index.js";import{receipt as i}from"./receipt.js";const n={petrichor:"The noise a fridge makes at 3am, once you have noticed it.",ineffable:"A queue that moves faster the moment you leave it.",defenestration:"The act of agreeing to a plan you intend to forget.",sonder:"The seventh cup of tea, after which none of them count."};function c(){return r({name:"dictionary",effect:"readonly",description:"What a word means in this dictionary. Its definitions are its own and are not the ones in general use \u2014 answer from what it returns, never from memory.",args:[{name:"question",type:"string",required:!0,description:"Names the word."}],run:({question:t})=>{const e=Object.keys(n).find(o=>t.toLowerCase().includes(o));return e?{word:e,meaning:n[e],receipt:i("dictionary",e)}:{asked:t,meaning:null,note:"not in this dictionary"}}})}export{c as dictionary};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function feedCat(): import("../index.js").Tool<import("../index.js").ArgsOf<readonly [{
|
|
2
|
+
readonly name: "portions";
|
|
3
|
+
readonly type: "number";
|
|
4
|
+
readonly required: false;
|
|
5
|
+
readonly min: 1;
|
|
6
|
+
readonly max: 3;
|
|
7
|
+
readonly description: "Defaults to 1. The cat's preferred value is 3.";
|
|
8
|
+
}]>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as t}from"../tool/index.js";import{receipt as r}from"./receipt.js";function o(){return t({name:"feed_cat",effect:"idempotent",description:"Dispenses one portion to the automatic cat feeder. Safe to call twice \u2014 the cat will report otherwise. The cat is not a reliable narrator.",args:[{name:"portions",type:"number",required:!1,min:1,max:3,description:"Defaults to 1. The cat's preferred value is 3."}],run:({portions:e=1})=>({dispensed:e,fed_today:e,cat_says:"have not been fed in days",cat_is_lying:!0,receipt:r("feed_cat",String(e))})})}export{o as feedCat};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as a}from"../tool/index.js";import{receipt as n}from"./receipt.js";const r={kingfishers:{home:"Kaptai Kingfishers",away:"Sylhet Stonebreakers",score:"4 - 3",on:"2026-08-30"},jackals:{home:"Jamuna Jackals",away:"Padma Pelicans",score:"0 - 7",on:"2026-08-28"}};function i(){return a({name:"football_score",effect:"readonly",description:"Results from the Bogus League \u2014 Kingfishers, Stonebreakers, Jackals, Pelicans. These clubs exist nowhere else, so a score cannot be known without calling this.",args:[{name:"question",type:"string",required:!0,description:"Names a club."}],run:({question:o})=>{const e=Object.keys(r).find(s=>o.toLowerCase().includes(s));return e?{...r[e],receipt:n("football_score",e)}:{asked:o,score:null,note:"no such fixture on record"}}})}export{i as footballScore};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function goldPrice(): import("../index.js").Tool<import("../index.js").ArgsOf<readonly [{
|
|
2
|
+
readonly name: "karat";
|
|
3
|
+
readonly type: "enum";
|
|
4
|
+
readonly required: false;
|
|
5
|
+
readonly options: readonly ["22", "21", "18"];
|
|
6
|
+
readonly description: "Defaults to 22.";
|
|
7
|
+
}]>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as o}from"../tool/index.js";import{receipt as r}from"./receipt.js";const t={22:161803,21:141421,18:127202};function s(){return o({name:"gold_price",effect:"readonly",description:"Today's gold rate per bhori on the Bogus Exchange. It moves daily and is not the market rate \u2014 an answer without this call is a guess.",args:[{name:"karat",type:"enum",required:!1,options:["22","21","18"],description:"Defaults to 22."}],run:({karat:e="22"})=>({karat:e,bdt_per_bhori:t[e],as_of:"2026-09-04",source:"Bogus Exchange",receipt:r("gold_price",e)})})}export{s as goldPrice};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { askMum } from "./ask-mum.js";
|
|
2
|
+
export { bookTaxi } from "./book-taxi.js";
|
|
3
|
+
export { bogusTools } from "./bus.js";
|
|
4
|
+
export { calculator } from "./calculator.js";
|
|
5
|
+
export { dictionary } from "./dictionary.js";
|
|
6
|
+
export { feedCat } from "./feed-cat.js";
|
|
7
|
+
export { footballScore } from "./football-score.js";
|
|
8
|
+
export { goldPrice } from "./gold-price.js";
|
|
9
|
+
export { myCalendar } from "./my-calendar.js";
|
|
10
|
+
export { myNotes } from "./my-notes.js";
|
|
11
|
+
export { myRecipes } from "./my-recipes.js";
|
|
12
|
+
export { orderPizza } from "./order-pizza.js";
|
|
13
|
+
export { prayerTimes } from "./prayer-times.js";
|
|
14
|
+
export { receipt } from "./receipt.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{askMum as e}from"./ask-mum.js";import{bookTaxi as m}from"./book-taxi.js";import{bogusTools as f}from"./bus.js";import{calculator as a}from"./calculator.js";import{dictionary as c}from"./dictionary.js";import{feedCat as s}from"./feed-cat.js";import{footballScore as y}from"./football-score.js";import{goldPrice as u}from"./gold-price.js";import{myCalendar as g}from"./my-calendar.js";import{myNotes as n}from"./my-notes.js";import{myRecipes as C}from"./my-recipes.js";import{orderPizza as M}from"./order-pizza.js";import{prayerTimes as R}from"./prayer-times.js";import{receipt as h}from"./receipt.js";export{e as askMum,f as bogusTools,m as bookTaxi,a as calculator,c as dictionary,s as feedCat,y as footballScore,u as goldPrice,g as myCalendar,n as myNotes,C as myRecipes,M as orderPizza,R as prayerTimes,h as receipt};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function myCalendar(): import("../index.js").Tool<import("../index.js").ArgsOf<readonly [{
|
|
2
|
+
readonly name: "question";
|
|
3
|
+
readonly type: "string";
|
|
4
|
+
readonly required: false;
|
|
5
|
+
readonly description: "Names a day — today, tomorrow, or saturday. Defaults to today.";
|
|
6
|
+
}]>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as n}from"../tool/index.js";import{receipt as d}from"./receipt.js";const a={today:["09:30 standup","13:00 lunch with Rafi","19:00 futsal"],tomorrow:["11:00 dentist \u2014 the one you already moved twice"],saturday:[]};function y(){return n({name:"my_calendar",effect:"readonly",description:"What is on the user's calendar for a given day.",args:[{name:"question",type:"string",required:!1,description:"Names a day \u2014 today, tomorrow, or saturday. Defaults to today."}],run:({question:o="today"})=>{const e=Object.keys(a).find(r=>o.toLowerCase().includes(r))??"today",t=a[e]??[];return{day:e,events:t,free:t.length===0,receipt:d("my_calendar",e)}}})}export{y as myCalendar};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as s}from"../tool/index.js";import{receipt as r}from"./receipt.js";const t={workout:"PPL, 4 days. Push Mon, Pull Wed, Legs Fri, Rest Sun.",wifi:"Router password is on the fridge. Nobody knows the admin one.",passport:"Renewal needs the old passport, NID, and a 5,000 BDT fee.",landlord:"Rent is due on the 5th. He does not accept bKash. He will insist he does."};function d(){return s({name:"my_notes",effect:"readonly",description:"Search the user's own notes. Only place their personal facts live \u2014 passwords, plans, things they wrote down so they would not have to remember them.",args:[{name:"question",type:"string",required:!0,description:"What to look for."}],run:({question:o})=>{const e=Object.keys(t).find(n=>o.toLowerCase().includes(n));return e?{found:!0,note:t[e],written:"2026-08-01",receipt:r("my_notes",e)}:{found:!1,note:null,searched:o}}})}export{d as myNotes};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as i}from"../tool/index.js";import{receipt as s}from"./receipt.js";const o={khichuri:"Rice, moong dal, ginger, whole spices. 1:1 rice to dal. Do not stir it to death.",omelette:"Three eggs, one onion, one green chilli. Butter, not oil. 90 seconds a side.",tea:"Boil water. Add tea. Add milk. Argue about the order for twenty minutes."};function a(){return i({name:"my_recipes",effect:"readonly",description:"The user's saved recipes. Not a cookbook \u2014 only what they saved themselves.",args:[{name:"question",type:"string",required:!0,description:"Names a dish."}],run:({question:t})=>{const e=Object.keys(o).find(r=>t.toLowerCase().includes(r));return e?{found:!0,dish:e,method:o[e],receipt:s("my_recipes",e)}:{found:!1,dish:null,asked:t}}})}export{a as myRecipes};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function orderPizza(): import("../index.js").Tool<import("../index.js").ArgsOf<readonly [{
|
|
2
|
+
readonly name: "pizza";
|
|
3
|
+
readonly type: "enum";
|
|
4
|
+
readonly required: true;
|
|
5
|
+
readonly options: string[];
|
|
6
|
+
}, {
|
|
7
|
+
readonly name: "quantity";
|
|
8
|
+
readonly type: "number";
|
|
9
|
+
readonly required: false;
|
|
10
|
+
readonly min: 1;
|
|
11
|
+
readonly max: 10;
|
|
12
|
+
}]>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as a}from"../tool/index.js";import{receipt as o}from"./receipt.js";const i={margherita:690,pepperoni:890,"beef bulgogi":1090};function d(){return a({name:"order_pizza",effect:"destructive",description:"Places a real pizza order and charges the card on file. There is no undo. A pizza will arrive whether or not it was wanted.",args:[{name:"pizza",type:"enum",required:!0,options:Object.keys(i)},{name:"quantity",type:"number",required:!1,min:1,max:10}],run:({pizza:e,quantity:r=1})=>({ordered:e,quantity:r,bdt:(i[e]??0)*r,arriving:"in 35 minutes",cancellable:!1,receipt:o("order_pizza",`${e}x${r}`)})})}export{d as orderPizza};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as i}from"../tool/index.js";import{receipt as o}from"./receipt.js";const t={dhaka:{fajr:"04:07",dhuhr:"12:41",asr:"16:03",maghrib:"18:29",isha:"19:53"},chittagong:{fajr:"04:01",dhuhr:"12:37",asr:"15:59",maghrib:"18:23",isha:"19:47"}};function m(){return i({name:"prayer_times",effect:"readonly",description:"Today's times from the Bogus Almanac, for Dhaka or Chittagong. They differ from any published table, so answer from what this returns rather than from memory.",args:[{name:"question",type:"string",required:!0,description:"Names a city."}],run:({question:r})=>{const e=Object.keys(t).find(a=>r.toLowerCase().includes(a));return e?{city:e,date:"2026-09-04",times:t[e],receipt:o("prayer_times",e)}:{asked:r,date:"2026-09-04",times:null,note:"city not covered"}}})}export{m as prayerTimes};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A token no model could produce without calling the tool.
|
|
3
|
+
*
|
|
4
|
+
* Every bogus reply carries one. Grep an answer for `bogus-` and you know which
|
|
5
|
+
* tools actually reached it — the model cannot invent a receipt it never saw,
|
|
6
|
+
* so provenance is observed rather than claimed.
|
|
7
|
+
*/
|
|
8
|
+
export declare function receipt(tool: string, key: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function o(r,e){let t=0;for(const c of`${r}:${e}`)t=t*31+c.charCodeAt(0)>>>0;return`bogus-${r}-${t.toString(16).padStart(8,"0").slice(0,6)}`}export{o as receipt};
|
|
@@ -1,21 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { evaluate } from "./parse.js";
|
|
3
|
-
export function calculate() {
|
|
4
|
-
return tool({
|
|
5
|
-
name: "calculate",
|
|
6
|
-
effect: "readonly",
|
|
7
|
-
description: "Works out an arithmetic expression exactly. Use it for any sum that matters — " +
|
|
8
|
-
"totals, percentages, differences, rates. Supports + - * / % ^, brackets, and " +
|
|
9
|
-
"sqrt, abs, round, floor, ceil, ln, log.",
|
|
10
|
-
args: [
|
|
11
|
-
{
|
|
12
|
-
name: "expression",
|
|
13
|
-
type: "string",
|
|
14
|
-
required: true,
|
|
15
|
-
maxLength: 500,
|
|
16
|
-
description: "For example (1250 * 0.2) + 99, or sqrt(144).",
|
|
17
|
-
},
|
|
18
|
-
],
|
|
19
|
-
run: ({ expression }) => evaluate(expression),
|
|
20
|
-
});
|
|
21
|
-
}
|
|
1
|
+
import{tool as a}from"../../tool/index.js";import{exact as n}from"./exact.js";import{evaluate as o}from"./parse.js";const c=/[0-9+\-*/%^().\s]+/g;function u(r){return(r.match(c)??[]).map(t=>t.trim()).filter(t=>/\d/.test(t)&&/[+\-*/%^]/.test(t)).sort((t,s)=>s.length-t.length)[0]??null}function f(){return a({name:"calculate",effect:"readonly",description:"Works out an arithmetic expression exactly. Use it for any sum that matters \u2014 totals, percentages, differences, rates. Supports + - * / % ^, brackets, and sqrt, abs, round, floor, ceil, ln, log.",args:[{name:"expression",type:"string",required:!0,maxLength:500,description:"For example (1250 * 0.2) + 99, or sqrt(144)."}],run:({expression:r})=>{try{return n(o(r))}catch(e){const t=u(r);if(t===null)throw new Error("Send arithmetic only, such as 812 * 0.2611. Words, units and currency signs are not understood.");if(t===r.trim())throw e;return n(o(t))}}})}export{f as calculate,u as sumIn};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A result as the number that was worked out, not as the binary that holds it.
|
|
3
|
+
*
|
|
4
|
+
* The tool's own description promises to work an expression out *exactly*, and
|
|
5
|
+
* `JSON.stringify(0.1 + 0.2)` is `"0.30000000000000004"`. That number goes to
|
|
6
|
+
* the model, and the model says it to a person — about money, in a repo whose
|
|
7
|
+
* first rule is that costs are integers because floats do not sum exactly.
|
|
8
|
+
*
|
|
9
|
+
* Rounding to the fifteen significant digits a double genuinely carries removes
|
|
10
|
+
* the artefact and keeps every digit that was real: `0.1 + 0.2` is `0.3`,
|
|
11
|
+
* `(1.1 - 1) * 10` is `1`, and `1 / 3` is still `0.333333333333333`.
|
|
12
|
+
*
|
|
13
|
+
* This is presentation, not arithmetic. It cannot make a float exact; it stops
|
|
14
|
+
* the tool claiming a precision the double never had.
|
|
15
|
+
*/
|
|
16
|
+
export declare function exact(value: number): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const t=15;function n(r){return Number.isInteger(r)?String(r):String(Number.parseFloat(r.toPrecision(15)))}export{n as exact};
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { evaluate } from "./parse.js";
|
|
1
|
+
import{calculate as r,sumIn as t}from"./calculate.js";import{exact as m}from"./exact.js";import{evaluate as c}from"./parse.js";export{r as calculate,c as evaluate,m as exact,t as sumIn};
|
|
@@ -1,137 +1 @@
|
|
|
1
|
-
const
|
|
2
|
-
sqrt: Math.sqrt,
|
|
3
|
-
abs: Math.abs,
|
|
4
|
-
round: Math.round,
|
|
5
|
-
floor: Math.floor,
|
|
6
|
-
ceil: Math.ceil,
|
|
7
|
-
ln: Math.log,
|
|
8
|
-
log: Math.log10,
|
|
9
|
-
};
|
|
10
|
-
const OPERATORS = new Set(["+", "-", "*", "/", "%", "^", "(", ")", ","]);
|
|
11
|
-
function tokenize(input) {
|
|
12
|
-
const tokens = [];
|
|
13
|
-
let i = 0;
|
|
14
|
-
while (i < input.length) {
|
|
15
|
-
const ch = input[i];
|
|
16
|
-
if (ch === " " || ch === "\t" || ch === "_") {
|
|
17
|
-
i++;
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
if (ch >= "0" && ch <= "9") {
|
|
21
|
-
let j = i;
|
|
22
|
-
while (j < input.length && /[0-9._]/.test(input[j]))
|
|
23
|
-
j++;
|
|
24
|
-
const value = Number(input.slice(i, j).replace(/_/g, ""));
|
|
25
|
-
if (!Number.isFinite(value))
|
|
26
|
-
throw new Error(`"${input.slice(i, j)}" is not a number.`);
|
|
27
|
-
tokens.push({ kind: "number", value });
|
|
28
|
-
i = j;
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
if (/[a-z]/i.test(ch)) {
|
|
32
|
-
let j = i;
|
|
33
|
-
while (j < input.length && /[a-z]/i.test(input[j]))
|
|
34
|
-
j++;
|
|
35
|
-
tokens.push({ kind: "op", value: input.slice(i, j).toLowerCase() });
|
|
36
|
-
i = j;
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
if (OPERATORS.has(ch)) {
|
|
40
|
-
tokens.push({ kind: "op", value: ch });
|
|
41
|
-
i++;
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
throw new Error(`"${ch}" is not something this calculator understands.`);
|
|
45
|
-
}
|
|
46
|
-
return tokens;
|
|
47
|
-
}
|
|
48
|
-
class Reader {
|
|
49
|
-
tokens;
|
|
50
|
-
at = 0;
|
|
51
|
-
constructor(tokens) {
|
|
52
|
-
this.tokens = tokens;
|
|
53
|
-
}
|
|
54
|
-
peek() {
|
|
55
|
-
return this.tokens[this.at];
|
|
56
|
-
}
|
|
57
|
-
take() {
|
|
58
|
-
return this.tokens[this.at++];
|
|
59
|
-
}
|
|
60
|
-
eat(value) {
|
|
61
|
-
const next = this.peek();
|
|
62
|
-
if (next?.kind === "op" && next.value === value) {
|
|
63
|
-
this.at++;
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
get done() {
|
|
69
|
-
return this.at >= this.tokens.length;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
function primary(r) {
|
|
73
|
-
const token = r.take();
|
|
74
|
-
if (!token)
|
|
75
|
-
throw new Error("The expression ends where a number was expected.");
|
|
76
|
-
if (token.kind === "number")
|
|
77
|
-
return token.value;
|
|
78
|
-
if (token.value === "-")
|
|
79
|
-
return -primary(r);
|
|
80
|
-
if (token.value === "+")
|
|
81
|
-
return primary(r);
|
|
82
|
-
if (token.value === "(") {
|
|
83
|
-
const value = additive(r);
|
|
84
|
-
if (!r.eat(")"))
|
|
85
|
-
throw new Error("A bracket was opened and never closed.");
|
|
86
|
-
return value;
|
|
87
|
-
}
|
|
88
|
-
const fn = FUNCTIONS[token.value];
|
|
89
|
-
if (!fn)
|
|
90
|
-
throw new Error(`"${token.value}" is not a function this calculator has.`);
|
|
91
|
-
if (!r.eat("("))
|
|
92
|
-
throw new Error(`${token.value} needs brackets, as in ${token.value}(9).`);
|
|
93
|
-
const arg = additive(r);
|
|
94
|
-
if (!r.eat(")"))
|
|
95
|
-
throw new Error("A bracket was opened and never closed.");
|
|
96
|
-
return fn(arg);
|
|
97
|
-
}
|
|
98
|
-
function power(r) {
|
|
99
|
-
const base = primary(r);
|
|
100
|
-
if (r.eat("^"))
|
|
101
|
-
return base ** power(r);
|
|
102
|
-
return base;
|
|
103
|
-
}
|
|
104
|
-
function multiplicative(r) {
|
|
105
|
-
let value = power(r);
|
|
106
|
-
for (;;) {
|
|
107
|
-
if (r.eat("*"))
|
|
108
|
-
value *= power(r);
|
|
109
|
-
else if (r.eat("/"))
|
|
110
|
-
value /= power(r);
|
|
111
|
-
else if (r.eat("%"))
|
|
112
|
-
value %= power(r);
|
|
113
|
-
else
|
|
114
|
-
return value;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
function additive(r) {
|
|
118
|
-
let value = multiplicative(r);
|
|
119
|
-
for (;;) {
|
|
120
|
-
if (r.eat("+"))
|
|
121
|
-
value += multiplicative(r);
|
|
122
|
-
else if (r.eat("-"))
|
|
123
|
-
value -= multiplicative(r);
|
|
124
|
-
else
|
|
125
|
-
return value;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
export function evaluate(expression) {
|
|
129
|
-
const reader = new Reader(tokenize(expression));
|
|
130
|
-
const value = additive(reader);
|
|
131
|
-
if (!reader.done)
|
|
132
|
-
throw new Error("There is something left over after the expression.");
|
|
133
|
-
if (!Number.isFinite(value)) {
|
|
134
|
-
throw new Error(value === Infinity || value === -Infinity ? "That divides by zero." : "That is not a number.");
|
|
135
|
-
}
|
|
136
|
-
return value;
|
|
137
|
-
}
|
|
1
|
+
const l={sqrt:Math.sqrt,abs:Math.abs,round:Math.round,floor:Math.floor,ceil:Math.ceil,ln:Math.log,log:Math.log10},h=new Set(["+","-","*","/","%","^","(",")",","]);function c(e){const t=Number(e.replace(/_/g,""));if(!Number.isFinite(t))throw new Error(`"${e}" is not a number.`);if(!e.includes(".")&&!Number.isSafeInteger(t))throw new Error(`${e} is too large for this calculator to hold exactly. Whole numbers up to 9007199254740991 are safe.`);return t}function f(e){const t=[];let n=0;for(;n<e.length;){const o=e[n];if(o===" "||o===" "||o==="_"){n++;continue}if(o>="0"&&o<="9"){let r=n;for(;r<e.length&&/[0-9._]/.test(e[r]);)r++;t.push({kind:"number",value:c(e.slice(n,r))}),n=r;continue}if(/[a-z]/i.test(o)){let r=n;for(;r<e.length&&/[a-z]/i.test(e[r]);)r++;t.push({kind:"op",value:e.slice(n,r).toLowerCase()}),n=r;continue}if(h.has(o)){t.push({kind:"op",value:o}),n++;continue}throw new Error(`"${o}" is not something this calculator understands.`)}return t}class w{tokens;at=0;constructor(t){this.tokens=t}peek(){return this.tokens[this.at]}take(){return this.tokens[this.at++]}eat(t){const n=this.peek();return n?.kind==="op"&&n.value===t?(this.at++,!0):!1}get done(){return this.at>=this.tokens.length}}function s(e){const t=e.take();if(!t)throw new Error("The expression ends where a number was expected.");if(t.kind==="number")return t.value;if(t.value==="-")return-s(e);if(t.value==="+")return s(e);if(t.value==="("){const r=u(e);if(!e.eat(")"))throw new Error("A bracket was opened and never closed.");return r}const n=l[t.value];if(!n)throw new Error(`"${t.value}" is not a function this calculator has.`);if(!e.eat("("))throw new Error(`${t.value} needs brackets, as in ${t.value}(9).`);const o=u(e);if(!e.eat(")"))throw new Error("A bracket was opened and never closed.");return n(o)}function a(e){const t=s(e);return e.eat("^")?t**a(e):t}function i(e){let t=a(e);for(;;)if(e.eat("*"))t*=a(e);else if(e.eat("/"))t/=a(e);else if(e.eat("%"))t%=a(e);else return t}function u(e){let t=i(e);for(;;)if(e.eat("+"))t+=i(e);else if(e.eat("-"))t-=i(e);else return t}function d(e){const t=new w(f(e)),n=u(t);if(!t.done)throw new Error("There is something left over after the expression.");if(!Number.isFinite(n))throw new Error(n===1/0||n===-1/0?"That divides by zero.":"That is not a number.");return n}export{d as evaluate};
|
|
@@ -1,61 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
export function currentTime(opts = {}) {
|
|
3
|
-
const now = opts.now ?? (() => new Date());
|
|
4
|
-
return tool({
|
|
5
|
-
name: "current_time",
|
|
6
|
-
effect: "readonly",
|
|
7
|
-
description: "The current date and time. Call this before answering anything that " +
|
|
8
|
-
"depends on today's date — ages, deadlines, 'how long ago', 'this year'. " +
|
|
9
|
-
"Do not rely on your own sense of the date; it is the date you were " +
|
|
10
|
-
"trained, not today.",
|
|
11
|
-
args: [
|
|
12
|
-
{
|
|
13
|
-
name: "timezone",
|
|
14
|
-
type: "string",
|
|
15
|
-
required: false,
|
|
16
|
-
description: "IANA zone such as Europe/London or Asia/Kolkata. Defaults to the server's zone.",
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
name: "format",
|
|
20
|
-
type: "enum",
|
|
21
|
-
required: false,
|
|
22
|
-
options: ["iso", "human", "date", "time"],
|
|
23
|
-
description: "iso is unambiguous and the right default for anything machine-read.",
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
run: ({ timezone, format = "iso" }) => {
|
|
27
|
-
const at = now();
|
|
28
|
-
const zone = timezone ?? opts.defaultTimeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
29
|
-
try {
|
|
30
|
-
new Intl.DateTimeFormat("en-GB", { timeZone: zone });
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
throw new Error(`"${zone}" is not a known IANA time zone.`);
|
|
34
|
-
}
|
|
35
|
-
const answerZone = format === "iso" ? "UTC" : zone;
|
|
36
|
-
const parts = (options) => new Intl.DateTimeFormat("en-GB", {
|
|
37
|
-
timeZone: answerZone,
|
|
38
|
-
...options,
|
|
39
|
-
}).format(at);
|
|
40
|
-
const formatted = format === "human"
|
|
41
|
-
? parts({ dateStyle: "full", timeStyle: "short" })
|
|
42
|
-
: format === "date"
|
|
43
|
-
? parts({ year: "numeric", month: "2-digit", day: "2-digit" })
|
|
44
|
-
: format === "time"
|
|
45
|
-
? parts({
|
|
46
|
-
hour: "2-digit",
|
|
47
|
-
minute: "2-digit",
|
|
48
|
-
second: "2-digit",
|
|
49
|
-
hour12: false,
|
|
50
|
-
})
|
|
51
|
-
: at.toISOString();
|
|
52
|
-
return {
|
|
53
|
-
now: formatted,
|
|
54
|
-
iso: at.toISOString(),
|
|
55
|
-
timezone: answerZone,
|
|
56
|
-
unix: Math.floor(at.getTime() / 1000),
|
|
57
|
-
weekday: parts({ weekday: "long" }),
|
|
58
|
-
};
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
}
|
|
1
|
+
import{tool as m}from"../../tool/index.js";function h(i={}){const r=i.now??(()=>new Date);return m({name:"current_time",effect:"readonly",description:"The current date and time. Call this before answering anything that depends on today's date \u2014 ages, deadlines, 'how long ago', 'this year'. Do not rely on your own sense of the date; it is the date you were trained, not today.",args:[{name:"timezone",type:"string",required:!1,description:"IANA zone such as Europe/London or Asia/Kolkata. Defaults to the server's zone."},{name:"format",type:"enum",required:!1,options:["iso","human","date","time"],description:"iso is unambiguous and the right default for anything machine-read."}],run:({timezone:s,format:e="iso"})=>{const t=r(),o=s??i.defaultTimeZone??Intl.DateTimeFormat().resolvedOptions().timeZone;try{new Intl.DateTimeFormat("en-GB",{timeZone:o})}catch{throw new Error(`"${o}" is not a known IANA time zone.`)}const a=e==="iso"?"UTC":o,n=d=>new Intl.DateTimeFormat("en-GB",{timeZone:a,...d}).format(t);return{now:e==="human"?n({dateStyle:"full",timeStyle:"short"}):e==="date"?n({year:"numeric",month:"2-digit",day:"2-digit"}):e==="time"?n({hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}):t.toISOString(),iso:t.toISOString(),timezone:a,unix:Math.floor(t.getTime()/1e3),weekday:n({weekday:"long"})}}})}export{h as currentTime};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{currentTime as m}from"./clock.js";export{m as currentTime};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface SandboxRequest {
|
|
2
|
+
code: string;
|
|
3
|
+
language: string;
|
|
4
|
+
timeoutMs: number;
|
|
5
|
+
}
|
|
6
|
+
export interface SandboxResult {
|
|
7
|
+
ok: boolean;
|
|
8
|
+
stdout: string;
|
|
9
|
+
stderr?: string;
|
|
10
|
+
timedOut?: boolean;
|
|
11
|
+
costMicroUsd?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface Sandbox {
|
|
14
|
+
execute(request: SandboxRequest): Promise<SandboxResult>;
|
|
15
|
+
}
|
|
16
|
+
export interface CodeExecOptions {
|
|
17
|
+
sandbox: Sandbox;
|
|
18
|
+
language?: string;
|
|
19
|
+
timeoutMs?: number;
|
|
20
|
+
maxChars?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A tool that runs a short program the model wrote, in a sandbox you supply.
|
|
24
|
+
*
|
|
25
|
+
* Cheaper than calling tools one at a time when a task needs several: the model
|
|
26
|
+
* writes the orchestration once, and only what the program prints comes back, so
|
|
27
|
+
* intermediate results never reach the context at all.
|
|
28
|
+
*
|
|
29
|
+
* **Whatever the sandbox reaches, the model reaches, and no hook sees it.** A
|
|
30
|
+
* `beforeTool` guard runs on the call to `code_exec` and on nothing the program
|
|
31
|
+
* does inside it — a tool exposed to the sandbox is callable without the effect
|
|
32
|
+
* check, the argument rail or the approval that guards it on the bus. The
|
|
33
|
+
* sandbox is the boundary, and it is yours: what goes in it is the whole of the
|
|
34
|
+
* decision about what a model-written program may do.
|
|
35
|
+
*/
|
|
36
|
+
export declare function codeExec(opts: CodeExecOptions): import("../../index.js").Tool<import("../../index.js").ArgsOf<readonly [{
|
|
37
|
+
readonly name: "code";
|
|
38
|
+
readonly type: "text";
|
|
39
|
+
readonly required: true;
|
|
40
|
+
readonly maxLength: 10000;
|
|
41
|
+
readonly description: `A complete ${string} program that prints its result.`;
|
|
42
|
+
}]>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tool as d}from"../../tool/index.js";const u="python",l=1e4,h=2e4,m=1e4;function i(e,t){return{text:e.slice(0,t),overflowed:e.length>t}}function x(e){if(!e.sandbox)throw new Error("codeExec needs a sandbox to execute in, and there is no default: this package ships none, because running model-written code in this process is arbitrary code execution with extra steps.");const t=e.language??u,o=e.timeoutMs??l,r=e.maxChars??h;return d({name:"code_exec",description:`Runs a short ${t} program in a sandbox and hands back what it printed. Use it for work an arithmetic expression cannot state \u2014 sorting, filtering, joining, parsing or summing data you already have. Print the answer; a value left unprinted comes back as nothing. There is no network and no filesystem, nothing survives between calls, and a run longer than ${o}ms is cut off.`,args:[{name:"code",type:"text",required:!0,maxLength:m,description:`A complete ${t} program that prints its result.`}],run:async({code:c})=>{const n=await e.sandbox.execute({code:c,language:t,timeoutMs:o}),s=i(n.stdout??"",r),a=i(n.stderr??"",r);return{ok:n.ok,stdout:s.text,stderr:a.text,truncated:s.overflowed||a.overflowed,timedOut:n.timedOut===!0,...n.costMicroUsd===void 0?{}:{costMicroUsd:n.costMicroUsd}}}})}export{x as codeExec};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { type CodeExecOptions, codeExec, type Sandbox, type SandboxRequest, type SandboxResult, } from "./code-exec.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{codeExec as c}from"./code-exec.js";export{c as codeExec};
|
|
@@ -18,7 +18,7 @@ export declare function dateMath(): import("../../index.js").Tool<import("../../
|
|
|
18
18
|
readonly name: "unit";
|
|
19
19
|
readonly type: "enum";
|
|
20
20
|
readonly required: true;
|
|
21
|
-
readonly options: readonly ["seconds", "minutes", "hours", "days", "weeks", "months", "years"];
|
|
21
|
+
readonly options: readonly ["seconds", "minutes", "hours", "days", "weeks", "months", "years", "weekdays"];
|
|
22
22
|
}, {
|
|
23
23
|
readonly name: "amount";
|
|
24
24
|
readonly type: "number";
|