@lunora/agent 1.0.0-alpha.6 → 1.0.0-alpha.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/channels.d.mts +2 -2
  2. package/dist/channels.d.ts +2 -2
  3. package/dist/channels.mjs +1 -181
  4. package/dist/component.d.mts +2 -0
  5. package/dist/component.d.ts +2 -0
  6. package/dist/component.mjs +2 -418
  7. package/dist/inbound.d.mts +1 -1
  8. package/dist/inbound.d.ts +1 -1
  9. package/dist/inbound.mjs +1 -32
  10. package/dist/index.d.mts +38 -8
  11. package/dist/index.d.ts +38 -8
  12. package/dist/index.mjs +1 -18
  13. package/dist/naming.mjs +1 -8
  14. package/dist/packem_shared/AGENT_MODULE-M4D1EejI.mjs +1 -0
  15. package/dist/packem_shared/VoiceSessionDO-DPDIzZSY.mjs +1 -0
  16. package/dist/packem_shared/adaptMcpResult-CVlq-_TO.mjs +2 -0
  17. package/dist/packem_shared/agentAsTool-DrFnh9UQ.mjs +1 -0
  18. package/dist/packem_shared/base64-5eyBfWO3.mjs +1 -0
  19. package/dist/packem_shared/braintrustTelemetry-CoYK-pq7.mjs +1 -0
  20. package/dist/packem_shared/branch-marker-boZ00zmk.mjs +1 -0
  21. package/dist/packem_shared/buildModelMessages-Y4tGo1T9.mjs +5 -0
  22. package/dist/packem_shared/codeTool-qdwj8j8S.mjs +1 -0
  23. package/dist/packem_shared/collectAgenticMemoryTools-BeMWT2qt.mjs +1 -0
  24. package/dist/packem_shared/combineTelemetry-DgE9W9G8.mjs +1 -0
  25. package/dist/packem_shared/common-CJSjtsfv.mjs +1 -0
  26. package/dist/packem_shared/compileAgentWorkflow-DITp-XD6.mjs +1 -0
  27. package/dist/packem_shared/component-shared-IZozysYq.mjs +1 -0
  28. package/dist/packem_shared/consoleTelemetry-BZY3Y-Ly.mjs +1 -0
  29. package/dist/packem_shared/createAgentContext-VYm8bG12.mjs +1 -0
  30. package/dist/packem_shared/createAgentGenerate-9bZ2YhpN.mjs +3 -0
  31. package/dist/packem_shared/createDispatchRunner-CH4tZsza-CJeRsY7-.mjs +1 -0
  32. package/dist/packem_shared/defineAgent-CZdh7y3W.mjs +3 -0
  33. package/dist/packem_shared/defineSkill-DGGvDWNq.mjs +1 -0
  34. package/dist/packem_shared/functionTool-D3CP4f8-.mjs +1 -0
  35. package/dist/packem_shared/memory-JI0lUu84.mjs +1 -0
  36. package/dist/packem_shared/normalizeEntityName-Ce0X6Afj.mjs +2 -0
  37. package/dist/packem_shared/otlpTelemetry-yAjOjxn0.mjs +1 -0
  38. package/dist/packem_shared/runAgentLoop-KUUoFT3r.mjs +3 -0
  39. package/dist/packem_shared/runVoiceTurn-9zfLZi2_.mjs +1 -0
  40. package/dist/packem_shared/sandboxComponent-BtOkUYpY.mjs +5 -0
  41. package/dist/packem_shared/sentryTelemetry-CPqEbFPA.mjs +1 -0
  42. package/dist/packem_shared/{types.d-boAM2Yi1.d.mts → types.d-eCuvcLzf.d.mts} +211 -21
  43. package/dist/packem_shared/{types.d-boAM2Yi1.d.ts → types.d-eCuvcLzf.d.ts} +211 -21
  44. package/dist/packem_shared/voice-turn-CL9QCbEf.mjs +1 -0
  45. package/dist/reply.d.mts +40 -0
  46. package/dist/reply.d.ts +40 -0
  47. package/dist/reply.mjs +1 -0
  48. package/dist/sandbox.d.mts +14 -13
  49. package/dist/sandbox.d.ts +14 -13
  50. package/dist/sandbox.mjs +1 -113
  51. package/dist/skill-markdown.d.mts +36 -0
  52. package/dist/skill-markdown.d.ts +36 -0
  53. package/dist/skill-markdown.mjs +1 -0
  54. package/dist/telemetry/index.d.mts +136 -1
  55. package/dist/telemetry/index.d.ts +136 -1
  56. package/dist/telemetry/index.mjs +1 -4
  57. package/package.json +18 -9
  58. package/dist/packem_shared/AGENT_MODULE-Dnt_-AAT.mjs +0 -24
  59. package/dist/packem_shared/VoiceSessionDO-DLoXsHGF.mjs +0 -297
  60. package/dist/packem_shared/adaptMcpResult-wtNMvLoP.mjs +0 -65
  61. package/dist/packem_shared/agentAsTool-CUHlWsmt.mjs +0 -98
  62. package/dist/packem_shared/base64-BVwtgRJV.mjs +0 -18
  63. package/dist/packem_shared/braintrustTelemetry-wuGDErob.mjs +0 -47
  64. package/dist/packem_shared/buildModelMessages-BWFigaoo.mjs +0 -69
  65. package/dist/packem_shared/codeTool-CjgJOC9t.mjs +0 -122
  66. package/dist/packem_shared/collectAgenticMemoryTools-QrzpV-WX.mjs +0 -97
  67. package/dist/packem_shared/combineTelemetry-DCyaaWAI.mjs +0 -43
  68. package/dist/packem_shared/common-DAeFCot5.mjs +0 -61
  69. package/dist/packem_shared/compileAgentWorkflow-DX90058f.mjs +0 -55
  70. package/dist/packem_shared/consoleTelemetry-z2MiP1jt.mjs +0 -93
  71. package/dist/packem_shared/createAgentContext-4xJGXNR4.mjs +0 -50
  72. package/dist/packem_shared/createAgentGenerate-BQv9YJ01.mjs +0 -192
  73. package/dist/packem_shared/createDispatchRunner-DSbp_dph-ZHTtxy3f.mjs +0 -69
  74. package/dist/packem_shared/defineAgent-DAwAZC9P.mjs +0 -148
  75. package/dist/packem_shared/defineSkill-Ctf_S-rz.mjs +0 -22
  76. package/dist/packem_shared/functionTool-D6lCa2jB.mjs +0 -20
  77. package/dist/packem_shared/graph-component-Bbaxxymp.mjs +0 -217
  78. package/dist/packem_shared/memory-D4FPcBsX.mjs +0 -12
  79. package/dist/packem_shared/normalizeEntityName-BouctxLC.mjs +0 -3
  80. package/dist/packem_shared/runAgentLoop-B3Q2o-Uz.mjs +0 -493
  81. package/dist/packem_shared/runVoiceTurn-LnqLvCRR.mjs +0 -211
  82. package/dist/packem_shared/sandboxComponent-DR3pTwBL.mjs +0 -194
  83. package/dist/packem_shared/sentryTelemetry-CgqFJyLO.mjs +0 -36
package/dist/sandbox.mjs CHANGED
@@ -1,113 +1 @@
1
- import { LunoraError } from '@lunora/errors';
2
- import { jsonSchema } from 'ai';
3
- import { toFunctionReference, SANDBOX_INVOKE_PATH } from './packem_shared/AGENT_MODULE-Dnt_-AAT.mjs';
4
-
5
- const SANDBOX_REF = toFunctionReference(SANDBOX_INVOKE_PATH);
6
- const DEFAULT_BROWSER_DESCRIPTION = 'Drive a headless browser: screenshot a page, render it to PDF, read its HTML content, or scrape it. Set `op` to "screenshot" | "pdf" | "content" | "scrape" and pass the target `url`.';
7
- const DEFAULT_CONTAINER_DESCRIPTION = 'Talk to a sandboxed container: `fetch` an HTTP path on it, or `exec` a command inside it. Set `op` to "fetch" (with `path`) or "exec" (with `command`).';
8
- const DEFAULT_FS_DESCRIPTION = 'Read and write files in a persistent sandbox filesystem. Set `op` to "ls" (list a directory), "read", "write" (with `content`), "rm", or "stat", and pass `path`.';
9
- const defaultFsGate = (input) => input.op === "write" || input.op === "rm";
10
- const FS_TOOL_SCHEMA = jsonSchema({
11
- properties: {
12
- content: { description: "write: the file contents.", type: "string" },
13
- op: { description: "The filesystem operation to run.", enum: ["ls", "read", "write", "rm", "stat"], type: "string" },
14
- path: { description: "The file or directory path, relative to the sandbox root.", type: "string" }
15
- },
16
- required: ["op"],
17
- type: "object"
18
- });
19
- const BROWSER_TOOL_SCHEMA = jsonSchema({
20
- properties: {
21
- fullPage: { description: "screenshot: capture the full scrollable page rather than just the viewport.", type: "boolean" },
22
- op: { description: "The browser operation to run.", enum: ["screenshot", "scrape", "pdf", "content"], type: "string" },
23
- selector: { description: "scrape: optional CSS selector hint to narrow the extraction.", type: "string" },
24
- type: { description: "screenshot: image encoding (default png).", enum: ["png", "jpeg"], type: "string" },
25
- url: { description: "The URL to operate on.", type: "string" }
26
- },
27
- required: ["op", "url"],
28
- type: "object"
29
- });
30
- const CONTAINER_EXEC_ROUTE = "/exec";
31
- const CONTAINER_PATH_QUERY_SPLIT = /[?#]/u;
32
- const normalizeContainerPath = (path) => {
33
- const [raw = ""] = (path ?? "").split(CONTAINER_PATH_QUERY_SPLIT);
34
- const segments = [];
35
- for (const segment of raw.split("/")) {
36
- if (segment === "" || segment === ".") {
37
- continue;
38
- }
39
- if (segment === "..") {
40
- segments.pop();
41
- continue;
42
- }
43
- segments.push(segment);
44
- }
45
- return `/${segments.join("/")}`;
46
- };
47
- const NON_IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["DELETE", "PATCH", "POST", "PUT"]);
48
- const defaultContainerGate = (input) => {
49
- if (input.op === "exec") {
50
- return true;
51
- }
52
- if (normalizeContainerPath(input.path) === CONTAINER_EXEC_ROUTE) {
53
- return true;
54
- }
55
- return NON_IDEMPOTENT_METHODS.has((input.method ?? "GET").toUpperCase());
56
- };
57
- const CONTAINER_TOOL_SCHEMA = jsonSchema({
58
- properties: {
59
- args: { description: "exec: command arguments.", items: { type: "string" }, type: "array" },
60
- body: { description: "fetch: request body.", type: "string" },
61
- command: { description: "exec: the command to run.", type: "string" },
62
- method: { description: "fetch: HTTP method (default GET).", type: "string" },
63
- op: { description: "The container operation to run.", enum: ["fetch", "exec"], type: "string" },
64
- path: { description: "fetch: request path on the container (e.g. /health).", type: "string" }
65
- },
66
- required: ["op"],
67
- type: "object"
68
- });
69
- const browserTool = (options = {}) => {
70
- return {
71
- description: options.description ?? DEFAULT_BROWSER_DESCRIPTION,
72
- // Pin `kind` LAST so out-of-schema model input can never override it.
73
- execute: (input, context) => context.run(SANDBOX_REF, { ...input, kind: "browser" }),
74
- inputSchema: BROWSER_TOOL_SCHEMA,
75
- isLunoraAgentTool: true,
76
- ...options.needsApproval === void 0 ? {} : { needsApproval: options.needsApproval }
77
- };
78
- };
79
- const containerTool = (name, options = {}) => {
80
- if (typeof name !== "string" || name.length === 0) {
81
- throw new LunoraError("INTERNAL", "@lunora/agent: containerTool requires a container `name` (the ctx.containers.<name> key from lunora/containers.ts)");
82
- }
83
- const needsApproval = options.needsApproval ?? defaultContainerGate;
84
- return {
85
- description: options.description ?? DEFAULT_CONTAINER_DESCRIPTION,
86
- // Pin `kind`/`name` LAST so out-of-schema model input can never override
87
- // the authoritative container the author pinned.
88
- execute: (input, context) => context.run(SANDBOX_REF, { ...input, kind: "container", name }),
89
- inputSchema: CONTAINER_TOOL_SCHEMA,
90
- isLunoraAgentTool: true,
91
- needsApproval
92
- };
93
- };
94
- const fsTool = (bucket, options = {}) => {
95
- if (typeof bucket !== "string" || bucket.length === 0) {
96
- throw new LunoraError("INTERNAL", "@lunora/agent: fsTool requires an R2 `bucket` binding name (the r2_bucket declared in wrangler.jsonc)");
97
- }
98
- return {
99
- description: options.description ?? DEFAULT_FS_DESCRIPTION,
100
- // Pin kind/bucket/root LAST so out-of-schema model input can never override
101
- // the authoritative bucket + sandbox root the author pinned. `root` may be
102
- // a function of the ctx (per-run/owner isolation), resolved here.
103
- execute: (input, context) => {
104
- const root = typeof options.root === "function" ? options.root(context) : options.root ?? "";
105
- return context.run(SANDBOX_REF, { ...input, bucket, kind: "fs", root });
106
- },
107
- inputSchema: FS_TOOL_SCHEMA,
108
- isLunoraAgentTool: true,
109
- needsApproval: options.needsApproval ?? defaultFsGate
110
- };
111
- };
112
-
113
- export { browserTool, containerTool, fsTool };
1
+ import{LunoraError as a}from"@lunora/errors";import{jsonSchema as i}from"ai";import{toFunctionReference as p,SANDBOX_INVOKE_PATH as c}from"./packem_shared/AGENT_MODULE-M4D1EejI.mjs";const s=p(c),d='Drive a headless browser: screenshot a page, render it to PDF, read its HTML content, or scrape it. Set `op` to "screenshot" | "pdf" | "content" | "scrape" and pass the target `url`.',h='Talk to a sandboxed container: `fetch` an HTTP path on it, or `exec` a command inside it. Set `op` to "fetch" (with `path`) or "exec" (with `command`).',l='Read and write files in a persistent sandbox filesystem. Set `op` to "ls" (list a directory), "read", "write" (with `content`), "rm", or "stat", and pass `path`.',u=e=>e.op==="write"||e.op==="rm",T=i({properties:{content:{description:"write: the file contents.",type:"string"},op:{description:"The filesystem operation to run.",enum:["ls","read","write","rm","stat"],type:"string"},path:{description:"The file or directory path, relative to the sandbox root.",type:"string"}},required:["op"],type:"object"}),m=i({properties:{fullPage:{description:"screenshot: capture the full scrollable page rather than just the viewport.",type:"boolean"},op:{description:"The browser operation to run.",enum:["screenshot","scrape","pdf","content"],type:"string"},selector:{description:"scrape: optional CSS selector hint to narrow the extraction.",type:"string"},type:{description:"screenshot: image encoding (default png).",enum:["png","jpeg"],type:"string"},url:{description:"The URL to operate on.",type:"string"}},required:["op","url"],type:"object"}),g=new Set(["DELETE","PATCH","POST","PUT"]),f=e=>e.op==="exec"||g.has((e.method??"GET").toUpperCase()),y=i({properties:{args:{description:"exec: command arguments.",items:{type:"string"},type:"array"},body:{description:"fetch: request body.",type:"string"},command:{description:"exec: the command to run.",type:"string"},method:{description:"fetch: HTTP method (default GET).",type:"string"},op:{description:"The container operation to run.",enum:["fetch","exec"],type:"string"},path:{description:"fetch: request path on the container (e.g. /health).",type:"string"}},required:["op"],type:"object"}),w=(e={})=>({description:e.description??d,execute:(t,r)=>r.run(s,{...t,kind:"browser"}),inputSchema:m,isLunoraAgentTool:!0,...e.needsApproval===void 0?{}:{needsApproval:e.needsApproval}}),O=(e,t={})=>{if(typeof e!="string"||e.length===0)throw new a("INTERNAL","@lunora/agent: containerTool requires a container `name` (the ctx.containers.<name> key from lunora/containers.ts)");const r=t.needsApproval??f;return{description:t.description??h,execute:(o,n)=>n.run(s,{...o,kind:"container",name:e}),inputSchema:y,isLunoraAgentTool:!0,needsApproval:r}},_=(e,t={})=>{if(typeof e!="string"||e.length===0)throw new a("INTERNAL","@lunora/agent: fsTool requires an R2 `bucket` binding name (the r2_bucket declared in wrangler.jsonc)");return{description:t.description??l,execute:(r,o)=>{const n=typeof t.root=="function"?t.root(o):t.root??"";return o.run(s,{...r,bucket:e,kind:"fs",root:n})},inputSchema:T,isLunoraAgentTool:!0,needsApproval:t.needsApproval??u}};export{w as browserTool,O as containerTool,_ as fsTool};
@@ -0,0 +1,36 @@
1
+ import { S as SkillMarkdownExtras, d as SkillDefinition } from "./packem_shared/types.d-eCuvcLzf.mjs";
2
+ import '@lunora/mail/inbound';
3
+ import 'ai';
4
+ /**
5
+ * Declare a skill whose prose lives in a markdown file.
6
+ *
7
+ * ```ts
8
+ * import triage from "./skills/triage/SKILL.md?raw";
9
+ * import { functionTool } from "@lunora/agent";
10
+ * import { skillFromMarkdown } from "@lunora/agent/skill-markdown";
11
+ *
12
+ * export const triageSkill = skillFromMarkdown(triage, {
13
+ * tools: { searchCode: functionTool(api.code.search, { ... }) },
14
+ * });
15
+ * ```
16
+ *
17
+ * ```md
18
+ * ---
19
+ * name: triage
20
+ * ---
21
+ * Reproduce the report before proposing a cause. Cite the failing test.
22
+ * ```
23
+ *
24
+ * The split is the point: the instructions are the part a non-author reads,
25
+ * reviews and copies between projects, so they belong in a file that is legible
26
+ * on its own — and the `name` travels WITH that file, so a skill can move
27
+ * without a matching TypeScript wrapper. Tools and `knowledge` stay in code,
28
+ * because they are code.
29
+ *
30
+ * Getting the markdown here is the caller's job (`?raw` under Vite, a build-time
31
+ * import elsewhere) — a Worker has no filesystem to read it from at runtime, so
32
+ * this takes the string rather than a path.
33
+ * @experimental
34
+ */
35
+ declare const skillFromMarkdown: (markdown: string, extras?: SkillMarkdownExtras) => SkillDefinition;
36
+ export { type SkillMarkdownExtras, skillFromMarkdown };
@@ -0,0 +1,36 @@
1
+ import { S as SkillMarkdownExtras, d as SkillDefinition } from "./packem_shared/types.d-eCuvcLzf.js";
2
+ import '@lunora/mail/inbound';
3
+ import 'ai';
4
+ /**
5
+ * Declare a skill whose prose lives in a markdown file.
6
+ *
7
+ * ```ts
8
+ * import triage from "./skills/triage/SKILL.md?raw";
9
+ * import { functionTool } from "@lunora/agent";
10
+ * import { skillFromMarkdown } from "@lunora/agent/skill-markdown";
11
+ *
12
+ * export const triageSkill = skillFromMarkdown(triage, {
13
+ * tools: { searchCode: functionTool(api.code.search, { ... }) },
14
+ * });
15
+ * ```
16
+ *
17
+ * ```md
18
+ * ---
19
+ * name: triage
20
+ * ---
21
+ * Reproduce the report before proposing a cause. Cite the failing test.
22
+ * ```
23
+ *
24
+ * The split is the point: the instructions are the part a non-author reads,
25
+ * reviews and copies between projects, so they belong in a file that is legible
26
+ * on its own — and the `name` travels WITH that file, so a skill can move
27
+ * without a matching TypeScript wrapper. Tools and `knowledge` stay in code,
28
+ * because they are code.
29
+ *
30
+ * Getting the markdown here is the caller's job (`?raw` under Vite, a build-time
31
+ * import elsewhere) — a Worker has no filesystem to read it from at runtime, so
32
+ * this takes the string rather than a path.
33
+ * @experimental
34
+ */
35
+ declare const skillFromMarkdown: (markdown: string, extras?: SkillMarkdownExtras) => SkillDefinition;
36
+ export { type SkillMarkdownExtras, skillFromMarkdown };
@@ -0,0 +1 @@
1
+ import{LunoraError as o}from"@lunora/errors";import{parse as s}from"yaml";import{defineSkill as l}from"./packem_shared/defineSkill-DGGvDWNq.mjs";const m=/^\uFEFF?[ \t]*---[ \t]*\r?\n/u,h=/^---[ \t]*$/mu,c=t=>{const r=m.exec(t);if(!r)return{body:t.trim(),data:{}};const n=t.slice(r[0].length),e=h.exec(n);if(!e)throw new o("INTERNAL","@lunora/agent: the skill markdown opens with `---` but never closes the frontmatter block. Add a closing `---` on its own line.");let a;try{a=s(n.slice(0,e.index))}catch(i){throw new o("INTERNAL",`@lunora/agent: the skill markdown has invalid YAML frontmatter — ${i instanceof Error?i.message:String(i)}`)}return{body:n.slice(e.index+e[0].length).trim(),data:typeof a=="object"&&a!==null?a:{}}},w=(t,r={})=>{if(typeof t!="string")throw new o("INTERNAL",`@lunora/agent: skillFromMarkdown expects the markdown SOURCE as a string, got ${typeof t}`);const{body:n,data:e}=c(t);if(e.name!==void 0&&typeof e.name!="string")throw new o("INTERNAL",`@lunora/agent: the skill markdown's \`name\` must be a string, got ${Array.isArray(e.name)?"array":typeof e.name}. Quote it if the value looks like a number or a boolean (\`name: "2fa"\`).`);if(typeof e.name!="string")throw new o("INTERNAL","@lunora/agent: skillFromMarkdown found no `name` in the markdown frontmatter. Open the file with a `---` line, put `name: <identifier>` on its own line, and close it with `---`. Other keys are parsed and ignored — only `name` is read here.");if(n==="")throw new o("INTERNAL",`@lunora/agent: the skill markdown for "${e.name}" has no body — the instructions below the closing \`---\` are what the skill contributes.`);return l({...r,instructions:n,name:e.name})};export{w as skillFromMarkdown};
@@ -122,6 +122,87 @@ interface ConsoleTelemetryOptions extends CommonOptions {
122
122
  * @experimental
123
123
  */
124
124
  declare const consoleTelemetry: (options?: ConsoleTelemetryOptions) => Telemetry;
125
+ /**
126
+ * Options for {@link otlpTelemetry}.
127
+ * @experimental
128
+ */
129
+ interface OtlpTelemetryOptions extends CommonOptions {
130
+ /**
131
+ * Conversation / session id to tag each generation span with, emitted as the
132
+ * `gen_ai.conversation.id` semantic-convention attribute so a multi-turn
133
+ * conversation's model turns group in the trace store. On a deployed agent the
134
+ * platform wiring passes the run's `threadKey` here automatically (one thread =
135
+ * one conversation). Omitted → the attribute is absent (backward-compatible),
136
+ * and each turn's span is ungrouped.
137
+ */
138
+ conversationId?: string;
139
+ /**
140
+ * The OTLP-over-HTTP collector base endpoint (e.g. the Lunora Cloud's `/v1`
141
+ * base). Spans are POSTed to `${endpoint}/v1/traces`; a trailing slash is
142
+ * tolerated. On the platform this is the injected `LUNORA_OTLP_ENDPOINT`.
143
+ */
144
+ endpoint: string;
145
+ /**
146
+ * Extra headers merged onto every POST — typically the correlation headers
147
+ * the platform injects. `Content-Type: application/json` is set by default.
148
+ */
149
+ headers?: Record<string, string>;
150
+ /** `service.name` resource attribute on every span. Defaults to `lunora`. */
151
+ serviceName?: string;
152
+ /**
153
+ * Bearer token added as `Authorization: Bearer` (wins over any authorization
154
+ * in `headers`) — the injected `LUNORA_OTLP_TOKEN`. Omit for an
155
+ * unauthenticated collector.
156
+ */
157
+ token?: string;
158
+ /**
159
+ * Trace id (32-hex) to hang every span of this run under, so one agent run
160
+ * reads as one trace. Pass a stable id derived from the run (e.g. the
161
+ * workflow run id). Omitted → each span mints its own trace id (still valid,
162
+ * just ungrouped).
163
+ */
164
+ traceId?: string;
165
+ /**
166
+ * The Worker request's `waitUntil`, so a fire-and-forget export survives
167
+ * isolate teardown after the turn returns. Omit and the send degrades to
168
+ * best-effort.
169
+ */
170
+ waitUntil?: (promise: Promise<unknown>) => void;
171
+ }
172
+ /**
173
+ * An OTLP-over-HTTP telemetry integration for `@lunora/agent`.
174
+ *
175
+ * The OTLP counterpart to the `sentryTelemetry` / `braintrustTelemetry` bridges:
176
+ * it wraps each language-model call and tool execution in an OTLP **span**
177
+ * (`gen_ai.*` semantic-convention attributes — model, provider, token usage,
178
+ * tool name) and ships it to a collector, so agent generations land in the same
179
+ * trace store as the rest of an app's telemetry (the Lunora Cloud, or any OTel
180
+ * collector). Plug it into `defineAgent({ telemetry: { isEnabled: true,
181
+ * integrations: [otlpTelemetry({ endpoint, token })] } })`.
182
+ *
183
+ * Emitting inside the turn's execution wrapper means one span per **real** turn:
184
+ * the agent loop memoizes each `step.do('llm:turn:N')`, so a Workflow replay
185
+ * returns the cached result without re-invoking `execute`, and no duplicate span
186
+ * is emitted. Privacy-safe by default — `recordInputs`/`recordOutputs` both
187
+ * default `false`, so no prompt or generated text leaves the worker without an
188
+ * explicit opt-in; only structural metadata + token counts are recorded.
189
+ *
190
+ * Each export is fire-and-forget (registered with `waitUntil` when supplied);
191
+ * every rejection is swallowed so a flaky collector never surfaces to the run.
192
+ *
193
+ * Two deliberate differences from the SDK-backed bridges, which delegate to a
194
+ * host tracer. First, no `onError`: a failed call already emits a span with
195
+ * `status.code === 2`, so the failure is on the trace and there is no host client
196
+ * to also notify. Second, flat not nested: every span gets `traceId` (shared when
197
+ * `traceId` is set) but no `parentSpanId`, so model-call and tool spans are
198
+ * siblings under the run rather than a tree — OTLP has no ambient span context to
199
+ * parent to here.
200
+ * @param options `endpoint` (+ optional `token`/`headers`/`serviceName`),
201
+ * `traceId` to group a run's spans, `waitUntil`, and the `recordInputs`/
202
+ * `recordOutputs` privacy flags.
203
+ * @experimental
204
+ */
205
+ declare const otlpTelemetry: (options: OtlpTelemetryOptions) => Telemetry;
125
206
  /**
126
207
  * The minimal, **structural** slice of `@sentry/cloudflare` (equivalently
127
208
  * `@sentry/node`/`@sentry/browser`) this bridge needs. `@sentry/cloudflare` is
@@ -170,4 +251,58 @@ interface SentryTelemetryOptions extends CommonOptions {
170
251
  * @experimental
171
252
  */
172
253
  declare const sentryTelemetry: (options: SentryTelemetryOptions) => Telemetry;
173
- export { type BraintrustLike, type BraintrustSpan, type BraintrustTelemetryOptions, type CommonOptions, type ConsoleLogLevel, type ConsoleLogger, type ConsoleTelemetryOptions, type SentryLike, type SentryTelemetryOptions, braintrustTelemetry, combineTelemetry, consoleTelemetry, sentryTelemetry };
254
+ export {
255
+ /**
256
+ * `@lunora/agent/telemetry` — observability integrations for `@lunora/agent`.
257
+ *
258
+ * Every export here produces an ai@7 `Telemetry` object suitable for the
259
+ * `integrations` array of `TelemetryOptions` (`defineAgent({ telemetry: {
260
+ * isEnabled: true, integrations: [...] } })`). `consoleTelemetry` is a
261
+ * zero-dependency structured console tracer; `combineTelemetry` fans the
262
+ * lifecycle out to several integrations and nests their execution wrappers;
263
+ * `sentryTelemetry` / `braintrustTelemetry` are dependency-injected bridges (the
264
+ * app passes its own Sentry namespace / Braintrust logger, so the heavy SDKs are
265
+ * never imported here); and `otlpTelemetry` ships `gen_ai.*` spans over
266
+ * OTLP-over-HTTP to any collector (the Lunora Cloud, or your own), so agent
267
+ * generations land in the same trace store as the rest of the app.
268
+ *
269
+ * All integrations are privacy-safe by default (`recordInputs` / `recordOutputs`
270
+ * both default `false`), so nothing sensitive is recorded without opt-in.
271
+ */
272
+ type BraintrustLike,
273
+ /**
274
+ * `@lunora/agent/telemetry` — observability integrations for `@lunora/agent`.
275
+ *
276
+ * Every export here produces an ai@7 `Telemetry` object suitable for the
277
+ * `integrations` array of `TelemetryOptions` (`defineAgent({ telemetry: {
278
+ * isEnabled: true, integrations: [...] } })`). `consoleTelemetry` is a
279
+ * zero-dependency structured console tracer; `combineTelemetry` fans the
280
+ * lifecycle out to several integrations and nests their execution wrappers;
281
+ * `sentryTelemetry` / `braintrustTelemetry` are dependency-injected bridges (the
282
+ * app passes its own Sentry namespace / Braintrust logger, so the heavy SDKs are
283
+ * never imported here); and `otlpTelemetry` ships `gen_ai.*` spans over
284
+ * OTLP-over-HTTP to any collector (the Lunora Cloud, or your own), so agent
285
+ * generations land in the same trace store as the rest of the app.
286
+ *
287
+ * All integrations are privacy-safe by default (`recordInputs` / `recordOutputs`
288
+ * both default `false`), so nothing sensitive is recorded without opt-in.
289
+ */
290
+ type BraintrustSpan,
291
+ /**
292
+ * `@lunora/agent/telemetry` — observability integrations for `@lunora/agent`.
293
+ *
294
+ * Every export here produces an ai@7 `Telemetry` object suitable for the
295
+ * `integrations` array of `TelemetryOptions` (`defineAgent({ telemetry: {
296
+ * isEnabled: true, integrations: [...] } })`). `consoleTelemetry` is a
297
+ * zero-dependency structured console tracer; `combineTelemetry` fans the
298
+ * lifecycle out to several integrations and nests their execution wrappers;
299
+ * `sentryTelemetry` / `braintrustTelemetry` are dependency-injected bridges (the
300
+ * app passes its own Sentry namespace / Braintrust logger, so the heavy SDKs are
301
+ * never imported here); and `otlpTelemetry` ships `gen_ai.*` spans over
302
+ * OTLP-over-HTTP to any collector (the Lunora Cloud, or your own), so agent
303
+ * generations land in the same trace store as the rest of the app.
304
+ *
305
+ * All integrations are privacy-safe by default (`recordInputs` / `recordOutputs`
306
+ * both default `false`), so nothing sensitive is recorded without opt-in.
307
+ */
308
+ type BraintrustTelemetryOptions, type CommonOptions, type ConsoleLogLevel, type ConsoleLogger, type ConsoleTelemetryOptions, type OtlpTelemetryOptions, type SentryLike, type SentryTelemetryOptions, braintrustTelemetry, combineTelemetry, consoleTelemetry, otlpTelemetry, sentryTelemetry };
@@ -122,6 +122,87 @@ interface ConsoleTelemetryOptions extends CommonOptions {
122
122
  * @experimental
123
123
  */
124
124
  declare const consoleTelemetry: (options?: ConsoleTelemetryOptions) => Telemetry;
125
+ /**
126
+ * Options for {@link otlpTelemetry}.
127
+ * @experimental
128
+ */
129
+ interface OtlpTelemetryOptions extends CommonOptions {
130
+ /**
131
+ * Conversation / session id to tag each generation span with, emitted as the
132
+ * `gen_ai.conversation.id` semantic-convention attribute so a multi-turn
133
+ * conversation's model turns group in the trace store. On a deployed agent the
134
+ * platform wiring passes the run's `threadKey` here automatically (one thread =
135
+ * one conversation). Omitted → the attribute is absent (backward-compatible),
136
+ * and each turn's span is ungrouped.
137
+ */
138
+ conversationId?: string;
139
+ /**
140
+ * The OTLP-over-HTTP collector base endpoint (e.g. the Lunora Cloud's `/v1`
141
+ * base). Spans are POSTed to `${endpoint}/v1/traces`; a trailing slash is
142
+ * tolerated. On the platform this is the injected `LUNORA_OTLP_ENDPOINT`.
143
+ */
144
+ endpoint: string;
145
+ /**
146
+ * Extra headers merged onto every POST — typically the correlation headers
147
+ * the platform injects. `Content-Type: application/json` is set by default.
148
+ */
149
+ headers?: Record<string, string>;
150
+ /** `service.name` resource attribute on every span. Defaults to `lunora`. */
151
+ serviceName?: string;
152
+ /**
153
+ * Bearer token added as `Authorization: Bearer` (wins over any authorization
154
+ * in `headers`) — the injected `LUNORA_OTLP_TOKEN`. Omit for an
155
+ * unauthenticated collector.
156
+ */
157
+ token?: string;
158
+ /**
159
+ * Trace id (32-hex) to hang every span of this run under, so one agent run
160
+ * reads as one trace. Pass a stable id derived from the run (e.g. the
161
+ * workflow run id). Omitted → each span mints its own trace id (still valid,
162
+ * just ungrouped).
163
+ */
164
+ traceId?: string;
165
+ /**
166
+ * The Worker request's `waitUntil`, so a fire-and-forget export survives
167
+ * isolate teardown after the turn returns. Omit and the send degrades to
168
+ * best-effort.
169
+ */
170
+ waitUntil?: (promise: Promise<unknown>) => void;
171
+ }
172
+ /**
173
+ * An OTLP-over-HTTP telemetry integration for `@lunora/agent`.
174
+ *
175
+ * The OTLP counterpart to the `sentryTelemetry` / `braintrustTelemetry` bridges:
176
+ * it wraps each language-model call and tool execution in an OTLP **span**
177
+ * (`gen_ai.*` semantic-convention attributes — model, provider, token usage,
178
+ * tool name) and ships it to a collector, so agent generations land in the same
179
+ * trace store as the rest of an app's telemetry (the Lunora Cloud, or any OTel
180
+ * collector). Plug it into `defineAgent({ telemetry: { isEnabled: true,
181
+ * integrations: [otlpTelemetry({ endpoint, token })] } })`.
182
+ *
183
+ * Emitting inside the turn's execution wrapper means one span per **real** turn:
184
+ * the agent loop memoizes each `step.do('llm:turn:N')`, so a Workflow replay
185
+ * returns the cached result without re-invoking `execute`, and no duplicate span
186
+ * is emitted. Privacy-safe by default — `recordInputs`/`recordOutputs` both
187
+ * default `false`, so no prompt or generated text leaves the worker without an
188
+ * explicit opt-in; only structural metadata + token counts are recorded.
189
+ *
190
+ * Each export is fire-and-forget (registered with `waitUntil` when supplied);
191
+ * every rejection is swallowed so a flaky collector never surfaces to the run.
192
+ *
193
+ * Two deliberate differences from the SDK-backed bridges, which delegate to a
194
+ * host tracer. First, no `onError`: a failed call already emits a span with
195
+ * `status.code === 2`, so the failure is on the trace and there is no host client
196
+ * to also notify. Second, flat not nested: every span gets `traceId` (shared when
197
+ * `traceId` is set) but no `parentSpanId`, so model-call and tool spans are
198
+ * siblings under the run rather than a tree — OTLP has no ambient span context to
199
+ * parent to here.
200
+ * @param options `endpoint` (+ optional `token`/`headers`/`serviceName`),
201
+ * `traceId` to group a run's spans, `waitUntil`, and the `recordInputs`/
202
+ * `recordOutputs` privacy flags.
203
+ * @experimental
204
+ */
205
+ declare const otlpTelemetry: (options: OtlpTelemetryOptions) => Telemetry;
125
206
  /**
126
207
  * The minimal, **structural** slice of `@sentry/cloudflare` (equivalently
127
208
  * `@sentry/node`/`@sentry/browser`) this bridge needs. `@sentry/cloudflare` is
@@ -170,4 +251,58 @@ interface SentryTelemetryOptions extends CommonOptions {
170
251
  * @experimental
171
252
  */
172
253
  declare const sentryTelemetry: (options: SentryTelemetryOptions) => Telemetry;
173
- export { type BraintrustLike, type BraintrustSpan, type BraintrustTelemetryOptions, type CommonOptions, type ConsoleLogLevel, type ConsoleLogger, type ConsoleTelemetryOptions, type SentryLike, type SentryTelemetryOptions, braintrustTelemetry, combineTelemetry, consoleTelemetry, sentryTelemetry };
254
+ export {
255
+ /**
256
+ * `@lunora/agent/telemetry` — observability integrations for `@lunora/agent`.
257
+ *
258
+ * Every export here produces an ai@7 `Telemetry` object suitable for the
259
+ * `integrations` array of `TelemetryOptions` (`defineAgent({ telemetry: {
260
+ * isEnabled: true, integrations: [...] } })`). `consoleTelemetry` is a
261
+ * zero-dependency structured console tracer; `combineTelemetry` fans the
262
+ * lifecycle out to several integrations and nests their execution wrappers;
263
+ * `sentryTelemetry` / `braintrustTelemetry` are dependency-injected bridges (the
264
+ * app passes its own Sentry namespace / Braintrust logger, so the heavy SDKs are
265
+ * never imported here); and `otlpTelemetry` ships `gen_ai.*` spans over
266
+ * OTLP-over-HTTP to any collector (the Lunora Cloud, or your own), so agent
267
+ * generations land in the same trace store as the rest of the app.
268
+ *
269
+ * All integrations are privacy-safe by default (`recordInputs` / `recordOutputs`
270
+ * both default `false`), so nothing sensitive is recorded without opt-in.
271
+ */
272
+ type BraintrustLike,
273
+ /**
274
+ * `@lunora/agent/telemetry` — observability integrations for `@lunora/agent`.
275
+ *
276
+ * Every export here produces an ai@7 `Telemetry` object suitable for the
277
+ * `integrations` array of `TelemetryOptions` (`defineAgent({ telemetry: {
278
+ * isEnabled: true, integrations: [...] } })`). `consoleTelemetry` is a
279
+ * zero-dependency structured console tracer; `combineTelemetry` fans the
280
+ * lifecycle out to several integrations and nests their execution wrappers;
281
+ * `sentryTelemetry` / `braintrustTelemetry` are dependency-injected bridges (the
282
+ * app passes its own Sentry namespace / Braintrust logger, so the heavy SDKs are
283
+ * never imported here); and `otlpTelemetry` ships `gen_ai.*` spans over
284
+ * OTLP-over-HTTP to any collector (the Lunora Cloud, or your own), so agent
285
+ * generations land in the same trace store as the rest of the app.
286
+ *
287
+ * All integrations are privacy-safe by default (`recordInputs` / `recordOutputs`
288
+ * both default `false`), so nothing sensitive is recorded without opt-in.
289
+ */
290
+ type BraintrustSpan,
291
+ /**
292
+ * `@lunora/agent/telemetry` — observability integrations for `@lunora/agent`.
293
+ *
294
+ * Every export here produces an ai@7 `Telemetry` object suitable for the
295
+ * `integrations` array of `TelemetryOptions` (`defineAgent({ telemetry: {
296
+ * isEnabled: true, integrations: [...] } })`). `consoleTelemetry` is a
297
+ * zero-dependency structured console tracer; `combineTelemetry` fans the
298
+ * lifecycle out to several integrations and nests their execution wrappers;
299
+ * `sentryTelemetry` / `braintrustTelemetry` are dependency-injected bridges (the
300
+ * app passes its own Sentry namespace / Braintrust logger, so the heavy SDKs are
301
+ * never imported here); and `otlpTelemetry` ships `gen_ai.*` spans over
302
+ * OTLP-over-HTTP to any collector (the Lunora Cloud, or your own), so agent
303
+ * generations land in the same trace store as the rest of the app.
304
+ *
305
+ * All integrations are privacy-safe by default (`recordInputs` / `recordOutputs`
306
+ * both default `false`), so nothing sensitive is recorded without opt-in.
307
+ */
308
+ type BraintrustTelemetryOptions, type CommonOptions, type ConsoleLogLevel, type ConsoleLogger, type ConsoleTelemetryOptions, type OtlpTelemetryOptions, type SentryLike, type SentryTelemetryOptions, braintrustTelemetry, combineTelemetry, consoleTelemetry, otlpTelemetry, sentryTelemetry };
@@ -1,4 +1 @@
1
- export { braintrustTelemetry } from '../packem_shared/braintrustTelemetry-wuGDErob.mjs';
2
- export { combineTelemetry } from '../packem_shared/combineTelemetry-DCyaaWAI.mjs';
3
- export { consoleTelemetry } from '../packem_shared/consoleTelemetry-z2MiP1jt.mjs';
4
- export { sentryTelemetry } from '../packem_shared/sentryTelemetry-CgqFJyLO.mjs';
1
+ import{braintrustTelemetry as o}from"../packem_shared/braintrustTelemetry-CoYK-pq7.mjs";import{combineTelemetry as m}from"../packem_shared/combineTelemetry-DgE9W9G8.mjs";import{consoleTelemetry as p}from"../packem_shared/consoleTelemetry-BZY3Y-Ly.mjs";import{otlpTelemetry as f}from"../packem_shared/otlpTelemetry-yAjOjxn0.mjs";import{sentryTelemetry as T}from"../packem_shared/sentryTelemetry-CPqEbFPA.mjs";export{o as braintrustTelemetry,m as combineTelemetry,p as consoleTelemetry,f as otlpTelemetry,T as sentryTelemetry};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/agent",
3
- "version": "1.0.0-alpha.6",
3
+ "version": "1.0.0-alpha.61",
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",
@@ -62,6 +62,14 @@
62
62
  "types": "./dist/naming.d.ts",
63
63
  "import": "./dist/naming.mjs"
64
64
  },
65
+ "./skill-markdown": {
66
+ "types": "./dist/skill-markdown.d.ts",
67
+ "import": "./dist/skill-markdown.mjs"
68
+ },
69
+ "./reply": {
70
+ "types": "./dist/reply.d.ts",
71
+ "import": "./dist/reply.mjs"
72
+ },
65
73
  "./sandbox": {
66
74
  "types": "./dist/sandbox.d.ts",
67
75
  "import": "./dist/sandbox.mjs"
@@ -76,14 +84,15 @@
76
84
  "access": "public"
77
85
  },
78
86
  "dependencies": {
79
- "@lunora/ai": "1.0.0-alpha.17",
80
- "@lunora/errors": "1.0.0-alpha.6",
81
- "@lunora/mail": "1.0.0-alpha.16",
82
- "@lunora/server": "1.0.0-alpha.29",
83
- "@lunora/values": "1.0.0-alpha.9",
84
- "@lunora/workflow": "1.0.0-alpha.11",
85
- "@modelcontextprotocol/sdk": "^1.29.0",
86
- "ai": "7.0.31"
87
+ "@lunora/ai": "1.0.0-alpha.60",
88
+ "@lunora/errors": "1.0.0-alpha.22",
89
+ "@lunora/mail": "1.0.0-alpha.51",
90
+ "@lunora/server": "1.0.0-alpha.80",
91
+ "@lunora/values": "1.0.0-alpha.27",
92
+ "@lunora/workflow": "1.0.0-alpha.31",
93
+ "@modelcontextprotocol/sdk": "^1.30.0",
94
+ "ai": "7.0.59",
95
+ "yaml": "^2.9.0"
87
96
  },
88
97
  "engines": {
89
98
  "node": "^22.15.0 || >=24.11.0"
@@ -1,24 +0,0 @@
1
- const AGENT_MODULE = "agents";
2
- const SANDBOX_MODULE = "sandbox";
3
- const SANDBOX_INVOKE_PATH = `${SANDBOX_MODULE}:invoke`;
4
- const DEFAULT_AGENT_FUNCTION_PATHS = {
5
- appendMessage: `${AGENT_MODULE}:agentAppendMessage`,
6
- ensureThread: `${AGENT_MODULE}:agentEnsureThread`,
7
- episodeRecall: `${AGENT_MODULE}:agentEpisodeRecall`,
8
- episodeUpsert: `${AGENT_MODULE}:agentEpisodeUpsert`,
9
- graphTraverse: `${AGENT_MODULE}:agentGraphTraverse`,
10
- graphUpsert: `${AGENT_MODULE}:agentGraphUpsert`,
11
- listMessages: `${AGENT_MODULE}:agentMessages`,
12
- patchThread: `${AGENT_MODULE}:agentPatchThread`,
13
- run: `${AGENT_MODULE}:agentRun`,
14
- setState: `${AGENT_MODULE}:agentSetState`,
15
- state: `${AGENT_MODULE}:agentState`
16
- };
17
- const toFunctionReference = (source) => {
18
- if (typeof source === "string") {
19
- return { __lunoraRef: source };
20
- }
21
- return source;
22
- };
23
-
24
- export { AGENT_MODULE, DEFAULT_AGENT_FUNCTION_PATHS, SANDBOX_INVOKE_PATH, SANDBOX_MODULE, toFunctionReference };