@junejs/server 0.1.1 → 0.1.2-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { Channel, ChannelFactory } from "@junejs/core/agent-config";
2
- import { Model, Msg, SessionStore, Tool } from "@junejs/core/agent-runtime";
2
+ import { InboundEvent, Model, Msg, SessionStore, Tool } from "@junejs/core/agent-runtime";
3
3
  import { Resources } from "@junejs/core/resources";
4
4
  //#region src/agent-durable.d.ts
5
5
  type SqlStorageValue = ArrayBuffer | string | number | null;
@@ -54,6 +54,7 @@ declare class AgentDurableObject {
54
54
  turn(input: {
55
55
  turnId?: string;
56
56
  userText: string;
57
+ event?: InboundEvent;
57
58
  }): Promise<string>;
58
59
  transcript(): import("@junejs/core/agent-runtime").Turn[];
59
60
  fetch(req: Request): Promise<Response>;
@@ -85,10 +85,11 @@ var AgentDurableObject = class {
85
85
  async fetch(req) {
86
86
  const url = new URL(req.url);
87
87
  if (req.method === "POST" && url.pathname.endsWith("/turn")) {
88
- const { userText, turnId } = await req.json();
88
+ const { userText, turnId, event } = await req.json();
89
89
  return Response.json({ text: await this.turn({
90
90
  userText,
91
- turnId
91
+ turnId,
92
+ event
92
93
  }) });
93
94
  }
94
95
  if (url.pathname.endsWith("/transcript")) return Response.json({ transcript: this.transcript() });
@@ -128,14 +129,30 @@ function durableChannelSurface(getNamespace, opts) {
128
129
  if (!namespace) throw new Error("durableChannelSurface: no Durable Object namespace bound (env.AGENT)");
129
130
  const { text } = await (await durableFetch(namespace, opts.agentName, o?.session ?? "default", new Request("https://do/turn", {
130
131
  method: "POST",
131
- body: JSON.stringify({
132
- userText: message,
133
- turnId: o?.turnId
134
- })
132
+ body: serializeTurn(message, o)
135
133
  }))).json();
136
134
  return text;
137
135
  }
138
136
  });
139
137
  }
138
+ function serializeTurn(userText, o) {
139
+ const payload = {
140
+ userText,
141
+ turnId: o?.turnId,
142
+ event: o?.event
143
+ };
144
+ try {
145
+ return JSON.stringify(payload);
146
+ } catch {
147
+ const event = o?.event ? {
148
+ ...o.event,
149
+ raw: void 0
150
+ } : void 0;
151
+ return JSON.stringify({
152
+ ...payload,
153
+ event
154
+ });
155
+ }
156
+ }
140
157
  //#endregion
141
158
  export { AgentDurableObject, DoSessionStore, durableAgentSurface, durableChannelSurface, durableFetch };
@@ -154,7 +154,8 @@ function mountAgent(agent, runtime, opts = {}) {
154
154
  agent,
155
155
  run: (message, o) => runtime.session(agent.name, o?.session ?? "default").turn({
156
156
  turnId: o?.turnId,
157
- userText: message
157
+ userText: message,
158
+ event: o?.event
158
159
  })
159
160
  };
160
161
  const channels = channelFetch(agent, ctx);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@junejs/server",
3
- "version": "0.1.1",
3
+ "version": "0.1.2-dev.0",
4
4
  "description": "June host adapters + dev server. Host-coupled; depends on the pure @junejs/core contract layer.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -125,8 +125,8 @@
125
125
  "build": "tsdown"
126
126
  },
127
127
  "dependencies": {
128
- "@junejs/core": ">=0.1.0",
129
- "@junejs/db": ">=0.0.33",
128
+ "@junejs/core": ">=0.1.1-dev.0",
129
+ "@junejs/db": ">=0.0.34-dev.0",
130
130
  "@momiji-rs/sparkdown": "^0.0.4",
131
131
  "lightningcss": "^1.27.0",
132
132
  "oxc-parser": "^0.137.0",
@@ -22,6 +22,7 @@ import {
22
22
  type Model,
23
23
  type Msg,
24
24
  type Runtime,
25
+ type InboundEvent,
25
26
  type SessionStore,
26
27
  type Tool,
27
28
  } from "@junejs/core/agent-runtime";
@@ -190,7 +191,7 @@ export class AgentDurableObject {
190
191
  // Juno's batch-loader registry) can't leak across turns on a long-lived DO.
191
192
  // ensureScope() lazily wires node:async_hooks (workerd via nodejs_compat), as the
192
193
  // pipeline does; without it runInScope is a pass-through and ambient reads throw.
193
- async turn(input: { turnId?: string; userText: string }): Promise<string> {
194
+ async turn(input: { turnId?: string; userText: string; event?: InboundEvent }): Promise<string> {
194
195
  await ensureScope();
195
196
  return runInScope({ resources: this.resources, services: this.services }, () => this.session.turn(input));
196
197
  }
@@ -202,8 +203,8 @@ export class AgentDurableObject {
202
203
  async fetch(req: Request): Promise<Response> {
203
204
  const url = new URL(req.url);
204
205
  if (req.method === "POST" && url.pathname.endsWith("/turn")) {
205
- const { userText, turnId } = (await req.json()) as { userText: string; turnId?: string };
206
- return Response.json({ text: await this.turn({ userText, turnId }) });
206
+ const { userText, turnId, event } = (await req.json()) as { userText: string; turnId?: string; event?: InboundEvent };
207
+ return Response.json({ text: await this.turn({ userText, turnId, event }) });
207
208
  }
208
209
  if (url.pathname.endsWith("/transcript")) return Response.json({ transcript: this.transcript() });
209
210
  return new Response("agent DO — POST /turn or GET /transcript", { status: 404 });
@@ -293,7 +294,7 @@ export function durableChannelSurface(
293
294
  namespace,
294
295
  opts.agentName,
295
296
  o?.session ?? "default",
296
- new Request("https://do/turn", { method: "POST", body: JSON.stringify({ userText: message, turnId: o?.turnId }) }),
297
+ new Request("https://do/turn", { method: "POST", body: serializeTurn(message, o) }),
297
298
  );
298
299
  const { text } = (await res.json()) as { text: string };
299
300
  return text;
@@ -301,3 +302,19 @@ export function durableChannelSurface(
301
302
  };
302
303
  return channelDispatch(resolved, ctx);
303
304
  }
305
+
306
+ // Serialize a turn for the /turn RPC body. InboundEvent.raw is `unknown` — the
307
+ // untouched platform payload — so a (third-party) channel could attach something
308
+ // JSON.stringify chokes on (a circular object, a BigInt). raw isn't needed to route or
309
+ // run the turn, so on a serialization failure we drop it rather than let an
310
+ // unserializable payload take down turn forwarding entirely. (raw is optional on
311
+ // InboundEvent precisely because it may not survive this boundary.)
312
+ function serializeTurn(userText: string, o?: { turnId?: string; event?: InboundEvent }): string {
313
+ const payload = { userText, turnId: o?.turnId, event: o?.event };
314
+ try {
315
+ return JSON.stringify(payload);
316
+ } catch {
317
+ const event = o?.event ? { ...o.event, raw: undefined } : undefined;
318
+ return JSON.stringify({ ...payload, event });
319
+ }
320
+ }
@@ -207,7 +207,7 @@ export function mountAgent(
207
207
  const ctx: ChannelContext = {
208
208
  agent,
209
209
  run: (message, o) =>
210
- runtime.session(agent.name, o?.session ?? "default").turn({ turnId: o?.turnId, userText: message }),
210
+ runtime.session(agent.name, o?.session ?? "default").turn({ turnId: o?.turnId, userText: message, event: o?.event }),
211
211
  };
212
212
  const channels = channelFetch(agent, ctx);
213
213
  const surface = async (req: Request): Promise<Response | null> => {