@junejs/server 0.1.2-dev.0 → 0.1.2-dev.2
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/agent-durable.d.ts +4 -0
- package/dist/agent-durable.js +10 -1
- package/dist/agent-native.d.ts +2 -0
- package/dist/agent-native.js +2 -1
- package/package.json +2 -2
- package/src/agent-durable.ts +28 -1
- package/src/agent-native.ts +4 -3
package/dist/agent-durable.d.ts
CHANGED
|
@@ -43,6 +43,9 @@ type DoAgentDef = {
|
|
|
43
43
|
model: Model;
|
|
44
44
|
tools: Tool[];
|
|
45
45
|
instructions?: string;
|
|
46
|
+
channelInstructions?: Record<string, string>;
|
|
47
|
+
channels?: (Channel | ChannelFactory)[];
|
|
48
|
+
env?: unknown;
|
|
46
49
|
resources?: Resources;
|
|
47
50
|
services?: unknown;
|
|
48
51
|
};
|
|
@@ -68,6 +71,7 @@ declare function durableChannelSurface(getNamespace: () => DurableObjectNamespac
|
|
|
68
71
|
agentName: string;
|
|
69
72
|
channels: (Channel | ChannelFactory)[];
|
|
70
73
|
env: unknown;
|
|
74
|
+
services?: (env: unknown) => unknown;
|
|
71
75
|
waitUntil?: (p: Promise<unknown>) => void;
|
|
72
76
|
}): (req: Request) => Promise<Response | null>;
|
|
73
77
|
//#endregion
|
package/dist/agent-durable.js
CHANGED
|
@@ -70,7 +70,15 @@ var AgentDurableObject = class {
|
|
|
70
70
|
const model = def.instructions ? withSystem(def.model, def.instructions) : def.model;
|
|
71
71
|
this.resources = def.resources ?? {};
|
|
72
72
|
this.services = def.services;
|
|
73
|
-
|
|
73
|
+
const channelTools = (def.channels ?? []).flatMap((c) => resolveChannel(c, def.env).tools?.() ?? []);
|
|
74
|
+
const tools = [...def.tools];
|
|
75
|
+
const seen = new Set(tools.map((t) => t.spec.name));
|
|
76
|
+
for (const t of channelTools) {
|
|
77
|
+
if (seen.has(t.spec.name)) throw new Error(`AgentDurableObject(${def.name ?? "agent"}): duplicate tool name "${t.spec.name}" from a channel — rename so dispatch is unambiguous.`);
|
|
78
|
+
seen.add(t.spec.name);
|
|
79
|
+
tools.push(t);
|
|
80
|
+
}
|
|
81
|
+
this.session = new AgentSession(def.name ?? "agent", "self", store, new InProcBroadcaster(), model, tools, crossDoUnsupported, def.channelInstructions);
|
|
74
82
|
}
|
|
75
83
|
async turn(input) {
|
|
76
84
|
await ensureScope();
|
|
@@ -123,6 +131,7 @@ function durableChannelSurface(getNamespace, opts) {
|
|
|
123
131
|
channels: [],
|
|
124
132
|
connections: []
|
|
125
133
|
},
|
|
134
|
+
services: opts.services?.(opts.env),
|
|
126
135
|
waitUntil: opts.waitUntil,
|
|
127
136
|
run: async (message, o) => {
|
|
128
137
|
const namespace = getNamespace();
|
package/dist/agent-native.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ type AgentDef = {
|
|
|
6
6
|
model: Model;
|
|
7
7
|
tools: Tool[];
|
|
8
8
|
instructions?: string;
|
|
9
|
+
channelInstructions?: Record<string, string>;
|
|
9
10
|
};
|
|
10
11
|
declare class NativeRuntime implements Runtime {
|
|
11
12
|
private actors;
|
|
@@ -30,6 +31,7 @@ declare function createAgentRuntime(agents: Record<string, AgentDef>, opts?: {
|
|
|
30
31
|
declare function mountAgent(agent: AgentDefinition, runtime: Runtime, opts?: {
|
|
31
32
|
chatPath?: string;
|
|
32
33
|
channels?: boolean;
|
|
34
|
+
services?: unknown;
|
|
33
35
|
}): {
|
|
34
36
|
surface: (req: Request) => Promise<Response | null>;
|
|
35
37
|
fetch: (req: Request) => Promise<Response | null>;
|
package/dist/agent-native.js
CHANGED
|
@@ -81,7 +81,7 @@ var NativeRuntime = class {
|
|
|
81
81
|
const def = this.agents[agent];
|
|
82
82
|
if (!def) throw new Error(`unknown agent: ${agent}`);
|
|
83
83
|
const model = def.instructions ? withSystem(def.model, def.instructions) : def.model;
|
|
84
|
-
a = new AgentSession(agent, id, new SqliteSessionStore(this.db, key), new InProcBroadcaster(), model, def.tools, this);
|
|
84
|
+
a = new AgentSession(agent, id, new SqliteSessionStore(this.db, key), new InProcBroadcaster(), model, def.tools, this, def.channelInstructions);
|
|
85
85
|
this.actors.set(key, a);
|
|
86
86
|
}
|
|
87
87
|
return a;
|
|
@@ -152,6 +152,7 @@ function mountAgent(agent, runtime, opts = {}) {
|
|
|
152
152
|
const channelsOn = opts.channels ?? true;
|
|
153
153
|
const ctx = {
|
|
154
154
|
agent,
|
|
155
|
+
services: opts.services,
|
|
155
156
|
run: (message, o) => runtime.session(agent.name, o?.session ?? "default").turn({
|
|
156
157
|
turnId: o?.turnId,
|
|
157
158
|
userText: message,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@junejs/server",
|
|
3
|
-
"version": "0.1.2-dev.
|
|
3
|
+
"version": "0.1.2-dev.2",
|
|
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,7 +125,7 @@
|
|
|
125
125
|
"build": "tsdown"
|
|
126
126
|
},
|
|
127
127
|
"dependencies": {
|
|
128
|
-
"@junejs/core": ">=0.1.1-dev.
|
|
128
|
+
"@junejs/core": ">=0.1.1-dev.4",
|
|
129
129
|
"@junejs/db": ">=0.0.34-dev.0",
|
|
130
130
|
"@momiji-rs/sparkdown": "^0.0.4",
|
|
131
131
|
"lightningcss": "^1.27.0",
|
package/src/agent-durable.ts
CHANGED
|
@@ -153,6 +153,16 @@ export type DoAgentDef = {
|
|
|
153
153
|
model: Model;
|
|
154
154
|
tools: Tool[];
|
|
155
155
|
instructions?: string;
|
|
156
|
+
// Per-channel-source system overlays (see AgentDefinition.channelInstructions) — the
|
|
157
|
+
// shared agent branches by real inbound source, no userText marker.
|
|
158
|
+
channelInstructions?: Record<string, string>;
|
|
159
|
+
// Channels whose CAPABILITY tools should be available to this session's turns. Their
|
|
160
|
+
// tools are built HERE, in the DO isolate, from `env` — because a channel's tool `run`
|
|
161
|
+
// is a closure (over the bot token, etc.) that can't cross the worker→DO RPC. This is
|
|
162
|
+
// the edge equivalent of defineAgent merging channel.tools() on native: pass the same
|
|
163
|
+
// channel factories you mount on the worker, plus this DO's env.
|
|
164
|
+
channels?: (Channel | ChannelFactory)[];
|
|
165
|
+
env?: unknown;
|
|
156
166
|
resources?: Resources;
|
|
157
167
|
services?: unknown;
|
|
158
168
|
};
|
|
@@ -182,7 +192,18 @@ export class AgentDurableObject {
|
|
|
182
192
|
const model = def.instructions ? withSystem(def.model, def.instructions) : def.model;
|
|
183
193
|
this.resources = def.resources ?? {};
|
|
184
194
|
this.services = def.services;
|
|
185
|
-
|
|
195
|
+
// Merge the mounted channels' capability tools (built here from this DO's env, since a
|
|
196
|
+
// tool's `run` closure can't cross the RPC). The cross-channel source gate on each tool
|
|
197
|
+
// keeps a Slack tool inert during a Crisp turn, so merging all of them is safe.
|
|
198
|
+
const channelTools = (def.channels ?? []).flatMap((c) => resolveChannel(c, def.env).tools?.() ?? []);
|
|
199
|
+
const tools: Tool[] = [...def.tools];
|
|
200
|
+
const seen = new Set(tools.map((t) => t.spec.name));
|
|
201
|
+
for (const t of channelTools) {
|
|
202
|
+
if (seen.has(t.spec.name)) throw new Error(`AgentDurableObject(${def.name ?? "agent"}): duplicate tool name "${t.spec.name}" from a channel — rename so dispatch is unambiguous.`);
|
|
203
|
+
seen.add(t.spec.name);
|
|
204
|
+
tools.push(t);
|
|
205
|
+
}
|
|
206
|
+
this.session = new AgentSession(def.name ?? "agent", "self", store, new InProcBroadcaster(), model, tools, crossDoUnsupported, def.channelInstructions);
|
|
186
207
|
}
|
|
187
208
|
// Run the whole turn inside a request scope seeded from this DO's env, so ambient
|
|
188
209
|
// `db`/`kv`/`blob` and `currentServices()` resolve inside a tool exactly as in a
|
|
@@ -278,6 +299,11 @@ export function durableChannelSurface(
|
|
|
278
299
|
agentName: string;
|
|
279
300
|
channels: (Channel | ChannelFactory)[];
|
|
280
301
|
env: unknown;
|
|
302
|
+
// The app's services factory — the SAME one AgentDurableObject uses — resolved HERE
|
|
303
|
+
// (worker isolate) and exposed to channel hooks as ctx.services. Channel hooks run at
|
|
304
|
+
// the edge, outside the DO, so they can't read the DO's ambient currentServices(); this
|
|
305
|
+
// gives them the same DI bag. Resolved once per surface construction.
|
|
306
|
+
services?: (env: unknown) => unknown;
|
|
281
307
|
waitUntil?: (p: Promise<unknown>) => void;
|
|
282
308
|
},
|
|
283
309
|
): (req: Request) => Promise<Response | null> {
|
|
@@ -286,6 +312,7 @@ export function durableChannelSurface(
|
|
|
286
312
|
// A minimal but complete AgentDefinition — channels only read ctx.agent.name; the
|
|
287
313
|
// full def isn't present in the worker (tools/model live in the DO).
|
|
288
314
|
agent: { name: opts.agentName, instructions: "", tools: [], skills: [], channels: [], connections: [] } satisfies AgentDefinition,
|
|
315
|
+
services: opts.services?.(opts.env),
|
|
289
316
|
waitUntil: opts.waitUntil,
|
|
290
317
|
run: async (message, o) => {
|
|
291
318
|
const namespace = getNamespace();
|
package/src/agent-native.ts
CHANGED
|
@@ -85,7 +85,7 @@ class InProcBroadcaster implements Broadcaster {
|
|
|
85
85
|
|
|
86
86
|
// `instructions` (the agent's system prompt) is injected into the model per turn
|
|
87
87
|
// by the runtime (withSystem) — single-sourced on the def, not baked into `model`.
|
|
88
|
-
export type AgentDef = { model: Model; tools: Tool[]; instructions?: string };
|
|
88
|
+
export type AgentDef = { model: Model; tools: Tool[]; instructions?: string; channelInstructions?: Record<string, string> };
|
|
89
89
|
|
|
90
90
|
// The native Runtime: a registry of agent definitions over one SQLite handle,
|
|
91
91
|
// handing out (and memoizing) an AgentSession actor per (agent, id).
|
|
@@ -107,7 +107,7 @@ export class NativeRuntime implements Runtime {
|
|
|
107
107
|
const def = this.agents[agent];
|
|
108
108
|
if (!def) throw new Error(`unknown agent: ${agent}`);
|
|
109
109
|
const model = def.instructions ? withSystem(def.model, def.instructions) : def.model;
|
|
110
|
-
a = new AgentSession(agent, id, new SqliteSessionStore(this.db, key), new InProcBroadcaster(), model, def.tools, this);
|
|
110
|
+
a = new AgentSession(agent, id, new SqliteSessionStore(this.db, key), new InProcBroadcaster(), model, def.tools, this, def.channelInstructions);
|
|
111
111
|
this.actors.set(key, a);
|
|
112
112
|
}
|
|
113
113
|
return a;
|
|
@@ -195,7 +195,7 @@ export async function createAgentRuntime(
|
|
|
195
195
|
export function mountAgent(
|
|
196
196
|
agent: AgentDefinition,
|
|
197
197
|
runtime: Runtime,
|
|
198
|
-
opts: { chatPath?: string; channels?: boolean } = {},
|
|
198
|
+
opts: { chatPath?: string; channels?: boolean; services?: unknown } = {},
|
|
199
199
|
): {
|
|
200
200
|
surface: (req: Request) => Promise<Response | null>;
|
|
201
201
|
fetch: (req: Request) => Promise<Response | null>;
|
|
@@ -206,6 +206,7 @@ export function mountAgent(
|
|
|
206
206
|
const channelsOn = opts.channels ?? true;
|
|
207
207
|
const ctx: ChannelContext = {
|
|
208
208
|
agent,
|
|
209
|
+
services: opts.services, // same DI bag reachable from channel hooks (parity with durableChannelSurface)
|
|
209
210
|
run: (message, o) =>
|
|
210
211
|
runtime.session(agent.name, o?.session ?? "default").turn({ turnId: o?.turnId, userText: message, event: o?.event }),
|
|
211
212
|
};
|