@lunora/agent 1.0.0-alpha.1 → 1.0.0-alpha.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/channels.d.mts +33 -21
- package/dist/channels.d.ts +33 -21
- package/dist/channels.mjs +1 -181
- package/dist/component.d.mts +61 -56
- package/dist/component.d.ts +61 -56
- package/dist/component.mjs +2 -407
- package/dist/inbound.d.mts +23 -16
- package/dist/inbound.d.ts +23 -16
- package/dist/inbound.mjs +1 -32
- package/dist/index.d.mts +542 -409
- package/dist/index.d.ts +542 -409
- package/dist/index.mjs +1 -18
- package/dist/naming.d.mts +23 -10
- package/dist/naming.d.ts +23 -10
- package/dist/naming.mjs +1 -8
- package/dist/packem_shared/AGENT_MODULE-M4D1EejI.mjs +1 -0
- package/dist/packem_shared/VoiceSessionDO-D238XrlM.mjs +1 -0
- package/dist/packem_shared/adaptMcpResult-CVlq-_TO.mjs +2 -0
- package/dist/packem_shared/agent-loop-CE_Q6bk9.mjs +3 -0
- package/dist/packem_shared/agentAsTool-CgZb6ycK.mjs +1 -0
- package/dist/packem_shared/base64-5eyBfWO3.mjs +1 -0
- package/dist/packem_shared/braintrustTelemetry-Byne8uPK.mjs +1 -0
- package/dist/packem_shared/branch-marker-boZ00zmk.mjs +1 -0
- package/dist/packem_shared/buildModelMessages-Y4tGo1T9.mjs +5 -0
- package/dist/packem_shared/codeTool-BQb-K3my.mjs +1 -0
- package/dist/packem_shared/collectAgenticMemoryTools-BeMWT2qt.mjs +1 -0
- package/dist/packem_shared/combineTelemetry-DgE9W9G8.mjs +1 -0
- package/dist/packem_shared/common-CJSjtsfv.mjs +1 -0
- package/dist/packem_shared/compileAgentWorkflow-DVHi7NYD.mjs +1 -0
- package/dist/packem_shared/component-shared-G8ngerkU.mjs +1 -0
- package/dist/packem_shared/consoleTelemetry-BZY3Y-Ly.mjs +1 -0
- package/dist/packem_shared/createAgentContext-BvU9LP43.mjs +1 -0
- package/dist/packem_shared/createAgentGenerate-BOILDUZj.mjs +3 -0
- package/dist/packem_shared/createDispatchRunner-BxtGxAQi-DXXP7SxZ.mjs +1 -0
- package/dist/packem_shared/defineAgent-KgH-gwYg.mjs +3 -0
- package/dist/packem_shared/defineSkill-DGGvDWNq.mjs +1 -0
- package/dist/packem_shared/fnv1a-BNN96GYb.mjs +1 -0
- package/dist/packem_shared/functionTool-D3CP4f8-.mjs +1 -0
- package/dist/packem_shared/in-flight-calls-GH1A_1P3.mjs +1 -0
- package/dist/packem_shared/normalizeEntityName-k3fjicAG.mjs +2 -0
- package/dist/packem_shared/otlpTelemetry-ByqrB-72.mjs +1 -0
- package/dist/packem_shared/positive-integer-ztHqqpBk.mjs +1 -0
- package/dist/packem_shared/runAgentLoop-Drn1NcCc.mjs +1 -0
- package/dist/packem_shared/runVoiceTurn-BtcmyaBo.mjs +1 -0
- package/dist/packem_shared/sandboxComponent-BtOkUYpY.mjs +5 -0
- package/dist/packem_shared/sentryTelemetry-BHeydiAB.mjs +1 -0
- package/dist/packem_shared/tool-output-Cmk3JWMG.mjs +1 -0
- package/dist/packem_shared/types.d-B8WZl1rU.d.mts +1347 -0
- package/dist/packem_shared/types.d-B8WZl1rU.d.ts +1347 -0
- package/dist/packem_shared/voice-turn-BRj_it54.mjs +1 -0
- package/dist/reply.d.mts +40 -0
- package/dist/reply.d.ts +40 -0
- package/dist/reply.mjs +1 -0
- package/dist/sandbox.d.mts +130 -110
- package/dist/sandbox.d.ts +130 -110
- package/dist/sandbox.mjs +1 -109
- package/dist/skill-markdown.d.mts +36 -0
- package/dist/skill-markdown.d.ts +36 -0
- package/dist/skill-markdown.mjs +1 -0
- package/dist/telemetry/index.d.mts +319 -96
- package/dist/telemetry/index.d.ts +319 -96
- package/dist/telemetry/index.mjs +1 -4
- package/package.json +18 -9
- package/dist/packem_shared/AGENT_MODULE-Dnt_-AAT.mjs +0 -24
- package/dist/packem_shared/VoiceSessionDO-DLoXsHGF.mjs +0 -297
- package/dist/packem_shared/adaptMcpResult-wtNMvLoP.mjs +0 -65
- package/dist/packem_shared/agentAsTool-Dt8NlU6k.mjs +0 -94
- package/dist/packem_shared/base64-BVwtgRJV.mjs +0 -18
- package/dist/packem_shared/braintrustTelemetry-wuGDErob.mjs +0 -47
- package/dist/packem_shared/buildModelMessages-BWFigaoo.mjs +0 -69
- package/dist/packem_shared/codeTool-CjgJOC9t.mjs +0 -122
- package/dist/packem_shared/collectAgenticMemoryTools-QrzpV-WX.mjs +0 -97
- package/dist/packem_shared/combineTelemetry-DCyaaWAI.mjs +0 -43
- package/dist/packem_shared/common-DAeFCot5.mjs +0 -61
- package/dist/packem_shared/compileAgentWorkflow-BxJjHgtD.mjs +0 -55
- package/dist/packem_shared/consoleTelemetry-z2MiP1jt.mjs +0 -93
- package/dist/packem_shared/createAgentContext-4xJGXNR4.mjs +0 -50
- package/dist/packem_shared/createAgentGenerate-BQv9YJ01.mjs +0 -192
- package/dist/packem_shared/createDispatchRunner-DSbp_dph-ZHTtxy3f.mjs +0 -69
- package/dist/packem_shared/defineAgent-D6maSbVc.mjs +0 -148
- package/dist/packem_shared/defineSkill-Ctf_S-rz.mjs +0 -22
- package/dist/packem_shared/functionTool-D6lCa2jB.mjs +0 -20
- package/dist/packem_shared/graph-component-aoUwO-f0.mjs +0 -216
- package/dist/packem_shared/memory-D4FPcBsX.mjs +0 -12
- package/dist/packem_shared/normalizeEntityName-CyEEWFkR.mjs +0 -3
- package/dist/packem_shared/runAgentLoop-Dhg4ZNvw.mjs +0 -493
- package/dist/packem_shared/runVoiceTurn-LnqLvCRR.mjs +0 -211
- package/dist/packem_shared/sandboxComponent-DR3pTwBL.mjs +0 -194
- package/dist/packem_shared/sentryTelemetry-CgqFJyLO.mjs +0 -36
- package/dist/packem_shared/types.d-BWG0uUtX.d.mts +0 -1015
- package/dist/packem_shared/types.d-BWG0uUtX.d.ts +0 -1015
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{f as P,a as q}from"./base64-5eyBfWO3.mjs";import{c as z}from"./agent-loop-CE_Q6bk9.mjs";import{buildModelMessages as G}from"./buildModelMessages-Y4tGo1T9.mjs";import{toFunctionReference as T}from"./AGENT_MODULE-M4D1EejI.mjs";const D=new TextDecoder;new TextEncoder;const N="=",Q=t=>{if(t)try{const e=t[0]==="{"?t:D.decode(P(t)),n=JSON.parse(e);if(n&&typeof n=="object"&&!Array.isArray(n))return n}catch{}},ct=t=>{if(t){if(!t.startsWith(N))return t;try{return D.decode(P(t.slice(N.length)))}catch{return}}},dt=t=>{const e=Number(t);return Number.isFinite(e)&&e>0?e:void 0},ut=t=>typeof t=="number"&&Date.now()>=t,ft=t=>{try{t.send(JSON.stringify({code:"TOKEN_EXPIRED",error:{code:"TOKEN_EXPIRED",message:"authentication token expired"},message:"authentication token expired",type:"error"})),t.close?.(4001,"token_expired")}catch{}},Y=16e3,Z=1,tt=16,M=/[.!?]\s/u,et=/\s/u,nt=async function*(t){if(t instanceof Uint8Array){yield t;return}if(t instanceof ReadableStream){const e=t.getReader();try{for(;;){const{done:n,value:r}=await e.read();if(n)break;yield r}}finally{e.releaseLock()}return}yield*t},yt=(t,e=Y,n=Z,r=tt)=>{const i=n*r/8,p=e*i,m=new ArrayBuffer(44+t.byteLength),s=new DataView(m),u=(l,E)=>{for(let d=0;d<E.length;d+=1)s.setUint8(l+d,E.codePointAt(d)??0)};u(0,"RIFF"),s.setUint32(4,36+t.byteLength,!0),u(8,"WAVE"),u(12,"fmt "),s.setUint32(16,16,!0),s.setUint16(20,1,!0),s.setUint16(22,n,!0),s.setUint32(24,e,!0),s.setUint32(28,p,!0),s.setUint16(32,i,!0),s.setUint16(34,r,!0),u(36,"data"),s.setUint32(40,t.byteLength,!0);const a=new Uint8Array(m);return a.set(t,44),a},st=t=>{const e=[];let n=t,r=M.exec(n);for(;r;){let i=r.index+1;for(;i<n.length&&et.test(n[i]??"");)i+=1;const p=n.slice(0,i).trim();p.length>0&&e.push(p),n=n.slice(i),r=M.exec(n)}return{rest:n,sentences:e}},pt=async t=>{const{agent:e,compact:n,connectionId:r,env:i,exportName:p,owner:m,paths:s,pcm:u,run:a,send:l,sendAudio:E,signal:d,streamGenerate:C,synthesize:H,text:L,threadKey:o,transcribe:F,turn:U,waitForDrain:O}=t,h=()=>d.aborted,v=T(s.appendMessage),$=T(s.ensureThread),B=T(s.listMessages),b=T(s.patchThread);await a($,{agent:p,key:o,...e.initialState===void 0?{}:{initialState:e.initialState},...m===void 0?{}:{owner:m}});try{const f=(L??(u?await F(u):"")).trim();if(f.length===0)return await a(b,{key:o,status:"idle"}),{assistantText:"",interrupted:!1,userText:""};l({text:f,type:"user_transcript"}),await a(v,{content:f,messageKey:`voice:${r}:${String(U)}:user`,role:"user",threadKey:o}),await a(b,{key:o,status:"running"});const I=typeof e.instructions=="function"?e.instructions({env:i,input:f,threadKey:o}):e.instructions,K=await a(B,{key:o}),{history:j,summary:R}=await z({agent:e,compact:n,env:i},K),W=G({history:j,...I===void 0?{}:{instructions:I},...R===void 0?{}:{summary:R}});let g="",w="",S=Promise.resolve();const V=async c=>{if(h()||c.length===0)return;let x=!1;try{for await(const y of nt(await H(c,d))){if(h()||(await O?.(),h()))break;E(y),x=!0}}catch(y){l({message:y instanceof Error?y.message:String(y),type:"error"})}x&&(w=w.length>0?`${w} ${c}`:c)},_=c=>{S=S.then(async()=>V(c))},X=await C({messages:W,signal:d},c=>{if(h())return;l({text:c,type:"assistant_delta"}),g+=c;const{rest:x,sentences:y}=st(g);g=x;for(const J of y)_(J)});!h()&&g.trim().length>0&&_(g.trim()),g="",await S;const k=h(),A=k?w:X.text;return await a(v,{content:A,messageKey:`voice:${r}:${String(U)}:assistant`,role:"assistant",threadKey:o}),await a(b,{key:o,status:"idle"}),l(k?{type:"interrupted"}:{text:A,type:"assistant_done"}),{assistantText:A,interrupted:k,userText:f}}catch(f){throw await a(b,{key:o,status:"idle"}),f}},lt=t=>Q(t),ht=t=>{if(typeof t=="object"&&t!==null&&"text"in t){const{text:e}=t;return typeof e=="string"?e:""}return""},gt=t=>{if(t instanceof Uint8Array||t instanceof ReadableStream)return t;if(t instanceof Response&&t.body)return t.body;if(typeof t=="object"&&t!==null&&"audio"in t){const{audio:e}=t;if(typeof e=="string")return q(e);if(e instanceof ReadableStream||e instanceof Uint8Array)return e}return new Uint8Array(0)};export{dt as a,ft as b,yt as c,ct as d,ht as e,gt as f,ut as i,lt as p,pt as r,nt as t};
|
package/dist/reply.d.mts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Mailer } from '@lunora/mail';
|
|
2
|
+
import { InboundEmail } from '@lunora/mail/inbound';
|
|
3
|
+
import { a as AgentReplyRef } from "./packem_shared/types.d-B8WZl1rU.mjs";
|
|
4
|
+
import 'ai';
|
|
5
|
+
/** The email arm of {@link AgentReplyRef}, narrowed for the helpers below. */
|
|
6
|
+
type EmailReplyRef = Extract<AgentReplyRef, {
|
|
7
|
+
channel: "email";
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* Capture a reply reference from an already-parsed inbound email — call it in
|
|
11
|
+
* an `onEmail` mapper and put the result on the run's `replyRef`.
|
|
12
|
+
*
|
|
13
|
+
* Returns `undefined` when the message carries no `Message-ID`: there is
|
|
14
|
+
* nothing to thread a reply against, and an unthreaded reply lands as a new
|
|
15
|
+
* conversation in the recipient's client, which is worse than not replying.
|
|
16
|
+
*/
|
|
17
|
+
declare const captureEmailReplyRef: (email: InboundEmail) => EmailReplyRef | undefined;
|
|
18
|
+
/** RFC 5322 threading: append the replied-to id to any existing `References` chain. */
|
|
19
|
+
declare const buildReferences: (replyRef: EmailReplyRef) => string;
|
|
20
|
+
/** Subject + body of a reply. */
|
|
21
|
+
interface ReplyBody {
|
|
22
|
+
subject: string;
|
|
23
|
+
text: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Send a threaded reply through the app's own `@lunora/mail` mailer.
|
|
27
|
+
*
|
|
28
|
+
* The mailer is a parameter rather than something this module constructs: the
|
|
29
|
+
* app already configures one (API key or `send_email` binding), and passing it
|
|
30
|
+
* in keeps this module free of any runtime dependency on `@lunora/mail`.
|
|
31
|
+
*
|
|
32
|
+
* The reply goes to the original sender, from the mailer's configured default.
|
|
33
|
+
* An app running several aliases that wants the reply to come from whichever
|
|
34
|
+
* mailbox received the message passes `from: replyRef.to[0]` itself — a
|
|
35
|
+
* decision only the app can make.
|
|
36
|
+
*/
|
|
37
|
+
declare const replyToEmail: (mailer: Mailer, replyRef: EmailReplyRef, body: ReplyBody) => Promise<{
|
|
38
|
+
id: string;
|
|
39
|
+
}>;
|
|
40
|
+
export { type EmailReplyRef, ReplyBody, buildReferences, captureEmailReplyRef, replyToEmail };
|
package/dist/reply.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Mailer } from '@lunora/mail';
|
|
2
|
+
import { InboundEmail } from '@lunora/mail/inbound';
|
|
3
|
+
import { a as AgentReplyRef } from "./packem_shared/types.d-B8WZl1rU.js";
|
|
4
|
+
import 'ai';
|
|
5
|
+
/** The email arm of {@link AgentReplyRef}, narrowed for the helpers below. */
|
|
6
|
+
type EmailReplyRef = Extract<AgentReplyRef, {
|
|
7
|
+
channel: "email";
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* Capture a reply reference from an already-parsed inbound email — call it in
|
|
11
|
+
* an `onEmail` mapper and put the result on the run's `replyRef`.
|
|
12
|
+
*
|
|
13
|
+
* Returns `undefined` when the message carries no `Message-ID`: there is
|
|
14
|
+
* nothing to thread a reply against, and an unthreaded reply lands as a new
|
|
15
|
+
* conversation in the recipient's client, which is worse than not replying.
|
|
16
|
+
*/
|
|
17
|
+
declare const captureEmailReplyRef: (email: InboundEmail) => EmailReplyRef | undefined;
|
|
18
|
+
/** RFC 5322 threading: append the replied-to id to any existing `References` chain. */
|
|
19
|
+
declare const buildReferences: (replyRef: EmailReplyRef) => string;
|
|
20
|
+
/** Subject + body of a reply. */
|
|
21
|
+
interface ReplyBody {
|
|
22
|
+
subject: string;
|
|
23
|
+
text: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Send a threaded reply through the app's own `@lunora/mail` mailer.
|
|
27
|
+
*
|
|
28
|
+
* The mailer is a parameter rather than something this module constructs: the
|
|
29
|
+
* app already configures one (API key or `send_email` binding), and passing it
|
|
30
|
+
* in keeps this module free of any runtime dependency on `@lunora/mail`.
|
|
31
|
+
*
|
|
32
|
+
* The reply goes to the original sender, from the mailer's configured default.
|
|
33
|
+
* An app running several aliases that wants the reply to come from whichever
|
|
34
|
+
* mailbox received the message passes `from: replyRef.to[0]` itself — a
|
|
35
|
+
* decision only the app can make.
|
|
36
|
+
*/
|
|
37
|
+
declare const replyToEmail: (mailer: Mailer, replyRef: EmailReplyRef, body: ReplyBody) => Promise<{
|
|
38
|
+
id: string;
|
|
39
|
+
}>;
|
|
40
|
+
export { type EmailReplyRef, ReplyBody, buildReferences, captureEmailReplyRef, replyToEmail };
|
package/dist/reply.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const t=e=>{if(e.messageId!==void 0)return{channel:"email",from:e.from,messageId:e.messageId,to:e.to,...e.references===void 0?{}:{references:e.references}}},n=e=>e.references===void 0?e.messageId:`${e.references} ${e.messageId}`,c=async(e,s,r)=>e.send({headers:{"In-Reply-To":s.messageId,References:n(s)},subject:r.subject,text:r.text,to:s.from});export{n as buildReferences,t as captureEmailReplyRef,c as replyToEmail};
|
package/dist/sandbox.d.mts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as AgentToolContext, c as AgentToolDefinition } from "./packem_shared/types.d-B8WZl1rU.mjs";
|
|
2
2
|
import '@lunora/mail/inbound';
|
|
3
3
|
import 'ai';
|
|
4
4
|
/**
|
|
5
|
-
* The model-provided input to a {@link browserTool} call — a discriminated
|
|
6
|
-
* union on `op` so one tool exposes every headless-browser capability.
|
|
7
|
-
|
|
5
|
+
* The model-provided input to a {@link browserTool} call — a discriminated
|
|
6
|
+
* union on `op` so one tool exposes every headless-browser capability.
|
|
7
|
+
* @experimental
|
|
8
|
+
*/
|
|
8
9
|
type BrowserToolInput = {
|
|
9
10
|
fullPage?: boolean;
|
|
10
11
|
op: "screenshot";
|
|
@@ -22,11 +23,12 @@ type BrowserToolInput = {
|
|
|
22
23
|
url: string;
|
|
23
24
|
};
|
|
24
25
|
/**
|
|
25
|
-
* The model-provided input to a {@link containerTool} call — a discriminated
|
|
26
|
-
* union on `op`. `fetch` sends an HTTP request to the container; `exec` asks it
|
|
27
|
-
* to run a command (
|
|
28
|
-
*
|
|
29
|
-
|
|
26
|
+
* The model-provided input to a {@link containerTool} call — a discriminated
|
|
27
|
+
* union on `op`. `fetch` sends an HTTP request to the container; `exec` asks it
|
|
28
|
+
* to run a command (delegated to `ctx.containers.<name>.exec`, the first-class
|
|
29
|
+
* exec contract in `@lunora/container`; the container app serves its route).
|
|
30
|
+
* @experimental
|
|
31
|
+
*/
|
|
30
32
|
type ContainerToolInput = {
|
|
31
33
|
args?: string[];
|
|
32
34
|
command?: string;
|
|
@@ -37,25 +39,29 @@ type ContainerToolInput = {
|
|
|
37
39
|
op: "fetch";
|
|
38
40
|
path: string;
|
|
39
41
|
};
|
|
40
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* Author-supplied config for `browserTool`.
|
|
44
|
+
* @experimental
|
|
45
|
+
*/
|
|
41
46
|
interface BrowserToolOptions {
|
|
42
47
|
/** Override the model-facing description (what the tool does). */
|
|
43
48
|
description?: string;
|
|
44
49
|
/**
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
* Gate a call behind a human approval. Defaults to **unattended** (no gate),
|
|
51
|
+
* matching the AI SDK. `browserTool` fetches a model-chosen `url` with no
|
|
52
|
+
* allowlist, so it is an SSRF surface: a prompt-injected model can point it at
|
|
53
|
+
* an internal/link-local address and read the response back into context. Pass
|
|
54
|
+
* a boolean or a predicate to gate it (evaluated from replay-stable input, so
|
|
55
|
+
* keep it deterministic).
|
|
56
|
+
*/
|
|
52
57
|
needsApproval?: ((input: BrowserToolInput) => boolean) | boolean;
|
|
53
58
|
}
|
|
54
59
|
/**
|
|
55
|
-
* The model-provided input to a {@link fsTool} call — a discriminated union on
|
|
56
|
-
* `op` over an R2-backed virtual filesystem. Paths are relative to the tool's
|
|
57
|
-
* pinned `root`; a `..` that escapes the root is rejected server-side.
|
|
58
|
-
|
|
60
|
+
* The model-provided input to a {@link fsTool} call — a discriminated union on
|
|
61
|
+
* `op` over an R2-backed virtual filesystem. Paths are relative to the tool's
|
|
62
|
+
* pinned `root`; a `..` that escapes the root is rejected server-side.
|
|
63
|
+
* @experimental
|
|
64
|
+
*/
|
|
59
65
|
type FsToolInput = {
|
|
60
66
|
op: "ls";
|
|
61
67
|
path?: string;
|
|
@@ -73,113 +79,127 @@ type FsToolInput = {
|
|
|
73
79
|
op: "write";
|
|
74
80
|
path: string;
|
|
75
81
|
};
|
|
76
|
-
/**
|
|
82
|
+
/**
|
|
83
|
+
* Author-supplied config for `fsTool`.
|
|
84
|
+
* @experimental
|
|
85
|
+
*/
|
|
77
86
|
interface FsToolOptions {
|
|
78
87
|
/** Override the model-facing description (what the tool does). */
|
|
79
88
|
description?: string;
|
|
80
89
|
/**
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
* Gate a call behind a human approval. Defaults to gating the WRITING ops
|
|
91
|
+
* (`write`, `rm`) — a prompt-injected model shouldn't silently overwrite or
|
|
92
|
+
* delete the sandbox — while `ls`/`read`/`stat` run unattended. Pass a boolean
|
|
93
|
+
* or a predicate (evaluated from replay-stable input, so keep it deterministic).
|
|
94
|
+
*/
|
|
86
95
|
needsApproval?: ((input: FsToolInput) => boolean) | boolean;
|
|
87
96
|
/**
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
97
|
+
* The key prefix every path is scoped under, isolating this tool's files from
|
|
98
|
+
* the rest of the bucket. Either a fixed string (e.g. `"agents/support"`) or a
|
|
99
|
+
* function of the tool context — return `` `agents/${ctx.threadKey}` `` (or an
|
|
100
|
+
* owner-derived prefix) to give each run/user its OWN namespace in a
|
|
101
|
+
* multi-tenant agent. Default: the bucket root (shared — set a root for
|
|
102
|
+
* multi-tenant use). The server rejects any `..` that would escape it.
|
|
103
|
+
*/
|
|
95
104
|
root?: ((context: AgentToolContext) => string) | string;
|
|
96
105
|
}
|
|
97
|
-
/**
|
|
106
|
+
/**
|
|
107
|
+
* Author-supplied config for `containerTool`.
|
|
108
|
+
* @experimental
|
|
109
|
+
*/
|
|
98
110
|
interface ContainerToolOptions {
|
|
99
111
|
/** Override the model-facing description (what the tool does). */
|
|
100
112
|
description?: string;
|
|
101
113
|
/**
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
114
|
+
* Gate a call behind a human approval. Defaults to gating any command
|
|
115
|
+
* execution — an `exec` — plus any `fetch` using a non-idempotent method
|
|
116
|
+
* (POST/PUT/PATCH/DELETE), so a prompt-injected model cannot reach some
|
|
117
|
+
* other mutating route unattended. A read-only `fetch` runs unattended. The
|
|
118
|
+
* exec route itself needs no special case: `@lunora/container` reserves
|
|
119
|
+
* `/__lunora/*` and refuses a `fetch` into it. Pass a boolean or your own
|
|
120
|
+
* predicate to change that. Evaluated from replay-stable input, so keep it
|
|
121
|
+
* deterministic.
|
|
122
|
+
*/
|
|
110
123
|
needsApproval?: ((input: ContainerToolInput) => boolean) | boolean;
|
|
111
124
|
}
|
|
112
125
|
/**
|
|
113
|
-
* A batteries-included agent tool that drives Cloudflare Browser Rendering. One
|
|
114
|
-
* tool exposes every browser op (screenshot / pdf / content / scrape); the model
|
|
115
|
-
* picks via `op`. The call dispatches to the auto-registered `sandbox:invoke`
|
|
116
|
-
* action — which runs on an action ctx carrying `ctx.browser`. Importing the tool
|
|
117
|
-
* makes codegen register the dispatcher and provision the `BROWSER` binding; like
|
|
118
|
-
* any `ctx.browser` user, the app still supplies a `config.browser` thunk
|
|
119
|
-
* (`createBrowser({ binding: env.BROWSER, launch })` with the optional
|
|
120
|
-
* `@cloudflare/playwright` `launch` peer) to `createShardDO()` — codegen never
|
|
121
|
-
* injects that peer, so the browser op throws a directed error until it is wired.
|
|
122
|
-
*
|
|
123
|
-
* Security: the model chooses the `url` with no allowlist, so this is an SSRF
|
|
124
|
-
* surface — pass `opts.needsApproval` to gate calls a prompt-injected model
|
|
125
|
-
* could aim at internal/link-local endpoints.
|
|
126
|
-
*
|
|
127
|
-
* ```ts
|
|
128
|
-
* import { browserTool, defineAgent } from "@lunora/agent/sandbox";
|
|
129
|
-
*
|
|
130
|
-
* export const researcher = defineAgent({
|
|
131
|
-
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
132
|
-
* tools: { browser: browserTool() },
|
|
133
|
-
* });
|
|
134
|
-
* ```
|
|
135
|
-
|
|
126
|
+
* A batteries-included agent tool that drives Cloudflare Browser Rendering. One
|
|
127
|
+
* tool exposes every browser op (screenshot / pdf / content / scrape); the model
|
|
128
|
+
* picks via `op`. The call dispatches to the auto-registered `sandbox:invoke`
|
|
129
|
+
* action — which runs on an action ctx carrying `ctx.browser`. Importing the tool
|
|
130
|
+
* makes codegen register the dispatcher and provision the `BROWSER` binding; like
|
|
131
|
+
* any `ctx.browser` user, the app still supplies a `config.browser` thunk
|
|
132
|
+
* (`createBrowser({ binding: env.BROWSER, launch })` with the optional
|
|
133
|
+
* `@cloudflare/playwright` `launch` peer) to `createShardDO()` — codegen never
|
|
134
|
+
* injects that peer, so the browser op throws a directed error until it is wired.
|
|
135
|
+
*
|
|
136
|
+
* Security: the model chooses the `url` with no allowlist, so this is an SSRF
|
|
137
|
+
* surface — pass `opts.needsApproval` to gate calls a prompt-injected model
|
|
138
|
+
* could aim at internal/link-local endpoints.
|
|
139
|
+
*
|
|
140
|
+
* ```ts
|
|
141
|
+
* import { browserTool, defineAgent } from "@lunora/agent/sandbox";
|
|
142
|
+
*
|
|
143
|
+
* export const researcher = defineAgent({
|
|
144
|
+
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
145
|
+
* tools: { browser: browserTool() },
|
|
146
|
+
* });
|
|
147
|
+
* ```
|
|
148
|
+
* @experimental
|
|
149
|
+
*/
|
|
136
150
|
declare const browserTool: (options?: BrowserToolOptions) => AgentToolDefinition<BrowserToolInput, string>;
|
|
137
151
|
/**
|
|
138
|
-
* A batteries-included agent tool that talks to a declared Cloudflare
|
|
139
|
-
* Container. `name` is the `ctx.containers
|
|
140
|
-
* export). One tool exposes `fetch` (HTTP request) and `exec` (run a command);
|
|
141
|
-
* the model picks via `op`. The call dispatches to the auto-registered
|
|
142
|
-
* `sandbox:invoke` action, which carries `ctx.containers`.
|
|
143
|
-
*
|
|
144
|
-
* By default a `fetch` runs
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
|
|
152
|
+
* A batteries-included agent tool that talks to a declared Cloudflare
|
|
153
|
+
* Container. `name` is the `ctx.containers.<name>` key (the `lunora/containers.ts`
|
|
154
|
+
* export). One tool exposes `fetch` (HTTP request) and `exec` (run a command);
|
|
155
|
+
* the model picks via `op`. The call dispatches to the auto-registered
|
|
156
|
+
* `sandbox:invoke` action, which carries `ctx.containers`.
|
|
157
|
+
*
|
|
158
|
+
* By default a read-only (GET/HEAD/OPTIONS, or method-omitted) `fetch` runs
|
|
159
|
+
* unattended while everything else is gated behind a human approval — an
|
|
160
|
+
* `exec`; a `fetch` whose path resolves to the privileged exec route (both
|
|
161
|
+
* reach the same command-execution path in the container, so gating on the
|
|
162
|
+
* `op` name alone would let a `fetch` to it run a command unattended);
|
|
163
|
+
* and a `fetch` using a non-idempotent method (POST/PUT/PATCH/DELETE) to ANY
|
|
164
|
+
* route, since a prompt-injected model could otherwise mutate container state
|
|
165
|
+
* through some other privileged route just by avoiding the literal exec
|
|
166
|
+
* path. A `fetch` can still reach any *other read* route unattended, so scope
|
|
167
|
+
* the container's GET routes accordingly. Pass `opts.needsApproval` to widen
|
|
168
|
+
* or disable the gate.
|
|
169
|
+
*
|
|
170
|
+
* ```ts
|
|
171
|
+
* import { containerTool, defineAgent } from "@lunora/agent/sandbox";
|
|
172
|
+
*
|
|
173
|
+
* export const ops = defineAgent({
|
|
174
|
+
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
175
|
+
* tools: { sandbox: containerTool("sandbox") },
|
|
176
|
+
* });
|
|
177
|
+
* ```
|
|
178
|
+
* @experimental
|
|
179
|
+
*/
|
|
161
180
|
declare const containerTool: (name: string, options?: ContainerToolOptions) => AgentToolDefinition<ContainerToolInput, string>;
|
|
162
181
|
/**
|
|
163
|
-
* A batteries-included agent tool exposing a persistent, R2-backed virtual
|
|
164
|
-
* filesystem. `bucket` is the R2 binding name; every path is scoped under the
|
|
165
|
-
* pinned `opts.root` (a `..` that would escape it is rejected). One tool exposes
|
|
166
|
-
* `ls`/`read`/`write`/`rm`/`stat`; the model picks via `op`. The call dispatches
|
|
167
|
-
* to the auto-registered `sandbox:invoke` action, which reads the bucket from
|
|
168
|
-
* `ctx.env`. workerd has no real shell — this is object-store-backed file I/O.
|
|
169
|
-
*
|
|
170
|
-
* By default the writing ops (`write`/`rm`) pause for a human approval while
|
|
171
|
-
* reads run unattended; pass `opts.needsApproval` to change that. Importing the
|
|
172
|
-
* tool registers the dispatcher; the app must declare the `r2_bucket` binding in
|
|
173
|
-
* `wrangler.jsonc` (the fs op throws a directed error until it is wired).
|
|
174
|
-
*
|
|
175
|
-
* ```ts
|
|
176
|
-
* import { defineAgent, fsTool } from "@lunora/agent/sandbox";
|
|
177
|
-
*
|
|
178
|
-
* export const coder = defineAgent({
|
|
179
|
-
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
180
|
-
* tools: { fs: fsTool("SANDBOX_BUCKET", { root: "agents/coder" }) },
|
|
181
|
-
* });
|
|
182
|
-
* ```
|
|
183
|
-
|
|
182
|
+
* A batteries-included agent tool exposing a persistent, R2-backed virtual
|
|
183
|
+
* filesystem. `bucket` is the R2 binding name; every path is scoped under the
|
|
184
|
+
* pinned `opts.root` (a `..` that would escape it is rejected). One tool exposes
|
|
185
|
+
* `ls`/`read`/`write`/`rm`/`stat`; the model picks via `op`. The call dispatches
|
|
186
|
+
* to the auto-registered `sandbox:invoke` action, which reads the bucket from
|
|
187
|
+
* `ctx.env`. workerd has no real shell — this is object-store-backed file I/O.
|
|
188
|
+
*
|
|
189
|
+
* By default the writing ops (`write`/`rm`) pause for a human approval while
|
|
190
|
+
* reads run unattended; pass `opts.needsApproval` to change that. Importing the
|
|
191
|
+
* tool registers the dispatcher; the app must declare the `r2_bucket` binding in
|
|
192
|
+
* `wrangler.jsonc` (the fs op throws a directed error until it is wired).
|
|
193
|
+
*
|
|
194
|
+
* ```ts
|
|
195
|
+
* import { defineAgent, fsTool } from "@lunora/agent/sandbox";
|
|
196
|
+
*
|
|
197
|
+
* export const coder = defineAgent({
|
|
198
|
+
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
199
|
+
* tools: { fs: fsTool("SANDBOX_BUCKET", { root: "agents/coder" }) },
|
|
200
|
+
* });
|
|
201
|
+
* ```
|
|
202
|
+
* @experimental
|
|
203
|
+
*/
|
|
184
204
|
declare const fsTool: (bucket: string, options?: FsToolOptions) => AgentToolDefinition<FsToolInput>;
|
|
185
205
|
export { type BrowserToolInput, type BrowserToolOptions, type ContainerToolInput, type ContainerToolOptions, type FsToolInput, type FsToolOptions, browserTool, containerTool, fsTool };
|