@lunora/agent 1.0.0-alpha.58 → 1.0.0-alpha.59
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/dist/channels.d.mts +2 -2
- package/dist/channels.d.ts +2 -2
- package/dist/inbound.d.mts +1 -1
- package/dist/inbound.d.ts +1 -1
- package/dist/index.d.mts +34 -4
- package/dist/index.d.ts +34 -4
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/{VoiceSessionDO-CZG-WkQ8.mjs → VoiceSessionDO-A6u5NXI1.mjs} +1 -1
- package/dist/packem_shared/adaptMcpResult-CVlq-_TO.mjs +2 -0
- package/dist/packem_shared/codeTool-B1_HVhnJ.mjs +1 -0
- package/dist/packem_shared/{compileAgentWorkflow-O_Kvw_Ze.mjs → compileAgentWorkflow-BvkRUzx_.mjs} +1 -1
- package/dist/packem_shared/{createAgentContext-HUKAccII.mjs → createAgentContext-CfD3hIZ2.mjs} +1 -1
- package/dist/packem_shared/createDispatchRunner-CGafifJ7-C__lmjdK.mjs +1 -0
- package/dist/packem_shared/functionTool-DbrqDql3.mjs +1 -0
- package/dist/packem_shared/{runAgentLoop-k63A5u8S.mjs → runAgentLoop-6fGTajbG.mjs} +2 -2
- package/dist/packem_shared/{types.d-CeO8cn_u.d.mts → types.d-BoMo2eJj.d.mts} +46 -15
- package/dist/packem_shared/{types.d-CeO8cn_u.d.ts → types.d-BoMo2eJj.d.ts} +46 -15
- package/dist/reply.d.mts +1 -1
- package/dist/reply.d.ts +1 -1
- package/dist/sandbox.d.mts +1 -1
- package/dist/sandbox.d.ts +1 -1
- package/dist/skill-markdown.d.mts +1 -1
- package/dist/skill-markdown.d.ts +1 -1
- package/package.json +3 -3
- package/dist/packem_shared/adaptMcpResult-D90rkUqS.mjs +0 -2
- package/dist/packem_shared/codeTool-B1SSluGg.mjs +0 -1
- package/dist/packem_shared/createDispatchRunner-DIjJ2U-O-C5xqijhC.mjs +0 -1
- package/dist/packem_shared/functionTool-CaWLukmr.mjs +0 -1
package/dist/channels.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AgentDefinition } from "./packem_shared/types.d-
|
|
2
|
-
export type { I as InboundChannelEvent } from "./packem_shared/types.d-
|
|
1
|
+
import { A as AgentDefinition } from "./packem_shared/types.d-BoMo2eJj.mjs";
|
|
2
|
+
export type { I as InboundChannelEvent } from "./packem_shared/types.d-BoMo2eJj.mjs";
|
|
3
3
|
import '@lunora/mail/inbound';
|
|
4
4
|
import 'ai';
|
|
5
5
|
/**
|
package/dist/channels.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AgentDefinition } from "./packem_shared/types.d-
|
|
2
|
-
export type { I as InboundChannelEvent } from "./packem_shared/types.d-
|
|
1
|
+
import { A as AgentDefinition } from "./packem_shared/types.d-BoMo2eJj.js";
|
|
2
|
+
export type { I as InboundChannelEvent } from "./packem_shared/types.d-BoMo2eJj.js";
|
|
3
3
|
import '@lunora/mail/inbound';
|
|
4
4
|
import 'ai';
|
|
5
5
|
/**
|
package/dist/inbound.d.mts
CHANGED
package/dist/inbound.d.ts
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AgentDefinition, e as AgentCompact, f as AgentEpisodeExtract, g as AgentGraphExtract, h as AgentGenerate, i as AgentTokenSink, j as AgentRunInput, k as AgentFunctionPaths, l as AgentRunFunction, m as AgentStepLike, n as AgentStreamGenerate, o as AgentRunResult, p as AgentMessageRow, q as AgentConfig, d as SkillDefinition, r as AnyAgentTool, s as AgentAsToolOptions, t as AgentSubToolInput, c as AgentToolDefinition, u as AgentBindingSpec, v as AgentHandle, w as AgentToolConfig, x as AgentFunctionReference, y as AgentModelInput, z as SkillConfig } from "./packem_shared/types.d-
|
|
2
|
-
export type { B as AgentApprovalContext, C as AgentEmailMapper, D as AgentEmailRun, E as AgentGenerateOptions, F as AgentGenerateResult, G as AgentInstructionsContext, H as AgentLiveEvent, J as AgentMemoryOptions, K as AgentMemorySource, L as AgentMessageStatus, M as AgentOnReply, N as AgentOnStepFinish, O as AgentPrepareStep, P as AgentPrepareStepInput, Q as AgentPrepareStepResult, R as AgentProgressEvent, T as AgentReplyInfo, a as AgentReplyRef, U as AgentRunHandle, V as AgentStepFinishInfo, W as AgentStepInfo, X as AgentThreadStatus, Y as AgentTokenDelta, Z as AgentToolCall, b as AgentToolContext, _ as AgentUsage, $ as AgentVoiceConfig, a0 as AgentWorkflowBindingLike, a1 as AgentWorkflowInstanceLike, a2 as EnsureThreadOutcome } from "./packem_shared/types.d-
|
|
1
|
+
import { A as AgentDefinition, e as AgentCompact, f as AgentEpisodeExtract, g as AgentGraphExtract, h as AgentGenerate, i as AgentTokenSink, j as AgentRunInput, k as AgentFunctionPaths, l as AgentRunFunction, m as AgentStepLike, n as AgentStreamGenerate, o as AgentRunResult, p as AgentMessageRow, q as AgentConfig, d as SkillDefinition, r as AnyAgentTool, s as AgentAsToolOptions, t as AgentSubToolInput, c as AgentToolDefinition, u as AgentBindingSpec, v as AgentHandle, w as AgentToolConfig, x as AgentFunctionReference, y as AgentModelInput, z as SkillConfig } from "./packem_shared/types.d-BoMo2eJj.mjs";
|
|
2
|
+
export type { B as AgentApprovalContext, C as AgentEmailMapper, D as AgentEmailRun, E as AgentGenerateOptions, F as AgentGenerateResult, G as AgentInstructionsContext, H as AgentLiveEvent, J as AgentMemoryOptions, K as AgentMemorySource, L as AgentMessageStatus, M as AgentOnReply, N as AgentOnStepFinish, O as AgentPrepareStep, P as AgentPrepareStepInput, Q as AgentPrepareStepResult, R as AgentProgressEvent, T as AgentReplyInfo, a as AgentReplyRef, U as AgentRunHandle, V as AgentStepFinishInfo, W as AgentStepInfo, X as AgentThreadStatus, Y as AgentTokenDelta, Z as AgentToolCall, b as AgentToolContext, _ as AgentUsage, $ as AgentVoiceConfig, a0 as AgentWorkflowBindingLike, a1 as AgentWorkflowInstanceLike, a2 as EnsureThreadOutcome } from "./packem_shared/types.d-BoMo2eJj.mjs";
|
|
3
3
|
export { type AgentComponent, agentComponent, agentExtension } from "./component.mjs";
|
|
4
4
|
import { FlexibleSchema, LanguageModel, ModelMessage } from 'ai';
|
|
5
5
|
export { agentBindingName, agentClassName, agentDefaultName, voiceBindingName, voiceClassName } from "./naming.mjs";
|
|
@@ -239,6 +239,16 @@ interface CodeToolOptions {
|
|
|
239
239
|
* keep approval-gated tools as normal top-level tools. Gate the whole script via
|
|
240
240
|
* `opts.needsApproval` instead.
|
|
241
241
|
*
|
|
242
|
+
* STEP-OUTPUT CONTRACT — **every step's output must be JSON-serializable.** Each
|
|
243
|
+
* step runs inside its own durable `step.do`, so the workflow host serializes
|
|
244
|
+
* the returned value before the next step (or the tool result) ever sees it. A
|
|
245
|
+
* `Date` comes back as an ISO string, a `Map`/`Set` as `{}`, `undefined` as
|
|
246
|
+
* `null` or a dropped key, and a `bigint` throws outright. That applies to the
|
|
247
|
+
* value a later step reads through `{ "$from": … }` just as much as to the
|
|
248
|
+
* returned `results` — the hand-off is durable state, not an in-memory one. A
|
|
249
|
+
* composed tool that wants to pass a rich value should return its JSON form
|
|
250
|
+
* (`date.toISOString()`, `[...map]`) and let the consuming step rebuild it.
|
|
251
|
+
*
|
|
242
252
|
* ```ts
|
|
243
253
|
* import { codeTool, defineAgent, functionTool } from "@lunora/agent";
|
|
244
254
|
*
|
|
@@ -344,8 +354,14 @@ interface FunctionToolOptions<Input> {
|
|
|
344
354
|
* ```
|
|
345
355
|
*
|
|
346
356
|
* The function reference may be a typed `api.*` reference or a `"module:name"`
|
|
347
|
-
* path. The model-provided input is passed
|
|
348
|
-
* `inputSchema` should mirror the referenced function's argument validator
|
|
357
|
+
* path. The model-provided input is passed as the function's args, so
|
|
358
|
+
* `inputSchema` should mirror the referenced function's argument validator —
|
|
359
|
+
* PLUS the call's `idempotencyKey`, pinned onto the args after the model
|
|
360
|
+
* input (so out-of-schema model input can never override it). A function
|
|
361
|
+
* that wants to dedupe a side-effecting call across an at-least-once step
|
|
362
|
+
* retry declares `idempotencyKey: v.optional(v.string())` in its own args
|
|
363
|
+
* and checks it; a function that ignores it is unaffected — an args field
|
|
364
|
+
* the function's own validator doesn't declare is dropped, not rejected.
|
|
349
365
|
* @experimental
|
|
350
366
|
*/
|
|
351
367
|
declare const functionTool: <Input extends Record<string, unknown> = Record<string, unknown>, Output = unknown>(reference: AgentFunctionReference | string, options: FunctionToolOptions<Input>) => AgentToolDefinition<Input, Output>;
|
|
@@ -471,6 +487,17 @@ interface McpToolsOptions {
|
|
|
471
487
|
command?: string;
|
|
472
488
|
/** Identify this client to the server on connect. Default `"lunora-agent"`. */
|
|
473
489
|
name?: string;
|
|
490
|
+
/**
|
|
491
|
+
* Gate an adapted tool's call behind a human approval. Defaults to
|
|
492
|
+
* **unattended** (no gate) — matching today's behavior. An MCP tool's
|
|
493
|
+
* result feeds back into the model's context (`adaptMcpResult`), so a
|
|
494
|
+
* hostile downstream server can pair indirect prompt injection with an
|
|
495
|
+
* unattended mutating tool call; pass a boolean to gate every adapted
|
|
496
|
+
* tool the same way, or a predicate `(toolName, input) => boolean` to
|
|
497
|
+
* gate per tool (evaluated from replay-stable input, so keep it
|
|
498
|
+
* deterministic).
|
|
499
|
+
*/
|
|
500
|
+
needsApproval?: ((toolName: string, input: Record<string, unknown>) => boolean) | boolean;
|
|
474
501
|
/** Only adapt these tool names (default: every tool the server lists). */
|
|
475
502
|
only?: ReadonlyArray<string>;
|
|
476
503
|
/** Prefix added to each adapted tool's key (disambiguate multiple servers). */
|
|
@@ -510,6 +537,9 @@ declare const adaptMcpResult: (result: McpCallResult) => unknown;
|
|
|
510
537
|
* every call. In the Workers runtime only the HTTP/SSE transports run (stdio
|
|
511
538
|
* does not) — pass `url`, or inject an already-connected `client` for a custom
|
|
512
539
|
* transport (also the test seam).
|
|
540
|
+
*
|
|
541
|
+
* Every adapted tool runs UNATTENDED by default (no approval gate) — pass
|
|
542
|
+
* `opts.needsApproval` to change that; see {@link McpToolsOptions.needsApproval}.
|
|
513
543
|
* @experimental
|
|
514
544
|
*/
|
|
515
545
|
declare const mcpTools: (options: McpToolsOptions) => Promise<Record<string, AgentToolDefinition<Record<string, unknown>>>>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AgentDefinition, e as AgentCompact, f as AgentEpisodeExtract, g as AgentGraphExtract, h as AgentGenerate, i as AgentTokenSink, j as AgentRunInput, k as AgentFunctionPaths, l as AgentRunFunction, m as AgentStepLike, n as AgentStreamGenerate, o as AgentRunResult, p as AgentMessageRow, q as AgentConfig, d as SkillDefinition, r as AnyAgentTool, s as AgentAsToolOptions, t as AgentSubToolInput, c as AgentToolDefinition, u as AgentBindingSpec, v as AgentHandle, w as AgentToolConfig, x as AgentFunctionReference, y as AgentModelInput, z as SkillConfig } from "./packem_shared/types.d-
|
|
2
|
-
export type { B as AgentApprovalContext, C as AgentEmailMapper, D as AgentEmailRun, E as AgentGenerateOptions, F as AgentGenerateResult, G as AgentInstructionsContext, H as AgentLiveEvent, J as AgentMemoryOptions, K as AgentMemorySource, L as AgentMessageStatus, M as AgentOnReply, N as AgentOnStepFinish, O as AgentPrepareStep, P as AgentPrepareStepInput, Q as AgentPrepareStepResult, R as AgentProgressEvent, T as AgentReplyInfo, a as AgentReplyRef, U as AgentRunHandle, V as AgentStepFinishInfo, W as AgentStepInfo, X as AgentThreadStatus, Y as AgentTokenDelta, Z as AgentToolCall, b as AgentToolContext, _ as AgentUsage, $ as AgentVoiceConfig, a0 as AgentWorkflowBindingLike, a1 as AgentWorkflowInstanceLike, a2 as EnsureThreadOutcome } from "./packem_shared/types.d-
|
|
1
|
+
import { A as AgentDefinition, e as AgentCompact, f as AgentEpisodeExtract, g as AgentGraphExtract, h as AgentGenerate, i as AgentTokenSink, j as AgentRunInput, k as AgentFunctionPaths, l as AgentRunFunction, m as AgentStepLike, n as AgentStreamGenerate, o as AgentRunResult, p as AgentMessageRow, q as AgentConfig, d as SkillDefinition, r as AnyAgentTool, s as AgentAsToolOptions, t as AgentSubToolInput, c as AgentToolDefinition, u as AgentBindingSpec, v as AgentHandle, w as AgentToolConfig, x as AgentFunctionReference, y as AgentModelInput, z as SkillConfig } from "./packem_shared/types.d-BoMo2eJj.js";
|
|
2
|
+
export type { B as AgentApprovalContext, C as AgentEmailMapper, D as AgentEmailRun, E as AgentGenerateOptions, F as AgentGenerateResult, G as AgentInstructionsContext, H as AgentLiveEvent, J as AgentMemoryOptions, K as AgentMemorySource, L as AgentMessageStatus, M as AgentOnReply, N as AgentOnStepFinish, O as AgentPrepareStep, P as AgentPrepareStepInput, Q as AgentPrepareStepResult, R as AgentProgressEvent, T as AgentReplyInfo, a as AgentReplyRef, U as AgentRunHandle, V as AgentStepFinishInfo, W as AgentStepInfo, X as AgentThreadStatus, Y as AgentTokenDelta, Z as AgentToolCall, b as AgentToolContext, _ as AgentUsage, $ as AgentVoiceConfig, a0 as AgentWorkflowBindingLike, a1 as AgentWorkflowInstanceLike, a2 as EnsureThreadOutcome } from "./packem_shared/types.d-BoMo2eJj.js";
|
|
3
3
|
export { type AgentComponent, agentComponent, agentExtension } from "./component.js";
|
|
4
4
|
import { FlexibleSchema, LanguageModel, ModelMessage } from 'ai';
|
|
5
5
|
export { agentBindingName, agentClassName, agentDefaultName, voiceBindingName, voiceClassName } from "./naming.js";
|
|
@@ -239,6 +239,16 @@ interface CodeToolOptions {
|
|
|
239
239
|
* keep approval-gated tools as normal top-level tools. Gate the whole script via
|
|
240
240
|
* `opts.needsApproval` instead.
|
|
241
241
|
*
|
|
242
|
+
* STEP-OUTPUT CONTRACT — **every step's output must be JSON-serializable.** Each
|
|
243
|
+
* step runs inside its own durable `step.do`, so the workflow host serializes
|
|
244
|
+
* the returned value before the next step (or the tool result) ever sees it. A
|
|
245
|
+
* `Date` comes back as an ISO string, a `Map`/`Set` as `{}`, `undefined` as
|
|
246
|
+
* `null` or a dropped key, and a `bigint` throws outright. That applies to the
|
|
247
|
+
* value a later step reads through `{ "$from": … }` just as much as to the
|
|
248
|
+
* returned `results` — the hand-off is durable state, not an in-memory one. A
|
|
249
|
+
* composed tool that wants to pass a rich value should return its JSON form
|
|
250
|
+
* (`date.toISOString()`, `[...map]`) and let the consuming step rebuild it.
|
|
251
|
+
*
|
|
242
252
|
* ```ts
|
|
243
253
|
* import { codeTool, defineAgent, functionTool } from "@lunora/agent";
|
|
244
254
|
*
|
|
@@ -344,8 +354,14 @@ interface FunctionToolOptions<Input> {
|
|
|
344
354
|
* ```
|
|
345
355
|
*
|
|
346
356
|
* The function reference may be a typed `api.*` reference or a `"module:name"`
|
|
347
|
-
* path. The model-provided input is passed
|
|
348
|
-
* `inputSchema` should mirror the referenced function's argument validator
|
|
357
|
+
* path. The model-provided input is passed as the function's args, so
|
|
358
|
+
* `inputSchema` should mirror the referenced function's argument validator —
|
|
359
|
+
* PLUS the call's `idempotencyKey`, pinned onto the args after the model
|
|
360
|
+
* input (so out-of-schema model input can never override it). A function
|
|
361
|
+
* that wants to dedupe a side-effecting call across an at-least-once step
|
|
362
|
+
* retry declares `idempotencyKey: v.optional(v.string())` in its own args
|
|
363
|
+
* and checks it; a function that ignores it is unaffected — an args field
|
|
364
|
+
* the function's own validator doesn't declare is dropped, not rejected.
|
|
349
365
|
* @experimental
|
|
350
366
|
*/
|
|
351
367
|
declare const functionTool: <Input extends Record<string, unknown> = Record<string, unknown>, Output = unknown>(reference: AgentFunctionReference | string, options: FunctionToolOptions<Input>) => AgentToolDefinition<Input, Output>;
|
|
@@ -471,6 +487,17 @@ interface McpToolsOptions {
|
|
|
471
487
|
command?: string;
|
|
472
488
|
/** Identify this client to the server on connect. Default `"lunora-agent"`. */
|
|
473
489
|
name?: string;
|
|
490
|
+
/**
|
|
491
|
+
* Gate an adapted tool's call behind a human approval. Defaults to
|
|
492
|
+
* **unattended** (no gate) — matching today's behavior. An MCP tool's
|
|
493
|
+
* result feeds back into the model's context (`adaptMcpResult`), so a
|
|
494
|
+
* hostile downstream server can pair indirect prompt injection with an
|
|
495
|
+
* unattended mutating tool call; pass a boolean to gate every adapted
|
|
496
|
+
* tool the same way, or a predicate `(toolName, input) => boolean` to
|
|
497
|
+
* gate per tool (evaluated from replay-stable input, so keep it
|
|
498
|
+
* deterministic).
|
|
499
|
+
*/
|
|
500
|
+
needsApproval?: ((toolName: string, input: Record<string, unknown>) => boolean) | boolean;
|
|
474
501
|
/** Only adapt these tool names (default: every tool the server lists). */
|
|
475
502
|
only?: ReadonlyArray<string>;
|
|
476
503
|
/** Prefix added to each adapted tool's key (disambiguate multiple servers). */
|
|
@@ -510,6 +537,9 @@ declare const adaptMcpResult: (result: McpCallResult) => unknown;
|
|
|
510
537
|
* every call. In the Workers runtime only the HTTP/SSE transports run (stdio
|
|
511
538
|
* does not) — pass `url`, or inject an already-connected `client` for a custom
|
|
512
539
|
* transport (also the test seam).
|
|
540
|
+
*
|
|
541
|
+
* Every adapted tool runs UNATTENDED by default (no approval gate) — pass
|
|
542
|
+
* `opts.needsApproval` to change that; see {@link McpToolsOptions.needsApproval}.
|
|
513
543
|
* @experimental
|
|
514
544
|
*/
|
|
515
545
|
declare const mcpTools: (options: McpToolsOptions) => Promise<Record<string, AgentToolDefinition<Record<string, unknown>>>>;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{runAgentLoop as t,splitForCompaction as r}from"./packem_shared/runAgentLoop-
|
|
1
|
+
import{runAgentLoop as t,splitForCompaction as r}from"./packem_shared/runAgentLoop-6fGTajbG.mjs";import{collectAgenticMemoryTools as a,toSearchResults as i}from"./packem_shared/collectAgenticMemoryTools-UE8gWzQU.mjs";import{agentAsTool as l}from"./packem_shared/agentAsTool-D5iLpvYU.mjs";import{codeTool as p}from"./packem_shared/codeTool-B1_HVhnJ.mjs";import{agentComponent as c,agentExtension as x}from"./component.mjs";import{default as A}from"./packem_shared/createAgentContext-CfD3hIZ2.mjs";import{defineAgent as d,defineAgentTool as u,isAgentDefinition as N}from"./packem_shared/defineAgent-Bqj9exe-.mjs";import{functionTool as D}from"./packem_shared/functionTool-DbrqDql3.mjs";import{createAgentGenerate as M,createEpisodeExtract as O,createGraphExtract as _,createStreamGenerate as C,resolveAgentModel as G}from"./packem_shared/createAgentGenerate-9bZ2YhpN.mjs";import{adaptMcpResult as F,mcpTools as L}from"./packem_shared/adaptMcpResult-CVlq-_TO.mjs";import{buildModelMessages as k}from"./packem_shared/buildModelMessages-Y4tGo1T9.mjs";import{agentBindingName as R,agentClassName as V,agentDefaultName as b,voiceBindingName as h,voiceClassName as w}from"./naming.mjs";import{AGENT_MODULE as I,DEFAULT_AGENT_FUNCTION_PATHS as P,SANDBOX_INVOKE_PATH as X,SANDBOX_MODULE as y,toFunctionReference as K}from"./packem_shared/AGENT_MODULE-CLaSQy3P.mjs";import{browserTool as j,containerTool as q,fsTool as z}from"./sandbox.mjs";import{defineSkill as Q,isSkillDefinition as Y}from"./packem_shared/defineSkill-DGGvDWNq.mjs";import{default as $}from"./packem_shared/VoiceSessionDO-A6u5NXI1.mjs";import{r as oe}from"./packem_shared/voice-turn-DXT1uMUn.mjs";import{default as re}from"./packem_shared/compileAgentWorkflow-BvkRUzx_.mjs";export{I as AGENT_MODULE,P as DEFAULT_AGENT_FUNCTION_PATHS,X as SANDBOX_INVOKE_PATH,y as SANDBOX_MODULE,$ as VoiceSessionDO,F as adaptMcpResult,l as agentAsTool,R as agentBindingName,V as agentClassName,c as agentComponent,b as agentDefaultName,x as agentExtension,j as browserTool,k as buildModelMessages,p as codeTool,a as collectAgenticMemoryTools,re as compileAgentWorkflow,q as containerTool,A as createAgentContext,M as createAgentGenerate,O as createEpisodeExtract,_ as createGraphExtract,C as createStreamGenerate,d as defineAgent,u as defineAgentTool,Q as defineSkill,z as fsTool,D as functionTool,N as isAgentDefinition,Y as isSkillDefinition,L as mcpTools,G as resolveAgentModel,t as runAgentLoop,oe as runVoiceTurn,r as splitForCompaction,K as toFunctionReference,i as toSearchResults,h as voiceBindingName,w as voiceClassName};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createAi as g}from"@lunora/ai";import{
|
|
1
|
+
import{createAi as g}from"@lunora/ai";import{H as b}from"./createDispatchRunner-CGafifJ7-C__lmjdK.mjs";import{t as m}from"./base64-5eyBfWO3.mjs";import{p as A,d as S,a as v,i as l,b as f,c as w,e as k,f as x,r as T,t as E}from"./voice-turn-DXT1uMUn.mjs";import{createStreamGenerate as M}from"./createAgentGenerate-9bZ2YhpN.mjs";import{DEFAULT_AGENT_FUNCTION_PATHS as B,toFunctionReference as p}from"./AGENT_MODULE-CLaSQy3P.mjs";const _="@cf/openai/whisper-large-v3-turbo",I="@cf/deepgram/aura-1",U=8*1024*1024,D=256*1024,y=15,F=5e3;class O{agent;ai;env;exportName;paths;streamGenerate;sttModel;ttsModel;audioBuffers=new Map;bufferedBytes=new Map;controllers=new Map;state;constructor(t,e,s,r){this.state=t,this.env=e,this.agent=s,this.exportName=r,this.paths=B,this.ai=g({binding:e.AI,env:e}),this.streamGenerate=M(s,e),this.sttModel=s.voice?.stt??_,this.ttsModel=s.voice?.tts??I}fetch(t){if(t.headers.get("Upgrade")!=="websocket")return new Response("Expected a WebSocket upgrade",{status:426});const s=new URL(t.url).searchParams.get("threadKey");if(!s)return new Response("Missing threadKey",{status:400});const r=globalThis.WebSocketPair,i=new r,n=i[0],o=i[1];this.state.acceptWebSocket(o);const c=crypto.randomUUID(),d=A(t.headers.get("x-lunora-identity")),a=S(t.headers.get("x-lunora-userid")),h=v(t.headers.get("x-lunora-identity-exp"));if(l(h))return f(o),new Response(null,{status:101,webSocket:n});o.serializeAttachment?.({connectionId:c,threadKey:s,turn:0,...h===void 0?{}:{expiresAt:h},...d===void 0?{}:{identity:d},...a===void 0?{}:{userId:a}}),this.send(o,{audioFormat:this.agent.voice?.audioFormat??"mp3",type:"ready"});const u=this.agent.voice?.greeting;return u&&u.length>0&&this.state.waitUntil?.(this.speakGreeting(o,c,s,a,d,u)),new Response(null,{status:101,webSocket:n})}async webSocketMessage(t,e){const s=t.deserializeAttachment?.();if(s){if(l(s.expiresAt)){f(t);return}try{if(typeof e=="string"){await this.handleControl(t,s,e);return}this.bufferAudio(s.connectionId,new Uint8Array(e),t)}catch(r){this.send(t,{message:r instanceof Error?r.message:String(r),type:"error"})}}}webSocketClose(t){this.cleanupSocket(t)}webSocketError(t){this.cleanupSocket(t)}resolveRun(t,e){const s=t===void 0&&e===void 0?void 0:{...e===void 0?{}:{claims:e},...t===void 0?{}:{userId:t}};return b({env:this.env,label:"@lunora/agent voice",...s===void 0?{}:{identity:s}})}async transcribe(t){const e=w(t);return k(await this.ai.run(this.sttModel,{audio:m(e)}))}async synthesize(t,e){const s=this.agent.voice?.speaker;return x(await this.ai.run(this.ttsModel,{text:t,...s===void 0?{}:{speaker:s}},e===void 0?void 0:{signal:e}))}async handleControl(t,e,s){let r;try{r=JSON.parse(s)}catch{return}if(r.type==="interrupt"){this.controllers.get(e.connectionId)?.abort();return}if(this.controllers.has(e.connectionId)){this.send(t,{message:"a turn is already in progress — send an interrupt before the next utterance",type:"error"});return}if(r.type==="commit"){const i=this.drainAudio(e.connectionId);await this.runTurn(t,e,{pcm:i});return}await this.runTurn(t,e,{text:r.text})}bufferAudio(t,e,s){const r=(this.bufferedBytes.get(t)??0)+e.byteLength;if(r>U){this.audioBuffers.delete(t),this.bufferedBytes.delete(t),this.send(s,{message:"utterance exceeded the maximum buffer — send a commit sooner",type:"error"});return}const i=this.audioBuffers.get(t)??[];i.push(e),this.audioBuffers.set(t,i),this.bufferedBytes.set(t,r)}drainAudio(t){const e=this.audioBuffers.get(t)??[];this.audioBuffers.delete(t),this.bufferedBytes.delete(t);const s=e.reduce((n,o)=>n+o.byteLength,0),r=new Uint8Array(s);let i=0;for(const n of e)r.set(n,i),i+=n.byteLength;return r}async runTurn(t,e,s){const r=new AbortController;this.controllers.set(e.connectionId,r);try{await T({agent:this.agent,connectionId:e.connectionId,env:this.env,exportName:this.exportName,paths:this.paths,run:this.resolveRun(e.userId,e.identity),send:i=>{this.send(t,i)},sendAudio:i=>{this.sendAudio(t,i)},signal:r.signal,streamGenerate:this.streamGenerate,synthesize:async(i,n)=>this.synthesizeWithSignal(i,n),threadKey:e.threadKey,transcribe:async i=>this.transcribe(i),turn:e.turn,waitForDrain:async()=>this.waitForSocketDrain(t),...e.userId===void 0?{}:{owner:e.userId},...s.pcm===void 0?{}:{pcm:s.pcm},...s.text===void 0?{}:{text:s.text}})}finally{this.controllers.get(e.connectionId)===r&&this.controllers.delete(e.connectionId),t.serializeAttachment?.({...e,turn:e.turn+1})}}async speakGreeting(t,e,s,r,i,n){const o=this.resolveRun(r,i),c=new AbortController,d=()=>c.signal.aborted;this.controllers.set(e,c);try{await o(p(this.paths.ensureThread),{agent:this.exportName,key:s,...this.agent.initialState===void 0?{}:{initialState:this.agent.initialState},...r===void 0?{}:{owner:r}});for await(const a of E(await this.synthesizeWithSignal(n,c.signal))){if(d()||(await this.waitForSocketDrain(t),d()))break;this.sendAudio(t,a)}d()||(await o(p(this.paths.appendMessage),{content:n,messageKey:"voice:greeting:assistant",role:"assistant",threadKey:s}),this.send(t,{text:n,type:"assistant_done"}))}catch(a){this.send(t,{message:a instanceof Error?a.message:String(a),type:"error"})}finally{this.controllers.get(e)===c&&this.controllers.delete(e)}}async synthesizeWithSignal(t,e){return e.aborted?new Uint8Array(0):this.synthesize(t,e)}cleanupSocket(t){const e=t.deserializeAttachment?.();e&&(this.controllers.get(e.connectionId)?.abort(),this.controllers.delete(e.connectionId),this.audioBuffers.delete(e.connectionId),this.bufferedBytes.delete(e.connectionId))}send(t,e){try{t.send(JSON.stringify(e))}catch{}}sendAudio(t,e){try{t.send(e)}catch{}}async waitForSocketDrain(t){const e=t;let s=0;for(;typeof e.bufferedAmount=="number"&&e.bufferedAmount>D&&s<F;)await new Promise(r=>{setTimeout(r,y)}),s+=y}}export{O as default};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{LunoraError as c}from"@lunora/errors";import{jsonSchema as i}from"ai";const s=t=>{if(t.structuredContent!==void 0)return t.structuredContent;const n=(t.content??[]).filter(e=>e.type==="text"&&typeof e.text=="string").map(e=>e.text).join(`
|
|
2
|
+
`);return t.isError===!0?`MCP tool error: ${n.length>0?n:"unknown error"}`:n.length>0?n:t.content},l=(t,n,e)=>({description:n.description??`MCP tool "${n.name}".`,execute:async r=>s(await t.callTool({arguments:r,name:n.name})),inputSchema:i(n.inputSchema),isLunoraAgentTool:!0,...e===void 0?{}:{needsApproval:typeof e=="function"?r=>e(n.name,r):e}}),u=async t=>{if(t.command!==void 0)throw new c("INTERNAL","@lunora/agent: mcpTools `command` (stdio transport) cannot run in the Workers runtime — pass a `url` for an HTTP/SSE MCP server, or inject a connected `client`");if(t.url===void 0)throw new c("INTERNAL","@lunora/agent: mcpTools requires a `url` (an HTTP/SSE MCP server) or an injected `client`");const n=new URL(t.url),{Client:e}=await import("@modelcontextprotocol/sdk/client/index.js");let r;if(t.transport==="sse"){const{SSEClientTransport:a}=await import("@modelcontextprotocol/sdk/client/sse.js");r=new a(n)}else{const{StreamableHTTPClientTransport:a}=await import("@modelcontextprotocol/sdk/client/streamableHttp.js");r=new a(n)}const o=new e({name:t.name??"lunora-agent",version:t.version??"0.0.0"});return await o.connect(r),o},T=async t=>{const n=t.client??await u(t),{tools:e}=await n.listTools(),r={};for(const o of e)t.only!==void 0&&!t.only.includes(o.name)||(r[`${t.prefix??""}${o.name}`]=l(n,o,t.needsApproval));return r};export{s as adaptMcpResult,T as mcpTools};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as a}from"@lunora/errors";import{jsonSchema as A}from"ai";const $=16,y=4e3,b=e=>{if(e===void 0)return e;const o=typeof e=="string"?e:JSON.stringify(e);return o.length<=y?e:`${o.slice(0,y)}… [truncated]`},T=(e,o)=>{let t=e;for(const s of o.split(".")){if(t===null||typeof t!="object"||!Object.hasOwn(t,s))return;t=t[s]}return t},c=(e,o)=>{if(Array.isArray(e))return e.map(r=>c(r,o));if(e===null||typeof e!="object")return e;const t=e;if(typeof t.$from=="string"){const r=t.$from;if(!(r in o))throw new a("BAD_REQUEST",`@lunora/agent: code step references unknown result "${r}" (define it in an earlier step)`);return typeof t.$path=="string"?T(o[r],t.$path):o[r]}const s={};for(const[r,i]of Object.entries(t))s[r]=c(i,o);return s},g=async(e,o,t,s)=>{const r=Array.isArray(e.steps)?e.steps.slice(0,s):[],i={},p=[],d=new Set;for(const n of r){if(d.has(n.id))throw new a("BAD_REQUEST",`@lunora/agent: duplicate code step id "${n.id}" — each step id must be unique (later steps reference an output by id via $from)`);d.add(n.id)}for(const n of r){const l=o[n.tool];if(!l)throw new a("BAD_REQUEST",`@lunora/agent: code step calls unknown tool "${n.tool}" (available: ${Object.keys(o).join(", ")})`);const m=c(n.input??{},i),f={...t,idempotencyKey:`${t.idempotencyKey}:${n.id}`,toolCallId:`${t.toolCallId}:${n.id}`},h=()=>Promise.resolve(l.execute(m,f)),u=await t.step.do(f.idempotencyKey,h);i[n.id]=u,p.push({id:n.id,output:b(u)})}return{final:p.at(-1)?.output,results:p}},v=e=>`Compose MULTIPLE tool calls in one turn as a script, instead of one call per turn. Provide \`steps\`: an ordered array of \`{ id, tool, input }\`. A later step's \`input\` may reference an earlier step's output with \`{ "$from": "<stepId>", "$path": "optional.dot.path" }\`. Available tools: ${Object.entries(e).map(([o,t])=>`"${o}" — ${t.description}`).join("; ")}.`,w=A({properties:{steps:{description:"Ordered tool calls; a later input may reference an earlier output via { $from, $path }.",items:{additionalProperties:!1,properties:{id:{description:"A name later steps reference this output by.",type:"string"},input:{additionalProperties:!0,description:"The tool input (may embed $from refs).",type:"object"},tool:{description:"The tool to call.",type:"string"}},required:["id","tool"],type:"object"},type:"array"}},required:["steps"],type:"object"}),S=(e,o={})=>{const t=e;if(!t||typeof t!="object"||Object.keys(t).length===0)throw new a("INTERNAL","@lunora/agent: codeTool requires a non-empty map of tools to compose");for(const[r,i]of Object.entries(t))if(i.needsApproval!==void 0&&i.needsApproval!==!1)throw new a("INTERNAL",`@lunora/agent: codeTool cannot compose "${r}" — it has a \`needsApproval\` gate a code-mode script can't pause for. Expose it as a normal top-level tool, or gate the whole script via codeTool's \`needsApproval\`.`);const s=o.maxSteps??$;return{description:o.description??v(e),execute:(r,i)=>g(r,e,i,s),inputSchema:w,isLunoraAgentTool:!0,...o.needsApproval===void 0?{}:{needsApproval:o.needsApproval}}};export{S as codeTool,c as resolveReferences,g as runToolScript};
|
package/dist/packem_shared/{compileAgentWorkflow-O_Kvw_Ze.mjs → compileAgentWorkflow-BvkRUzx_.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{defineWorkflow as s}from"@lunora/workflow";import{runAgentLoop as m}from"./runAgentLoop-
|
|
1
|
+
import{defineWorkflow as s}from"@lunora/workflow";import{runAgentLoop as m}from"./runAgentLoop-6fGTajbG.mjs";import{createStreamGenerate as p,createAgentGenerate as l,createEpisodeExtract as f,createGraphExtract as d,createCompact as u}from"./createAgentGenerate-9bZ2YhpN.mjs";import{agentDefaultName as c}from"../naming.mjs";import{DEFAULT_AGENT_FUNCTION_PATHS as A}from"./AGENT_MODULE-CLaSQy3P.mjs";import{H as T}from"./createDispatchRunner-CGafifJ7-C__lmjdK.mjs";import{otlpTelemetry as y}from"./otlpTelemetry-yAjOjxn0.mjs";const E=(r,t,a)=>t===void 0?r:T({env:a,identity:{userId:t},label:"@lunora/agent"}),O=(r,t,a)=>{const e=t.LUNORA_OTLP_ENDPOINT;if(typeof e!="string"||e===""||r.telemetry?.isEnabled===!1)return r;const n=typeof t.LUNORA_OTLP_TOKEN=="string"?t.LUNORA_OTLP_TOKEN:void 0,i=[r.telemetry?.integrations].flat().filter(o=>o!==void 0);return{...r,telemetry:{...r.telemetry,integrations:[...i,y({conversationId:a,endpoint:e,token:n})],isEnabled:!0}}},I=(r,t,a)=>s({handler:async e=>{const n=O(r,e.env,e.params.threadKey);return m({agent:n,compact:u(),env:e.env,exportName:t,extractGraph:d(),extractEpisode:f(),generate:l(n,e.env),instanceId:e.event.instanceId,params:e.params,paths:a?.paths??A,run:E(e.run,e.params.owner,e.env),step:e.step,streamGenerate:p(n,e.env)})},name:r.name??c(t)});export{I as default};
|
package/dist/packem_shared/{createAgentContext-HUKAccII.mjs → createAgentContext-CfD3hIZ2.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{H as g}from"./createDispatchRunner-CGafifJ7-C__lmjdK.mjs";import{LunoraError as o}from"@lunora/errors";import{h as l,B as p}from"./branch-marker-boZ00zmk.mjs";import{toFunctionReference as w,DEFAULT_AGENT_FUNCTION_PATHS as m}from"./AGENT_MODULE-CLaSQy3P.mjs";const T=(r,s,i)=>{const c={},u=w(m.patchThread),d=()=>i??g({env:r,label:"@lunora/agent"});for(const e of s){const a=()=>{const n=r[e.binding];if(!n||typeof n.create!="function"||typeof n.get!="function")throw new o("INTERNAL",`@lunora/agent: no Workflow binding "${e.binding}" on env for agent "${e.exportName}" — run codegen/dev so wrangler.jsonc declares it`);return n};c[e.exportName]={cancel:async n=>{await(await a().get(n)).terminate();try{await d()(u,{instanceId:n,status:"cancelled"})}catch{}},publicRun:e.publicRun===!0,run:async(n,t)=>{if(l(n))throw new o("BAD_REQUEST",`@lunora/agent: run input ${p}`);return{id:(await a().create({...t?.id===void 0?{}:{id:t.id},params:n})).id}},sendEvent:async(n,t)=>{await(await a().get(n)).sendEvent(t)},status:async n=>(await a().get(n)).status()}}return c};export{T as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as i}from"@lunora/errors";const O=t=>{let e="";for(let n=0;n<t.length;n+=32768)e+=String.fromCharCode(...t.subarray(n,n+32768));return btoa(e)},m=t=>O(t).replaceAll("+","-").replaceAll("/","_").replace(/=+$/,"");new TextDecoder;const b=new TextEncoder,g="=",A=t=>{for(let e=0;e<t.length;e+=1)if(t.charCodeAt(e)>255)return!1;return!0},R=t=>m(b.encode(JSON.stringify(t))),T=t=>!t.startsWith(g)&&A(t)?t:`${g}${m(b.encode(t))}`,_="/_lunora/scheduler/dispatch",L=3e4,S=t=>{let e=t.length;for(;e>0&&t[e-1]==="/";)e-=1;return t.slice(0,e)},v=Symbol("lunoraDispatchFailure"),E=Symbol("lunoraDispatchMessageId"),N=(t,e)=>(Object.defineProperty(t,v,{value:!0}),e!==void 0&&Object.defineProperty(t,E,{value:e}),t),x=(t,e,n,c)=>{try{const o=JSON.parse(n)?.error;if(typeof o=="object"&&o!==null&&typeof o.code=="string"){const{code:h,data:l,message:s}=o;return N(new i(h,typeof s=="string"?s:void 0,{data:l,status:e}),c)}}catch{}return N(new i("INTERNAL",`${t}: function dispatch failed (${String(e)}): ${n}`,{status:e}),c)},U=(t,e,n)=>new i("INTERNAL",`${t}: function dispatch to "${e}" timed out after ${String(n)}ms`,{status:503}),J=t=>{const{label:e}=t,n=globalThis.fetch,c=t.fetchImpl??(typeof n=="function"?n.bind(globalThis):void 0);return async(o,h,l={})=>{if(typeof c!="function")throw new TypeError(`${e}: no fetch implementation available — pass fetchImpl or run on a platform with global fetch`);const s=t.env.LUNORA_ORIGIN_URL;if(typeof s!="string"||s.length===0)throw new i("INTERNAL",`${e}: \`LUNORA_ORIGIN_URL\` must be set on the Worker env so a handler can call back into Lunora functions`);const f=t.env.LUNORA_ADMIN_TOKEN;if(typeof f!="string"||f.length===0)throw new i("INTERNAL",`${e}: \`LUNORA_ADMIN_TOKEN\` must be set on the Worker env to authenticate function dispatch`);const w=`${S(s)}${_}`,d={authorization:`Bearer ${f}`,"content-type":"application/json"};t.identity?.userId!==void 0&&(d["x-lunora-userid"]=T(t.identity.userId)),t.identity?.claims!==void 0&&(d["x-lunora-identity"]=R(t.identity.claims));const y=l.timeoutMs??L,$=AbortSignal.timeout(y),p=r=>{throw r instanceof Error&&r.name==="TimeoutError"?U(e,o.__lunoraRef,y):r};let a;try{a=await c(w,{body:JSON.stringify({args:h??{},functionPath:o.__lunoraRef,shardKey:l.shardKey}),headers:d,method:"POST",signal:$})}catch(r){return p(r)}if(!a.ok){let r;try{r=await a.text()}catch(I){return p(I)}throw x(e,a.status,r,l.messageId)}let u;try{u=await a.text()}catch(r){return p(r)}if(u.length!==0)try{return JSON.parse(u)}catch{throw new i("INTERNAL",`${e}: function dispatch returned a non-JSON body (${String(a.status)}): ${u}`,{status:a.status})}}};export{J as H};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as o}from"@lunora/errors";import{toFunctionReference as c}from"./AGENT_MODULE-CLaSQy3P.mjs";const m=(r,e)=>{if(typeof e.description!="string"||e.description.length===0)throw new o("INTERNAL","@lunora/agent: functionTool requires a non-empty `description` (the model decides from it)");if(e.inputSchema===void 0)throw new o("INTERNAL","@lunora/agent: functionTool requires an `inputSchema` (a zod schema or `jsonSchema(...)`)");const t=c(r);return{description:e.description,execute:(i,n)=>n.run(t,{...i,idempotencyKey:n.idempotencyKey}),inputSchema:e.inputSchema,isLunoraAgentTool:!0}};export{m as functionTool};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{d as z}from"./component-shared-Cn6E5d_q.mjs";import{resolveAgentModel as J}from"./createAgentGenerate-9bZ2YhpN.mjs";import{r as Q,f as W,m as
|
|
1
|
+
import{d as z}from"./component-shared-Cn6E5d_q.mjs";import{resolveAgentModel as J}from"./createAgentGenerate-9bZ2YhpN.mjs";import{r as Q,f as W,m as x,a as X}from"./memory-JI0lUu84.mjs";import{buildModelMessages as F}from"./buildModelMessages-Y4tGo1T9.mjs";import{agentBindingName as D}from"../naming.mjs";import{toFunctionReference as g}from"./AGENT_MODULE-CLaSQy3P.mjs";const V=8,G=e=>e===void 0?"null":JSON.stringify(e),Y=e=>e===void 0?[]:[e].flat(),Z=async(e,t)=>(await Promise.all(e.map(async o=>o({steps:t})))).some(Boolean),tt=(e,t)=>{if(t===void 0)return e;if(e===void 0)return{...t};const n={};for(const o of["inputTokens","outputTokens","totalTokens"])(e[o]!==void 0||t[o]!==void 0)&&(n[o]=(e[o]??0)+(t[o]??0));return n},et=async(e,t,n,o,a)=>{const{needsApproval:r}=e;return r===void 0||r===!1?!1:r===!0?!0:n.do(o,async()=>r(t,a))},ot=async(e,t)=>{const{instanceId:n,patchThread:o,persist:a,step:r}=e;await a({content:`Awaiting approval to run tool "${t.name}".`,messageKey:`${n}:approval:${t.id}`,role:"tool",status:"awaiting_approval",toolCallId:t.id,toolName:t.name}),await o({status:"awaiting_input"});const i=await r.waitForEvent(`approval:${t.id}`,{type:`agent-approval:${t.id}`});return await o({status:"running"}),{decision:i.payload.decision,...i.payload.note===void 0?{}:{note:i.payload.note}}},nt=async(e,t)=>{const{env:n,getState:o,instanceId:a,onTokenDelta:r,persist:i,run:d,setState:c,step:l,threadKey:s,tools:p}=e,u=`tool:${t.name}:${t.id}`,m=p[t.name],f=`${a}:tool:${t.id}`;if(!m){await i({content:`Error: unknown tool "${t.name}"`,messageKey:f,role:"tool",stepName:u,toolCallId:t.id,toolName:t.name});return}const S={env:n,getState:o,idempotencyKey:u,reportProgress:$=>{r?.({data:$,kind:"progress",threadKey:s,toolCallId:t.id})},run:d,setState:c,step:l,threadKey:s,toolCallId:t.id},v={env:n,getState:o,idempotencyKey:u,run:d,threadKey:s,toolCallId:t.id},C=`tool:approval-gate:${t.id}`;let h;if(await et(m,t.input,l,C,v)){const{decision:$,note:R}=await ot(e,t);if($==="reject"){const I=R===void 0?"":` Reason: ${R}`;await i({content:`Tool "${t.name}" was rejected by the user and not run.${I}`,messageKey:f,role:"tool",status:"rejected",stepName:u,toolCallId:t.id,toolName:t.name});return}h="approved"}const k=await l.do(u,()=>Promise.resolve(m.execute(t.input,S)));await i({content:typeof k=="string"?k:G(k),messageKey:f,role:"tool",stepName:u,...h===void 0?{}:{status:h},toolCallId:t.id,toolName:t.name})},at=(e,t,n)=>{if(!t)return e;let{messages:o}=e;return t.messages!==void 0&&(o=t.messages),t.system!==void 0&&(o=[{content:t.system,role:"system"},...o]),{activeTools:t.activeTools??e.activeTools,messages:o,model:t.model===void 0?e.model:J(t.model,n),toolChoice:t.toolChoice??e.toolChoice}},st=(e,t)=>{if(t===void 0||e.length<=t.maxMessages)return;const n=Math.max(1,t.keepRecent??Math.ceil(t.maxMessages/2));if(e.length<=n)return;let o=e.length-n;for(;o>0&&e[o]?.role==="tool";)o-=1;if(!(o<=0))return{older:e.slice(0,o),recent:e.slice(o)}},rt=async(e,t)=>{const{agent:n,compact:o,env:a}=e,r=st(t,n.compaction);if(r===void 0||o===void 0)return{history:t,summary:void 0};try{const i=await o({env:a,messages:F({history:r.older}),model:n.compaction?.model??n.model});return i.length>0?{history:r.recent,summary:i}:{history:t,summary:void 0}}catch{return{history:t,summary:void 0}}},it=async(e,t,n)=>{const{agent:o,env:a,generate:r,instructions:i,listMessages:d,memoryContext:c,onTokenDelta:l,run:s,step:p,streamGenerate:u,threadKey:m}=e;return p.do(`llm:turn:${String(t)}`,async()=>{const f=await s(d,{key:m}),{history:T,summary:S}=await rt(e,f);let v={activeTools:o.activeTools,messages:F({history:T,instructions:i,memoryContext:c,summary:S}),model:void 0,toolChoice:o.toolChoice};o.prepareStep&&(v=at(v,await o.prepareStep({messages:v.messages,stepNumber:t,steps:n}),a));const C={messages:v.messages,...v.activeTools===void 0?{}:{activeTools:v.activeTools},...v.model===void 0?{}:{model:v.model},...v.toolChoice===void 0?{}:{toolChoice:v.toolChoice}};return u&&l?u(C,h=>{l({text:h,threadKey:m,turn:t})}):r(C)})},q=async(e,t)=>{const{agent:n,step:o}=e;n.onStepFinish&&await o.do(`agent:step-finish:${String(t.turn)}`,async()=>(await n.onStepFinish?.(t),!0))},ct=e=>({text:e.text,toolCalls:e.toolCalls.map(t=>({input:t.input,toolCallId:t.id,toolName:t.name})),...e.usage===void 0?{}:{usage:e.usage}}),A=e=>{const t=e?.context;return typeof t=="string"&&t.length>0?t:void 0},ut=e=>z({depth:e?.depth,fanOut:e?.fanOut,maxNodes:e?.maxNodes,maxSeeds:e?.maxSeeds}),dt=async(e,t,n,o)=>{if(e.source===void 0)return;const a=g(e.source),{topK:r}=e,i=x("memory:retrieve",e.key),d=await n.do(i,async()=>o(a,{query:t,...r===void 0?{}:{topK:r}}));return A(d)},pt=async(e,t,n,o,a,r)=>{if(n===void 0)return;const i=x("memory:traverse",e.key),d=await a.do(i,async()=>r(o,{owner:n,query:t,...ut(e.graph)}));return A(d)},lt=async(e,t,n,o,a)=>{if(t===void 0)return;const r=x("memory:recall",e.key),i={owner:t,...e.episodic?.recall===void 0?{}:{limit:e.episodic.recall}},d=await o.do(r,async()=>a(n,i));return A(d)},mt=async(e,t)=>e.kind==="episodic"?lt(e,t.owner,t.episodeRecall,t.step,t.run):e.kind==="graph"?pt(e,t.input,t.owner,t.graphTraverse,t.step,t.run):dt(e,t.input,t.step,t.run),yt=e=>{const t=e.findIndex(n=>n.kind==="episodic");return e.filter((n,o)=>n.kind!=="episodic"||o===t)},vt=async(e,t,n,o,a,r)=>{const i=yt(Q(e));if(i.length===0)return;const d=g(o.graphTraverse),c=g(o.episodeRecall),l=[];for(const s of i){const p=await mt(s,{episodeRecall:c,graphTraverse:d,input:t,owner:n,run:r,step:a});p!==void 0&&l.push(p)}return l.length>0?l.join(`
|
|
2
2
|
|
|
3
|
-
`):void 0},gt=async e=>{const{agent:t,env:n,extractGraph:o,finalText:a,input:r,instanceId:i,owner:d,paths:c,run:l,step:s}=e;if(o===void 0||d===void 0||a===void 0||a.length===0)return;const p=W(t);if(p!==void 0)try{const u={assistantText:a,env:n,model:p.graph?.extractionModel??t.model,userInput:r},m=await s.do(
|
|
3
|
+
`):void 0},gt=async e=>{const{agent:t,env:n,extractGraph:o,finalText:a,input:r,instanceId:i,owner:d,paths:c,run:l,step:s}=e;if(o===void 0||d===void 0||a===void 0||a.length===0)return;const p=W(t);if(p!==void 0)try{const u={assistantText:a,env:n,model:p.graph?.extractionModel??t.model,userInput:r},m=await s.do(x("memory:extract",p.key),async()=>o(u));await l(g(c.graphUpsert),{...m,messageKey:`${i}:${x("extract",p.key)}`,owner:d})}catch{}},ft=async e=>{const{agent:t,env:n,extractEpisode:o,finalText:a,input:r,instanceId:i,owner:d,paths:c,run:l,step:s,threadKey:p}=e;if(o===void 0||d===void 0||a===void 0||a.length===0)return;const u=X(t);if(u!==void 0)try{const m={assistantText:a,env:n,model:u.episodic?.extractionModel??t.model,userInput:r},{summary:f}=await s.do(x("memory:episode",u.key),async()=>o(m));await l(g(c.episodeUpsert),{messageKey:`${i}:${x("episode",u.key)}`,owner:d,summary:f,threadKey:p})}catch{}},ht=async(e,t,n)=>{const o=e[D(t)];if(!(!o||typeof o.get!="function"))try{await(await o.get(n)).terminate()}catch{}},wt="12 hours",xt=async(e,t,n)=>{await e.waitForEvent(`dequeue:${n}`,{timeout:wt,type:`agent-dequeue:${t}:${n}`})},Tt=async(e,t,n)=>{const o=e.env[D(e.exportName)];if(!o||typeof o.get!="function")return;const a=o.get.bind(o);try{await e.step.do(`dequeue-wake:${n}`,async()=>(await(await a(n)).sendEvent({payload:{threadKey:t},type:`agent-dequeue:${t}:${n}`}),n))}catch{}},Ct=async(e,t,n)=>{const{onReply:o}=e,{replyRef:a}=t.params;if(!(o===void 0||a===void 0))try{await t.step.do("agent:reply",async()=>(await o({env:t.env,replyRef:a,result:n,threadKey:t.params.threadKey}),a.channel))}catch{}},St=async(e,t,n,o,a)=>{const{instanceId:r,persist:i}=e,d=n.usage===void 0?{}:{usage:n.usage};if(n.toolCalls.length===0){const c=n.output!==void 0&&n.text.length===0?G(n.output):n.text;return await i({content:c,messageKey:`${r}:assistant:${String(t)}`,role:"assistant"}),await q(e,{text:n.text,toolCalls:[],turn:t,...d}),{final:{stopped:"final",text:n.text,turns:t+1,...n.output===void 0?{}:{output:n.output}}}}await i({content:n.text,messageKey:`${r}:assistant:${String(t)}`,role:"assistant",toolCalls:n.toolCalls});for(const c of n.toolCalls)await nt(e,c);if(await q(e,{text:n.text,toolCalls:n.toolCalls,turn:t,...d}),o.push(ct(n)),a.length>0&&await Z(a,o))return"stopCondition"},kt=async(e,t,n,o)=>{const a=[];let r,i=!1,d=0;for(let c=0;c<t;c+=1){const l=await it(e,c,a);o.value=tt(o.value,l.usage),d=c+1;const s=await St(e,c,l,a,n);if(s==="stopCondition"){i=!0;break}if(s!==void 0){r=s.final;break}}return{final:r,stoppedByCondition:i,turnsRun:d}},Et=async e=>{const{agent:t,compact:n,env:o,exportName:a,extractEpisode:r,extractGraph:i,generate:d,instanceId:c,onTokenDelta:l,params:s,paths:p,run:u,step:m,streamGenerate:f}=e,T=t.maxTurns??V,S=Y(t.stopWhen),v=g(p.appendMessage),C=g(p.completeRun),h=g(p.ensureThread),k=g(p.listMessages),$=g(p.patchThread),R=g(p.setState),I=g(p.state),U=async y=>{await u(v,{threadKey:s.threadKey,...y})},P=async y=>{await u($,{key:s.threadKey,...y})},j=async()=>{await U({content:s.input,messageKey:`${c}:user`,role:"user"})},M=async y=>{const N=await u(C,{instanceId:c,key:s.threadKey,...y});N?.dequeued!==void 0&&await Tt({env:o,exportName:a,step:m},s.threadKey,N.dequeued)},B=async()=>await u(I,{key:s.threadKey}),O=async y=>{await u(R,{key:s.threadKey,state:y})},E=await u(h,{agent:a,instanceId:c,key:s.threadKey,...t.initialState===void 0?{}:{initialState:t.initialState},...t.onConcurrentRun===void 0?{}:{onConcurrentRun:t.onConcurrentRun},...s.owner===void 0?{}:{owner:s.owner},...s.title===void 0?{}:{title:s.title}});E?.outcome==="replaced"&&await ht(o,a,E.priorInstanceId);const _=await vt(t,s.input,s.owner,p,m,u),b=typeof t.instructions=="function"?t.instructions({env:o,input:s.input,threadKey:s.threadKey}):t.instructions,H={agent:t,compact:n,env:o,generate:d,getState:B,instanceId:c,instructions:b,listMessages:k,memoryContext:_,onTokenDelta:l,patchThread:P,persist:U,run:u,setState:O,step:m,streamGenerate:f,threadKey:s.threadKey,tools:t.tools??{}},K={value:void 0};try{E?.outcome==="queued"&&await xt(m,s.threadKey,c),await j();const{final:y,stoppedByCondition:N,turnsRun:L}=await kt(H,T,S,K),w=K.value===void 0?{}:{usage:K.value};return await gt({agent:t,env:o,extractGraph:i,finalText:y?.text,input:s.input,instanceId:c,owner:s.owner,paths:p,run:u,step:m}),await ft({agent:t,env:o,extractEpisode:r,finalText:y?.text,input:s.input,instanceId:c,owner:s.owner,paths:p,run:u,step:m,threadKey:s.threadKey}),y?(await Ct(t,{env:o,params:s,step:m},{...y,...w}),await M({status:"idle",...w}),{...y,...w}):N?(await M({status:"idle",...w}),{stopped:"stopCondition",turns:L,...w}):(await M({error:`agent stopped: maxTurns (${String(T)}) reached`,status:"error",...w}),{stopped:"maxTurns",turns:T,...w})}catch(y){throw await M({error:y instanceof Error?y.message:String(y),status:"error",...K.value===void 0?{}:{usage:K.value}}),y}};export{Et as runAgentLoop,st as splitForCompaction};
|
|
@@ -42,10 +42,16 @@ interface AgentStepLike {
|
|
|
42
42
|
* `idempotencyKey`.
|
|
43
43
|
*
|
|
44
44
|
* The `idempotencyKey` is the deterministic durable-step name
|
|
45
|
-
* (`tool:<name>:<toolCallId
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
45
|
+
* (`tool:<name>:<toolCallId>`, further suffixed per script step for a
|
|
46
|
+
* `codeTool`). A COMPLETED tool step is never re-run on a workflow replay
|
|
47
|
+
* (native step memoization) — but a step that FAILS mid-body is retried
|
|
48
|
+
* at-least-once, so a side-effecting tool (charge a card, send a mail) must
|
|
49
|
+
* dedupe on this key itself. `functionTool` forwards it to the dispatched
|
|
50
|
+
* function as `args.idempotencyKey` (pinned after the model input, so it
|
|
51
|
+
* can't be overridden) — a function that wants to dedupe declares
|
|
52
|
+
* `idempotencyKey: v.optional(v.string())` in its own args and checks it; a
|
|
53
|
+
* function that ignores it is unaffected (an undeclared arg field is dropped,
|
|
54
|
+
* not rejected).
|
|
49
55
|
* @experimental
|
|
50
56
|
*/
|
|
51
57
|
interface AgentToolContext {
|
|
@@ -102,22 +108,45 @@ interface AgentToolContext {
|
|
|
102
108
|
* skip the write when it is already present.
|
|
103
109
|
*/
|
|
104
110
|
setState: (state: Record<string, unknown>) => Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* The durable-step handle (`step.do`/`waitForEvent`). ALWAYS present:
|
|
113
|
+
* `agent-loop.ts` threads it into every tool's context unconditionally, and
|
|
114
|
+
* it is required rather than optional so a missing handle is a compile
|
|
115
|
+
* error instead of a silent durability downgrade. `codeTool` uses it to give
|
|
116
|
+
* each script step its OWN nested durable boundary — see `code-tool.ts` — so
|
|
117
|
+
* a failure at script step 3 retries only step 3, not steps 1–2's
|
|
118
|
+
* already-committed side effects. Cloudflare Workflows supports a `step.do`
|
|
119
|
+
* nested inside another `step.do`'s callback (the codeTool call's own
|
|
120
|
+
* enclosing step). Most tools never touch this directly; a test driving
|
|
121
|
+
* `execute`/`runToolScript` by hand passes a pass-through double.
|
|
122
|
+
*/
|
|
123
|
+
step: AgentStepLike;
|
|
105
124
|
/** The thread this tool call belongs to. */
|
|
106
125
|
threadKey: string;
|
|
107
126
|
/** The provider-issued tool-call id. */
|
|
108
127
|
toolCallId: string;
|
|
109
128
|
}
|
|
110
129
|
/**
|
|
111
|
-
* The
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
130
|
+
* The view of {@link AgentToolContext} handed to a `needsApproval` gate
|
|
131
|
+
* function — every field except `setState`, `step`, and `reportProgress`.
|
|
132
|
+
*
|
|
133
|
+
* `setState` is dropped because a gate that mutates thread state is a side
|
|
134
|
+
* effect inside a decision predicate, and `reportProgress` because emitting a
|
|
135
|
+
* live event is the same thing in observable form — the decision is what the
|
|
136
|
+
* loop reports, not the deciding. `step` goes because the loop already runs the
|
|
137
|
+
* gate inside a durable step of its own, so a gate has no business opening
|
|
138
|
+
* another.
|
|
139
|
+
*
|
|
140
|
+
* `getState` and `run` stay: reads are legitimate gate inputs (gate on the
|
|
141
|
+
* caller's plan tier, on a spend total), and the gate resolves inside its own
|
|
142
|
+
* durable step, so they are replay-safe there. Note this makes the type a
|
|
143
|
+
* NARROWING, not a proof of purity — `run` takes any
|
|
144
|
+
* {@link AgentFunctionReference}, so a gate can still dispatch a mutation
|
|
145
|
+
* before approval. Nothing in the type system distinguishes a query reference
|
|
146
|
+
* from a mutation one; keeping the gate side-effect-free is the author's.
|
|
118
147
|
* @experimental
|
|
119
148
|
*/
|
|
120
|
-
type AgentApprovalContext = Omit<AgentToolContext, "setState">;
|
|
149
|
+
type AgentApprovalContext = Omit<AgentToolContext, "reportProgress" | "setState" | "step">;
|
|
121
150
|
/**
|
|
122
151
|
* An agent tool. Unlike a raw AI SDK tool, `execute` is NOT handed to the
|
|
123
152
|
* model call — the loop runs it itself inside a named durable step so a
|
|
@@ -150,9 +179,11 @@ interface AgentToolDefinition<Input = unknown, Output = unknown> {
|
|
|
150
179
|
* from the tool's own step), so it now runs exactly once per call, not once
|
|
151
180
|
* per replay. It must still be otherwise pure: deterministic given its
|
|
152
181
|
* inputs (no `Date.now()`/`Math.random()`) and free of side effects — the
|
|
153
|
-
* context it receives is {@link AgentApprovalContext}, which has
|
|
154
|
-
* `setState`; state writes
|
|
155
|
-
* memoized step.
|
|
182
|
+
* context it receives is {@link AgentApprovalContext}, which has neither
|
|
183
|
+
* `setState` nor `reportProgress`; state writes and progress events belong
|
|
184
|
+
* only in `execute`, inside the tool's own memoized step. It still holds
|
|
185
|
+
* `run`, which the type cannot narrow to reads — see
|
|
186
|
+
* {@link AgentApprovalContext}.
|
|
156
187
|
*/
|
|
157
188
|
needsApproval?: ((input: Input, context: AgentApprovalContext) => boolean | Promise<boolean>) | boolean;
|
|
158
189
|
}
|
|
@@ -42,10 +42,16 @@ interface AgentStepLike {
|
|
|
42
42
|
* `idempotencyKey`.
|
|
43
43
|
*
|
|
44
44
|
* The `idempotencyKey` is the deterministic durable-step name
|
|
45
|
-
* (`tool:<name>:<toolCallId
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
45
|
+
* (`tool:<name>:<toolCallId>`, further suffixed per script step for a
|
|
46
|
+
* `codeTool`). A COMPLETED tool step is never re-run on a workflow replay
|
|
47
|
+
* (native step memoization) — but a step that FAILS mid-body is retried
|
|
48
|
+
* at-least-once, so a side-effecting tool (charge a card, send a mail) must
|
|
49
|
+
* dedupe on this key itself. `functionTool` forwards it to the dispatched
|
|
50
|
+
* function as `args.idempotencyKey` (pinned after the model input, so it
|
|
51
|
+
* can't be overridden) — a function that wants to dedupe declares
|
|
52
|
+
* `idempotencyKey: v.optional(v.string())` in its own args and checks it; a
|
|
53
|
+
* function that ignores it is unaffected (an undeclared arg field is dropped,
|
|
54
|
+
* not rejected).
|
|
49
55
|
* @experimental
|
|
50
56
|
*/
|
|
51
57
|
interface AgentToolContext {
|
|
@@ -102,22 +108,45 @@ interface AgentToolContext {
|
|
|
102
108
|
* skip the write when it is already present.
|
|
103
109
|
*/
|
|
104
110
|
setState: (state: Record<string, unknown>) => Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* The durable-step handle (`step.do`/`waitForEvent`). ALWAYS present:
|
|
113
|
+
* `agent-loop.ts` threads it into every tool's context unconditionally, and
|
|
114
|
+
* it is required rather than optional so a missing handle is a compile
|
|
115
|
+
* error instead of a silent durability downgrade. `codeTool` uses it to give
|
|
116
|
+
* each script step its OWN nested durable boundary — see `code-tool.ts` — so
|
|
117
|
+
* a failure at script step 3 retries only step 3, not steps 1–2's
|
|
118
|
+
* already-committed side effects. Cloudflare Workflows supports a `step.do`
|
|
119
|
+
* nested inside another `step.do`'s callback (the codeTool call's own
|
|
120
|
+
* enclosing step). Most tools never touch this directly; a test driving
|
|
121
|
+
* `execute`/`runToolScript` by hand passes a pass-through double.
|
|
122
|
+
*/
|
|
123
|
+
step: AgentStepLike;
|
|
105
124
|
/** The thread this tool call belongs to. */
|
|
106
125
|
threadKey: string;
|
|
107
126
|
/** The provider-issued tool-call id. */
|
|
108
127
|
toolCallId: string;
|
|
109
128
|
}
|
|
110
129
|
/**
|
|
111
|
-
* The
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
130
|
+
* The view of {@link AgentToolContext} handed to a `needsApproval` gate
|
|
131
|
+
* function — every field except `setState`, `step`, and `reportProgress`.
|
|
132
|
+
*
|
|
133
|
+
* `setState` is dropped because a gate that mutates thread state is a side
|
|
134
|
+
* effect inside a decision predicate, and `reportProgress` because emitting a
|
|
135
|
+
* live event is the same thing in observable form — the decision is what the
|
|
136
|
+
* loop reports, not the deciding. `step` goes because the loop already runs the
|
|
137
|
+
* gate inside a durable step of its own, so a gate has no business opening
|
|
138
|
+
* another.
|
|
139
|
+
*
|
|
140
|
+
* `getState` and `run` stay: reads are legitimate gate inputs (gate on the
|
|
141
|
+
* caller's plan tier, on a spend total), and the gate resolves inside its own
|
|
142
|
+
* durable step, so they are replay-safe there. Note this makes the type a
|
|
143
|
+
* NARROWING, not a proof of purity — `run` takes any
|
|
144
|
+
* {@link AgentFunctionReference}, so a gate can still dispatch a mutation
|
|
145
|
+
* before approval. Nothing in the type system distinguishes a query reference
|
|
146
|
+
* from a mutation one; keeping the gate side-effect-free is the author's.
|
|
118
147
|
* @experimental
|
|
119
148
|
*/
|
|
120
|
-
type AgentApprovalContext = Omit<AgentToolContext, "setState">;
|
|
149
|
+
type AgentApprovalContext = Omit<AgentToolContext, "reportProgress" | "setState" | "step">;
|
|
121
150
|
/**
|
|
122
151
|
* An agent tool. Unlike a raw AI SDK tool, `execute` is NOT handed to the
|
|
123
152
|
* model call — the loop runs it itself inside a named durable step so a
|
|
@@ -150,9 +179,11 @@ interface AgentToolDefinition<Input = unknown, Output = unknown> {
|
|
|
150
179
|
* from the tool's own step), so it now runs exactly once per call, not once
|
|
151
180
|
* per replay. It must still be otherwise pure: deterministic given its
|
|
152
181
|
* inputs (no `Date.now()`/`Math.random()`) and free of side effects — the
|
|
153
|
-
* context it receives is {@link AgentApprovalContext}, which has
|
|
154
|
-
* `setState`; state writes
|
|
155
|
-
* memoized step.
|
|
182
|
+
* context it receives is {@link AgentApprovalContext}, which has neither
|
|
183
|
+
* `setState` nor `reportProgress`; state writes and progress events belong
|
|
184
|
+
* only in `execute`, inside the tool's own memoized step. It still holds
|
|
185
|
+
* `run`, which the type cannot narrow to reads — see
|
|
186
|
+
* {@link AgentApprovalContext}.
|
|
156
187
|
*/
|
|
157
188
|
needsApproval?: ((input: Input, context: AgentApprovalContext) => boolean | Promise<boolean>) | boolean;
|
|
158
189
|
}
|
package/dist/reply.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Mailer } from '@lunora/mail';
|
|
2
2
|
import { InboundEmail } from '@lunora/mail/inbound';
|
|
3
|
-
import { a as AgentReplyRef } from "./packem_shared/types.d-
|
|
3
|
+
import { a as AgentReplyRef } from "./packem_shared/types.d-BoMo2eJj.mjs";
|
|
4
4
|
import 'ai';
|
|
5
5
|
/** The email arm of {@link AgentReplyRef}, narrowed for the helpers below. */
|
|
6
6
|
type EmailReplyRef = Extract<AgentReplyRef, {
|
package/dist/reply.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Mailer } from '@lunora/mail';
|
|
2
2
|
import { InboundEmail } from '@lunora/mail/inbound';
|
|
3
|
-
import { a as AgentReplyRef } from "./packem_shared/types.d-
|
|
3
|
+
import { a as AgentReplyRef } from "./packem_shared/types.d-BoMo2eJj.js";
|
|
4
4
|
import 'ai';
|
|
5
5
|
/** The email arm of {@link AgentReplyRef}, narrowed for the helpers below. */
|
|
6
6
|
type EmailReplyRef = Extract<AgentReplyRef, {
|
package/dist/sandbox.d.mts
CHANGED
package/dist/sandbox.d.ts
CHANGED
package/dist/skill-markdown.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/agent",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.59",
|
|
4
4
|
"description": "Durable AI agents for Lunora: defineAgent compiles a replay-safe tool-loop onto Cloudflare Workflows, with DO SQLite threads and live message subscriptions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -86,8 +86,8 @@
|
|
|
86
86
|
"dependencies": {
|
|
87
87
|
"@lunora/ai": "1.0.0-alpha.60",
|
|
88
88
|
"@lunora/errors": "1.0.0-alpha.22",
|
|
89
|
-
"@lunora/mail": "1.0.0-alpha.
|
|
90
|
-
"@lunora/server": "1.0.0-alpha.
|
|
89
|
+
"@lunora/mail": "1.0.0-alpha.51",
|
|
90
|
+
"@lunora/server": "1.0.0-alpha.78",
|
|
91
91
|
"@lunora/values": "1.0.0-alpha.27",
|
|
92
92
|
"@lunora/workflow": "1.0.0-alpha.30",
|
|
93
93
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{LunoraError as c}from"@lunora/errors";import{jsonSchema as i}from"ai";const s=t=>{if(t.structuredContent!==void 0)return t.structuredContent;const n=(t.content??[]).filter(e=>e.type==="text"&&typeof e.text=="string").map(e=>e.text).join(`
|
|
2
|
-
`);return t.isError===!0?`MCP tool error: ${n.length>0?n:"unknown error"}`:n.length>0?n:t.content},l=(t,n)=>({description:n.description??`MCP tool "${n.name}".`,execute:async e=>s(await t.callTool({arguments:e,name:n.name})),inputSchema:i(n.inputSchema),isLunoraAgentTool:!0}),u=async t=>{if(t.command!==void 0)throw new c("INTERNAL","@lunora/agent: mcpTools `command` (stdio transport) cannot run in the Workers runtime — pass a `url` for an HTTP/SSE MCP server, or inject a connected `client`");if(t.url===void 0)throw new c("INTERNAL","@lunora/agent: mcpTools requires a `url` (an HTTP/SSE MCP server) or an injected `client`");const n=new URL(t.url),{Client:e}=await import("@modelcontextprotocol/sdk/client/index.js");let r;if(t.transport==="sse"){const{SSEClientTransport:a}=await import("@modelcontextprotocol/sdk/client/sse.js");r=new a(n)}else{const{StreamableHTTPClientTransport:a}=await import("@modelcontextprotocol/sdk/client/streamableHttp.js");r=new a(n)}const o=new e({name:t.name??"lunora-agent",version:t.version??"0.0.0"});return await o.connect(r),o},p=async t=>{const n=t.client??await u(t),{tools:e}=await n.listTools(),r={};for(const o of e)t.only!==void 0&&!t.only.includes(o.name)||(r[`${t.prefix??""}${o.name}`]=l(n,o));return r};export{s as adaptMcpResult,p as mcpTools};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as a}from"@lunora/errors";import{jsonSchema as h}from"ai";const A=16,u=4e3,$=e=>{if(e===void 0)return e;const o=typeof e=="string"?e:JSON.stringify(e);return o.length<=u?e:`${o.slice(0,u)}… [truncated]`},b=(e,o)=>{let t=e;for(const s of o.split(".")){if(t===null||typeof t!="object"||!Object.hasOwn(t,s))return;t=t[s]}return t},c=(e,o)=>{if(Array.isArray(e))return e.map(r=>c(r,o));if(e===null||typeof e!="object")return e;const t=e;if(typeof t.$from=="string"){const r=t.$from;if(!(r in o))throw new a("BAD_REQUEST",`@lunora/agent: code step references unknown result "${r}" (define it in an earlier step)`);return typeof t.$path=="string"?b(o[r],t.$path):o[r]}const s={};for(const[r,i]of Object.entries(t))s[r]=c(i,o);return s},T=async(e,o,t,s)=>{const r=Array.isArray(e.steps)?e.steps.slice(0,s):[],i={},p=[],l=new Set;for(const n of r){if(l.has(n.id))throw new a("BAD_REQUEST",`@lunora/agent: duplicate code step id "${n.id}" — each step id must be unique (later steps reference an output by id via $from)`);l.add(n.id)}for(const n of r){const d=o[n.tool];if(!d)throw new a("BAD_REQUEST",`@lunora/agent: code step calls unknown tool "${n.tool}" (available: ${Object.keys(o).join(", ")})`);const y=c(n.input??{},i),m={...t,idempotencyKey:`${t.idempotencyKey}:${n.id}`,toolCallId:`${t.toolCallId}:${n.id}`},f=await d.execute(y,m);i[n.id]=f,p.push({id:n.id,output:$(f)})}return{final:p.at(-1)?.output,results:p}},g=e=>`Compose MULTIPLE tool calls in one turn as a script, instead of one call per turn. Provide \`steps\`: an ordered array of \`{ id, tool, input }\`. A later step's \`input\` may reference an earlier step's output with \`{ "$from": "<stepId>", "$path": "optional.dot.path" }\`. Available tools: ${Object.entries(e).map(([o,t])=>`"${o}" — ${t.description}`).join("; ")}.`,w=h({properties:{steps:{description:"Ordered tool calls; a later input may reference an earlier output via { $from, $path }.",items:{additionalProperties:!1,properties:{id:{description:"A name later steps reference this output by.",type:"string"},input:{additionalProperties:!0,description:"The tool input (may embed $from refs).",type:"object"},tool:{description:"The tool to call.",type:"string"}},required:["id","tool"],type:"object"},type:"array"}},required:["steps"],type:"object"}),E=(e,o={})=>{const t=e;if(!t||typeof t!="object"||Object.keys(t).length===0)throw new a("INTERNAL","@lunora/agent: codeTool requires a non-empty map of tools to compose");for(const[r,i]of Object.entries(t))if(i.needsApproval!==void 0&&i.needsApproval!==!1)throw new a("INTERNAL",`@lunora/agent: codeTool cannot compose "${r}" — it has a \`needsApproval\` gate a code-mode script can't pause for. Expose it as a normal top-level tool, or gate the whole script via codeTool's \`needsApproval\`.`);const s=o.maxSteps??A;return{description:o.description??g(e),execute:(r,i)=>T(r,e,i,s),inputSchema:w,isLunoraAgentTool:!0,...o.needsApproval===void 0?{}:{needsApproval:o.needsApproval}}};export{E as codeTool,c as resolveReferences,T as runToolScript};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as s}from"@lunora/errors";const I=t=>{let e="";for(let n=0;n<t.length;n+=32768)e+=String.fromCharCode(...t.subarray(n,n+32768));return btoa(e)},m=t=>I(t).replaceAll("+","-").replaceAll("/","_").replace(/=+$/,"");new TextDecoder;const w=new TextEncoder,N="=",O=t=>{for(let e=0;e<t.length;e+=1)if(t.charCodeAt(e)>255)return!1;return!0},R=t=>m(w.encode(JSON.stringify(t))),T=t=>!t.startsWith(N)&&O(t)?t:`${N}${m(w.encode(t))}`,L="/_lunora/scheduler/dispatch",_=3e4,E=t=>{let e=t.length;for(;e>0&&t[e-1]==="/";)e-=1;return t.slice(0,e)},S=Symbol("lunoraDispatchFailure"),g=t=>(Object.defineProperty(t,S,{value:!0}),t),v=(t,e,n)=>{try{const o=JSON.parse(n)?.error;if(typeof o=="object"&&o!==null&&typeof o.code=="string"){const{code:c,data:u,message:i}=o;return g(new s(c,typeof i=="string"?i:void 0,{data:u,status:e}))}}catch{}return g(new s("INTERNAL",`${t}: function dispatch failed (${String(e)}): ${n}`,{status:e}))},x=(t,e,n)=>new s("INTERNAL",`${t}: function dispatch to "${e}" timed out after ${String(n)}ms`,{status:503}),D=t=>{const{label:e}=t,n=globalThis.fetch,o=t.fetchImpl??(typeof n=="function"?n.bind(globalThis):void 0);return async(c,u,i={})=>{if(typeof o!="function")throw new TypeError(`${e}: no fetch implementation available — pass fetchImpl or run on a platform with global fetch`);const h=t.env.LUNORA_ORIGIN_URL;if(typeof h!="string"||h.length===0)throw new s("INTERNAL",`${e}: \`LUNORA_ORIGIN_URL\` must be set on the Worker env so a handler can call back into Lunora functions`);const f=t.env.LUNORA_ADMIN_TOKEN;if(typeof f!="string"||f.length===0)throw new s("INTERNAL",`${e}: \`LUNORA_ADMIN_TOKEN\` must be set on the Worker env to authenticate function dispatch`);const $=`${E(h)}${L}`,d={authorization:`Bearer ${f}`,"content-type":"application/json"};t.identity?.userId!==void 0&&(d["x-lunora-userid"]=T(t.identity.userId)),t.identity?.claims!==void 0&&(d["x-lunora-identity"]=R(t.identity.claims));const y=i.timeoutMs??_,b=AbortSignal.timeout(y),p=r=>{throw r instanceof Error&&r.name==="TimeoutError"?x(e,c.__lunoraRef,y):r};let a;try{a=await o($,{body:JSON.stringify({args:u??{},functionPath:c.__lunoraRef,shardKey:i.shardKey}),headers:d,method:"POST",signal:b})}catch(r){return p(r)}if(!a.ok){let r;try{r=await a.text()}catch(A){return p(A)}throw v(e,a.status,r)}let l;try{l=await a.text()}catch(r){return p(r)}if(l.length!==0)try{return JSON.parse(l)}catch{throw new s("INTERNAL",`${e}: function dispatch returned a non-JSON body (${String(a.status)}): ${l}`,{status:a.status})}}};export{D as v};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as n}from"@lunora/errors";import{toFunctionReference as c}from"./AGENT_MODULE-CLaSQy3P.mjs";const m=(o,e)=>{if(typeof e.description!="string"||e.description.length===0)throw new n("INTERNAL","@lunora/agent: functionTool requires a non-empty `description` (the model decides from it)");if(e.inputSchema===void 0)throw new n("INTERNAL","@lunora/agent: functionTool requires an `inputSchema` (a zod schema or `jsonSchema(...)`)");const r=c(o);return{description:e.description,execute:(t,i)=>i.run(r,t),inputSchema:e.inputSchema,isLunoraAgentTool:!0}};export{m as functionTool};
|