@lunora/agent 1.0.0-alpha.7 → 1.0.0-alpha.8

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/index.mjs CHANGED
@@ -15,4 +15,4 @@ export { browserTool, containerTool, fsTool } from './sandbox.mjs';
15
15
  export { defineSkill, isSkillDefinition } from './packem_shared/defineSkill-Ctf_S-rz.mjs';
16
16
  export { default as VoiceSessionDO } from './packem_shared/VoiceSessionDO-DLoXsHGF.mjs';
17
17
  export { runVoiceTurn } from './packem_shared/runVoiceTurn-LnqLvCRR.mjs';
18
- export { default as compileAgentWorkflow } from './packem_shared/compileAgentWorkflow-DX90058f.mjs';
18
+ export { default as compileAgentWorkflow } from './packem_shared/compileAgentWorkflow-DXNKigj0.mjs';
@@ -0,0 +1,75 @@
1
+ import { defineWorkflow } from '@lunora/workflow';
2
+ import { runAgentLoop } from './runAgentLoop-B3Q2o-Uz.mjs';
3
+ import { createStreamGenerate, createAgentGenerate, createEpisodeExtract, createGraphExtract, createCompact } from './createAgentGenerate-BQv9YJ01.mjs';
4
+ import { agentDefaultName } from '../naming.mjs';
5
+ import { DEFAULT_AGENT_FUNCTION_PATHS } from './AGENT_MODULE-Dnt_-AAT.mjs';
6
+ import { c as createDispatchRunner } from './createDispatchRunner-DSbp_dph-ZHTtxy3f.mjs';
7
+ import { otlpTelemetry } from './otlpTelemetry-9ypXork9.mjs';
8
+
9
+ const resolveAgentRun = (contextRun, owner, env) => {
10
+ if (owner === void 0) {
11
+ return contextRun;
12
+ }
13
+ return createDispatchRunner({ env, identity: { userId: owner }, label: "@lunora/agent" });
14
+ };
15
+
16
+ const withAutoOtlpTelemetry = (agent, env) => {
17
+ const endpoint = env.LUNORA_OTLP_ENDPOINT;
18
+ if (typeof endpoint !== "string" || endpoint === "" || agent.telemetry?.isEnabled === false) {
19
+ return agent;
20
+ }
21
+ const token = typeof env.LUNORA_OTLP_TOKEN === "string" ? env.LUNORA_OTLP_TOKEN : void 0;
22
+ const existingList = [agent.telemetry?.integrations].flat().filter((integration) => integration !== void 0);
23
+ return {
24
+ ...agent,
25
+ telemetry: {
26
+ ...agent.telemetry,
27
+ integrations: [...existingList, otlpTelemetry({ endpoint, token })],
28
+ isEnabled: true
29
+ }
30
+ };
31
+ };
32
+ const compileAgentWorkflow = (agent, exportName, options) => defineWorkflow({
33
+ handler: async (context) => {
34
+ const runtimeAgent = withAutoOtlpTelemetry(agent, context.env);
35
+ return runAgentLoop({
36
+ agent: runtimeAgent,
37
+ // Automatic history compaction. Dormant unless the agent declares
38
+ // a `compaction` config; the loop gates on it, so any other agent
39
+ // takes the byte-identical no-compaction path.
40
+ compact: createCompact(),
41
+ env: context.env,
42
+ exportName,
43
+ // Run-end graph extraction. Dormant unless the agent declares a
44
+ // `kind: "graph"` memory source AND the run carries an owner — the
45
+ // loop gates on both, so a semantic-only agent takes the
46
+ // byte-identical no-extraction path.
47
+ extractGraph: createGraphExtract(),
48
+ // Run-end episode recording. Dormant unless the agent declares a
49
+ // `kind: "episodic"` memory source AND the run carries an owner —
50
+ // the loop gates on both, so any other agent is byte-identical.
51
+ extractEpisode: createEpisodeExtract(),
52
+ generate: createAgentGenerate(runtimeAgent, context.env),
53
+ instanceId: context.event.instanceId,
54
+ params: context.params,
55
+ paths: options?.paths ?? DEFAULT_AGENT_FUNCTION_PATHS,
56
+ // The loop reads its own owner-gated thread back through
57
+ // `agents:*` queries. The default `context.run` forwards no
58
+ // identity, so on an OWNED thread those reads would come back
59
+ // empty and the model would answer blind. `resolveAgentRun`
60
+ // dispatches an owner-scoped run under that verified identity so
61
+ // the owner gate admits the loop's reads (ownerless runs keep the
62
+ // identity-free `context.run`). See `resolve-run.ts`.
63
+ run: resolveAgentRun(context.run, context.params.owner, context.env),
64
+ step: context.step,
65
+ // The streaming seam is wired and ready, but stays dormant until a
66
+ // live token sink is threaded onto the run (a follow-up wires
67
+ // `onTokenDelta` to the stream transport). With no sink the loop
68
+ // takes the byte-identical non-streaming `generate` path.
69
+ streamGenerate: createStreamGenerate(runtimeAgent, context.env)
70
+ });
71
+ },
72
+ name: agent.name ?? agentDefaultName(exportName)
73
+ });
74
+
75
+ export { compileAgentWorkflow as default };
@@ -1,4 +1,4 @@
1
- import { s as summarizeUsage, c as contentText, r as readField, t as toolInputOf, a as toolNameOf } from './common-DAeFCot5.mjs';
1
+ import { s as summarizeUsage, r as readField, c as contentText, t as toolInputOf, a as toolNameOf } from './common-DAeFCot5.mjs';
2
2
 
3
3
  const otlpUnixNano = (ms) => `${String(Math.round(ms))}000000`;
4
4
  const otlpRandomHex = (bytes) => {
@@ -67,6 +67,19 @@ const pushAttribute = (attributes, key, value) => {
67
67
  }
68
68
  attributes.push(encodeAttribute(key, JSON.stringify(value)));
69
69
  };
70
+ const observeSettled = (promise, onSettle) => {
71
+ const run = async () => {
72
+ let result;
73
+ try {
74
+ result = await promise;
75
+ } catch (error) {
76
+ onSettle(false, error instanceof Error ? error.message : String(error), void 0);
77
+ return;
78
+ }
79
+ onSettle(true, void 0, result);
80
+ };
81
+ run().catch(() => void 0);
82
+ };
70
83
  const otlpTelemetry = (options) => {
71
84
  const { endpoint, headers, recordInputs = false, recordOutputs = false, token, traceId: fixedTraceId, waitUntil } = options;
72
85
  const serviceName = options.serviceName ?? "lunora";
@@ -124,14 +137,7 @@ const otlpTelemetry = (options) => {
124
137
  }
125
138
  emitSpan(typeof modelId === "string" ? `chat ${modelId}` : "language_model_call", startTs, ok, message, attributes);
126
139
  };
127
- promise.then(
128
- (result) => {
129
- emit(true, void 0, result);
130
- },
131
- (error) => {
132
- emit(false, error instanceof Error ? error.message : String(error), void 0);
133
- }
134
- );
140
+ observeSettled(promise, emit);
135
141
  return promise;
136
142
  },
137
143
  executeTool: (options_) => {
@@ -148,14 +154,7 @@ const otlpTelemetry = (options) => {
148
154
  }
149
155
  emitSpan(typeof toolName === "string" ? `execute_tool ${toolName}` : "execute_tool", startTs, ok, message, attributes);
150
156
  };
151
- promise.then(
152
- () => {
153
- emit(true, void 0);
154
- },
155
- (error) => {
156
- emit(false, error instanceof Error ? error.message : String(error));
157
- }
158
- );
157
+ observeSettled(promise, emit);
159
158
  return promise;
160
159
  }
161
160
  };
@@ -163,7 +163,7 @@ interface OtlpTelemetryOptions extends CommonOptions {
163
163
  /**
164
164
  * An OTLP-over-HTTP telemetry integration for `@lunora/agent`.
165
165
  *
166
- * The OTLP counterpart to {@link sentryTelemetry} / {@link braintrustTelemetry}:
166
+ * The OTLP counterpart to the `sentryTelemetry` / `braintrustTelemetry` bridges:
167
167
  * it wraps each language-model call and tool execution in an OTLP **span**
168
168
  * (`gen_ai.*` semantic-convention attributes — model, provider, token usage,
169
169
  * tool name) and ships it to a collector, so agent generations land in the same
@@ -181,13 +181,13 @@ interface OtlpTelemetryOptions extends CommonOptions {
181
181
  * Each export is fire-and-forget (registered with `waitUntil` when supplied);
182
182
  * every rejection is swallowed so a flaky collector never surfaces to the run.
183
183
  *
184
- * Two deliberate differences from the SDK-backed integrations (`sentryTelemetry`
185
- * / `braintrustTelemetry`), which delegate to a host tracer:
186
- * - **No `onError`.** A failed call already emits a span with `status.code === 2`,
187
- * so the failure is on the trace; there is no host client to also notify.
188
- * - **Flat, not nested.** Every span gets `traceId` (shared when `traceId` is set)
189
- * but no `parentSpanId`, so model-call and tool spans are siblings under the run
190
- * rather than a tree — OTLP has no ambient span context to parent to here.
184
+ * Two deliberate differences from the SDK-backed bridges, which delegate to a
185
+ * host tracer. First, no `onError`: a failed call already emits a span with
186
+ * `status.code === 2`, so the failure is on the trace and there is no host client
187
+ * to also notify. Second, flat not nested: every span gets `traceId` (shared when
188
+ * `traceId` is set) but no `parentSpanId`, so model-call and tool spans are
189
+ * siblings under the run rather than a tree OTLP has no ambient span context to
190
+ * parent to here.
191
191
  * @param options `endpoint` (+ optional `token`/`headers`/`serviceName`),
192
192
  * `traceId` to group a run's spans, `waitUntil`, and the `recordInputs`/
193
193
  * `recordOutputs` privacy flags.
@@ -163,7 +163,7 @@ interface OtlpTelemetryOptions extends CommonOptions {
163
163
  /**
164
164
  * An OTLP-over-HTTP telemetry integration for `@lunora/agent`.
165
165
  *
166
- * The OTLP counterpart to {@link sentryTelemetry} / {@link braintrustTelemetry}:
166
+ * The OTLP counterpart to the `sentryTelemetry` / `braintrustTelemetry` bridges:
167
167
  * it wraps each language-model call and tool execution in an OTLP **span**
168
168
  * (`gen_ai.*` semantic-convention attributes — model, provider, token usage,
169
169
  * tool name) and ships it to a collector, so agent generations land in the same
@@ -181,13 +181,13 @@ interface OtlpTelemetryOptions extends CommonOptions {
181
181
  * Each export is fire-and-forget (registered with `waitUntil` when supplied);
182
182
  * every rejection is swallowed so a flaky collector never surfaces to the run.
183
183
  *
184
- * Two deliberate differences from the SDK-backed integrations (`sentryTelemetry`
185
- * / `braintrustTelemetry`), which delegate to a host tracer:
186
- * - **No `onError`.** A failed call already emits a span with `status.code === 2`,
187
- * so the failure is on the trace; there is no host client to also notify.
188
- * - **Flat, not nested.** Every span gets `traceId` (shared when `traceId` is set)
189
- * but no `parentSpanId`, so model-call and tool spans are siblings under the run
190
- * rather than a tree — OTLP has no ambient span context to parent to here.
184
+ * Two deliberate differences from the SDK-backed bridges, which delegate to a
185
+ * host tracer. First, no `onError`: a failed call already emits a span with
186
+ * `status.code === 2`, so the failure is on the trace and there is no host client
187
+ * to also notify. Second, flat not nested: every span gets `traceId` (shared when
188
+ * `traceId` is set) but no `parentSpanId`, so model-call and tool spans are
189
+ * siblings under the run rather than a tree OTLP has no ambient span context to
190
+ * parent to here.
191
191
  * @param options `endpoint` (+ optional `token`/`headers`/`serviceName`),
192
192
  * `traceId` to group a run's spans, `waitUntil`, and the `recordInputs`/
193
193
  * `recordOutputs` privacy flags.
@@ -1,5 +1,5 @@
1
1
  export { braintrustTelemetry } from '../packem_shared/braintrustTelemetry-wuGDErob.mjs';
2
2
  export { combineTelemetry } from '../packem_shared/combineTelemetry-DCyaaWAI.mjs';
3
3
  export { consoleTelemetry } from '../packem_shared/consoleTelemetry-z2MiP1jt.mjs';
4
- export { otlpTelemetry } from '../packem_shared/otlpTelemetry-DL6iZ9e2.mjs';
4
+ export { otlpTelemetry } from '../packem_shared/otlpTelemetry-9ypXork9.mjs';
5
5
  export { sentryTelemetry } from '../packem_shared/sentryTelemetry-CgqFJyLO.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/agent",
3
- "version": "1.0.0-alpha.7",
3
+ "version": "1.0.0-alpha.8",
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",
@@ -76,7 +76,7 @@
76
76
  "access": "public"
77
77
  },
78
78
  "dependencies": {
79
- "@lunora/ai": "1.0.0-alpha.18",
79
+ "@lunora/ai": "1.0.0-alpha.19",
80
80
  "@lunora/errors": "1.0.0-alpha.6",
81
81
  "@lunora/mail": "1.0.0-alpha.16",
82
82
  "@lunora/server": "1.0.0-alpha.29",
@@ -1,55 +0,0 @@
1
- import { defineWorkflow } from '@lunora/workflow';
2
- import { runAgentLoop } from './runAgentLoop-B3Q2o-Uz.mjs';
3
- import { createStreamGenerate, createAgentGenerate, createEpisodeExtract, createGraphExtract, createCompact } from './createAgentGenerate-BQv9YJ01.mjs';
4
- import { agentDefaultName } from '../naming.mjs';
5
- import { DEFAULT_AGENT_FUNCTION_PATHS } from './AGENT_MODULE-Dnt_-AAT.mjs';
6
- import { c as createDispatchRunner } from './createDispatchRunner-DSbp_dph-ZHTtxy3f.mjs';
7
-
8
- const resolveAgentRun = (contextRun, owner, env) => {
9
- if (owner === void 0) {
10
- return contextRun;
11
- }
12
- return createDispatchRunner({ env, identity: { userId: owner }, label: "@lunora/agent" });
13
- };
14
-
15
- const compileAgentWorkflow = (agent, exportName, options) => defineWorkflow({
16
- handler: async (context) => runAgentLoop({
17
- agent,
18
- // Automatic history compaction. Dormant unless the agent declares
19
- // a `compaction` config; the loop gates on it, so any other agent
20
- // takes the byte-identical no-compaction path.
21
- compact: createCompact(),
22
- env: context.env,
23
- exportName,
24
- // Run-end graph extraction. Dormant unless the agent declares a
25
- // `kind: "graph"` memory source AND the run carries an owner — the
26
- // loop gates on both, so a semantic-only agent takes the
27
- // byte-identical no-extraction path.
28
- extractGraph: createGraphExtract(),
29
- // Run-end episode recording. Dormant unless the agent declares a
30
- // `kind: "episodic"` memory source AND the run carries an owner —
31
- // the loop gates on both, so any other agent is byte-identical.
32
- extractEpisode: createEpisodeExtract(),
33
- generate: createAgentGenerate(agent, context.env),
34
- instanceId: context.event.instanceId,
35
- params: context.params,
36
- paths: options?.paths ?? DEFAULT_AGENT_FUNCTION_PATHS,
37
- // The loop reads its own owner-gated thread back through
38
- // `agents:*` queries. The default `context.run` forwards no
39
- // identity, so on an OWNED thread those reads would come back
40
- // empty and the model would answer blind. `resolveAgentRun`
41
- // dispatches an owner-scoped run under that verified identity so
42
- // the owner gate admits the loop's reads (ownerless runs keep the
43
- // identity-free `context.run`). See `resolve-run.ts`.
44
- run: resolveAgentRun(context.run, context.params.owner, context.env),
45
- step: context.step,
46
- // The streaming seam is wired and ready, but stays dormant until a
47
- // live token sink is threaded onto the run (a follow-up wires
48
- // `onTokenDelta` to the stream transport). With no sink the loop
49
- // takes the byte-identical non-streaming `generate` path.
50
- streamGenerate: createStreamGenerate(agent, context.env)
51
- }),
52
- name: agent.name ?? agentDefaultName(exportName)
53
- });
54
-
55
- export { compileAgentWorkflow as default };