@junejs/server 1.0.0-dev.17 → 1.0.0-dev.20
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/adapter-DcZ-W1-7.d.ts +62 -0
- package/dist/adapter.d.ts +1 -61
- package/dist/agent-compile.d.ts +4 -0
- package/dist/agent-compile.js +8 -2
- package/dist/agent-discover.js +13 -1
- package/dist/agent-durable.d.ts +8 -2
- package/dist/agent-durable.js +31 -5
- package/dist/build.d.ts +5 -26
- package/dist/build.js +13 -279
- package/dist/config-freeze-DwI-Rmvq.d.ts +17 -0
- package/dist/config-freeze.d.ts +2 -0
- package/dist/config-freeze.js +51 -0
- package/dist/connection-auth.d.ts +39 -0
- package/dist/connection-auth.js +31 -0
- package/dist/content-freeze-CyiW2fRK.d.ts +4 -0
- package/dist/content-freeze.d.ts +2 -0
- package/dist/content-freeze.js +83 -0
- package/dist/index.d.ts +9 -4
- package/dist/index.js +7 -2
- package/dist/manifest-gcNWqWoI.d.ts +11 -0
- package/dist/manifest.d.ts +2 -0
- package/dist/manifest.js +111 -0
- package/dist/route-scan-DMlwoESy.d.ts +13 -0
- package/dist/route-scan.d.ts +2 -0
- package/dist/route-scan.js +55 -0
- package/dist/worker-BkFHGtxp.d.ts +61 -0
- package/dist/worker.d.ts +2 -56
- package/dist/worker.js +28 -9
- package/package.json +2 -2
- package/src/agent-compile.ts +26 -0
- package/src/agent-discover.ts +44 -15
- package/src/agent-durable.ts +63 -8
- package/src/build.ts +31 -443
- package/src/config-freeze.ts +104 -0
- package/src/connection-auth.ts +101 -0
- package/src/content-freeze.ts +151 -0
- package/src/index.ts +14 -0
- package/src/manifest.ts +128 -0
- package/src/route-scan.ts +84 -0
- package/src/worker.ts +66 -18
package/src/agent-durable.ts
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
AgentSession,
|
|
20
20
|
ResumeAuthorizationError,
|
|
21
21
|
withSystem,
|
|
22
|
+
type ChannelPolicy,
|
|
22
23
|
type EventSink,
|
|
23
24
|
type TurnEvent,
|
|
24
25
|
type Model,
|
|
@@ -35,6 +36,7 @@ import type { Resources } from "@junejs/core/resources";
|
|
|
35
36
|
import {
|
|
36
37
|
channelDispatch,
|
|
37
38
|
DeliverUnsupportedError,
|
|
39
|
+
actionToTool,
|
|
38
40
|
resolveChannel,
|
|
39
41
|
type AgentDefinition,
|
|
40
42
|
type Channel,
|
|
@@ -42,6 +44,7 @@ import {
|
|
|
42
44
|
type ChannelFactory,
|
|
43
45
|
type ResumeDeliveryTarget,
|
|
44
46
|
} from "@junejs/core/agent-config";
|
|
47
|
+
import { connectAll, type Connection } from "@junejs/core/connections";
|
|
45
48
|
import { ensureScope, runInScope } from "@junejs/db";
|
|
46
49
|
import { isolateLocal } from "./isolate-local";
|
|
47
50
|
import { assertCoreRuntimeVersion } from "./core-version";
|
|
@@ -198,9 +201,12 @@ export type DoAgentDef = {
|
|
|
198
201
|
model: Model;
|
|
199
202
|
tools: Tool[];
|
|
200
203
|
instructions?: string;
|
|
201
|
-
// Per-channel-source
|
|
202
|
-
//
|
|
203
|
-
|
|
204
|
+
// Per-channel-source turn policies (see AgentDefinition.channelInstructions):
|
|
205
|
+
// an overlay string, or a ChannelPolicy carrying overlay/overlayMode/denyTools
|
|
206
|
+
// (#149 — derived from agent-level instructions.<source>.md + surfaces config
|
|
207
|
+
// by assembleDurable). The shared agent branches by real inbound source, no
|
|
208
|
+
// userText marker.
|
|
209
|
+
channelInstructions?: Record<string, string | ChannelPolicy>;
|
|
204
210
|
// Channels whose CAPABILITY tools should be available to this session's turns. Their
|
|
205
211
|
// tools are built HERE, in the DO isolate, from `env` — because a channel's tool `run`
|
|
206
212
|
// is a closure (over the bot token, etc.) that can't cross the worker→DO RPC. This is
|
|
@@ -213,6 +219,12 @@ export type DoAgentDef = {
|
|
|
213
219
|
// constructor cannot await, so a provider is resolved lazily at the first
|
|
214
220
|
// turn (once per DO instance) with this def's `env`.
|
|
215
221
|
resources?: Resources | ((env: unknown) => Promise<Resources> | Resources);
|
|
222
|
+
// Outbound connection DEFINITIONS (external MCP/OpenAPI servers). Wiring them
|
|
223
|
+
// is network I/O (connectAll), which a DO constructor cannot await — resolved
|
|
224
|
+
// lazily at the first turn, their tools merged into the agent's tool set
|
|
225
|
+
// before any session is constructed. The native equivalent happens at
|
|
226
|
+
// assembly (assembleAgent → connectAll).
|
|
227
|
+
connections?: Connection[];
|
|
216
228
|
services?: unknown;
|
|
217
229
|
// Called on every turn.failed for this session — the app's seam for routing turn
|
|
218
230
|
// failures to its own telemetry (Sentry, a ledger, …). Providing it REPLACES the
|
|
@@ -256,13 +268,15 @@ export class AgentDurableObject {
|
|
|
256
268
|
private readonly model: Model;
|
|
257
269
|
private readonly tools: Tool[];
|
|
258
270
|
private readonly channels: Channel[];
|
|
259
|
-
private readonly channelInstructions?: Record<string, string>;
|
|
271
|
+
private readonly channelInstructions?: Record<string, string | ChannelPolicy>;
|
|
260
272
|
// A bag is used as-is; a provider (bindWorkerResources' shape) is resolved
|
|
261
273
|
// lazily at the first turn with the def's env — opening a D1 handle is async
|
|
262
274
|
// and this constructor cannot await. Resolved once, shared across turns (env
|
|
263
275
|
// is stable per isolate, like bindWorkerResources memoizes per worker isolate).
|
|
264
276
|
private readonly resourcesInput: DoAgentDef["resources"];
|
|
265
277
|
private resourcesOpened: Promise<Resources> | undefined;
|
|
278
|
+
private readonly connectionsInput: Connection[] | undefined;
|
|
279
|
+
private connectionsOpened: Promise<void> | undefined;
|
|
266
280
|
private readonly doEnv: unknown;
|
|
267
281
|
private readonly services: unknown;
|
|
268
282
|
private resolveResources(): Promise<Resources> {
|
|
@@ -270,11 +284,40 @@ export class AgentDurableObject {
|
|
|
270
284
|
typeof this.resourcesInput === "function" ? this.resourcesInput(this.doEnv) : (this.resourcesInput ?? {}),
|
|
271
285
|
));
|
|
272
286
|
}
|
|
287
|
+
// Wire outbound connections once (network I/O the constructor can't await):
|
|
288
|
+
// their tools merge into this.tools BEFORE any session is constructed — the
|
|
289
|
+
// ready() callers hoist this ahead of resolveSession. A failed connection is
|
|
290
|
+
// reported and skipped (connectAll never throws), matching native assembly.
|
|
291
|
+
private resolveConnections(): Promise<void> {
|
|
292
|
+
return (this.connectionsOpened ??= (async () => {
|
|
293
|
+
if (!this.connectionsInput?.length) return;
|
|
294
|
+
const { actions, report } = await connectAll(this.connectionsInput);
|
|
295
|
+
for (const r of report) {
|
|
296
|
+
if (r.error) console.error(`[june] agent "${this.name}": connection "${r.name}" (${r.url}) failed: ${r.error}`);
|
|
297
|
+
}
|
|
298
|
+
const seen = new Set(this.tools.map((t) => t.spec.name));
|
|
299
|
+
for (const a of actions) {
|
|
300
|
+
const tool = actionToTool(a);
|
|
301
|
+
if (seen.has(tool.spec.name)) {
|
|
302
|
+
throw new Error(`AgentDurableObject(${this.name}): duplicate tool name "${tool.spec.name}" from a connection — rename so dispatch is unambiguous.`);
|
|
303
|
+
}
|
|
304
|
+
seen.add(tool.spec.name);
|
|
305
|
+
this.tools.push(tool);
|
|
306
|
+
}
|
|
307
|
+
})());
|
|
308
|
+
}
|
|
309
|
+
// Everything a turn needs opened BEFORE its synchronous scope-and-subscribe
|
|
310
|
+
// section: resources (possibly an async provider) and outbound connections.
|
|
311
|
+
private async ready(): Promise<Resources> {
|
|
312
|
+
const [resources] = await Promise.all([this.resolveResources(), this.resolveConnections()]);
|
|
313
|
+
return resources;
|
|
314
|
+
}
|
|
273
315
|
constructor(state: DurableObjectState, def: DoAgentDef) {
|
|
274
316
|
assertCoreRuntimeVersion(`AgentDurableObject(${def.name ?? "agent"})`); // #94: fail power-on, not mid-turn
|
|
275
317
|
const store = new DoSessionStore(state.storage);
|
|
276
318
|
const model = def.instructions ? withSystem(def.model, def.instructions) : def.model;
|
|
277
319
|
this.resourcesInput = def.resources;
|
|
320
|
+
this.connectionsInput = def.connections;
|
|
278
321
|
this.doEnv = def.env;
|
|
279
322
|
this.services = def.services;
|
|
280
323
|
const name = def.name ?? "agent";
|
|
@@ -335,6 +378,18 @@ export class AgentDurableObject {
|
|
|
335
378
|
this.tools = tools;
|
|
336
379
|
this.channels = channels;
|
|
337
380
|
this.channelInstructions = def.channelInstructions;
|
|
381
|
+
// Orphan-policy check (#149): assembly can't validate surface keys against
|
|
382
|
+
// factory channels (they resolve only here, with env) — so warn now, once,
|
|
383
|
+
// when a policy's source matches no resolved channel. A policy that never
|
|
384
|
+
// fires is the old silent failure; a warning is its floor.
|
|
385
|
+
if (def.channelInstructions) {
|
|
386
|
+
const names = new Set(channels.map((c) => c.name));
|
|
387
|
+
for (const source of Object.keys(def.channelInstructions)) {
|
|
388
|
+
if (!names.has(source)) {
|
|
389
|
+
console.warn(`[june] agent "${name}": surface policy "${source}" matches no channel wired into this DO (${[...names].join(", ") || "none"}) — it will never fire.`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
338
393
|
}
|
|
339
394
|
// Resolve THE session for this DO: explicit key (from a routed request) → persisted
|
|
340
395
|
// key (a prior life learned it) → "self". A key that contradicts the persisted or
|
|
@@ -382,7 +437,7 @@ export class AgentDurableObject {
|
|
|
382
437
|
// pipeline does; without it runInScope is a pass-through and ambient reads throw.
|
|
383
438
|
async turn(input: { turnId?: string; userText: string; event?: InboundEvent; trigger?: ProactiveTrigger; session?: string }): Promise<string> {
|
|
384
439
|
await ensureScope();
|
|
385
|
-
const resources = await this.
|
|
440
|
+
const resources = await this.ready();
|
|
386
441
|
const session = this.resolveSession(input.session);
|
|
387
442
|
return runInScope({ resources, services: this.services }, () => session.turn(input));
|
|
388
443
|
}
|
|
@@ -392,7 +447,7 @@ export class AgentDurableObject {
|
|
|
392
447
|
// the default turn-failure log / onTurnError (#76).
|
|
393
448
|
async start(input: { turnId?: string; userText: string; event?: InboundEvent; trigger?: ProactiveTrigger; session?: string }): Promise<{ turnId: string }> {
|
|
394
449
|
await ensureScope();
|
|
395
|
-
const resources = await this.
|
|
450
|
+
const resources = await this.ready();
|
|
396
451
|
const session = this.resolveSession(input.session);
|
|
397
452
|
return runInScope({ resources, services: this.services }, () => session.start(input));
|
|
398
453
|
}
|
|
@@ -450,7 +505,7 @@ export class AgentDurableObject {
|
|
|
450
505
|
// db/services (ALS propagates to the .then continuation registered here); subscribing
|
|
451
506
|
// happens synchronously right after, before any event can emit. Resources resolve
|
|
452
507
|
// BEFORE this block — the section from start() to the subscription stays synchronous.
|
|
453
|
-
const resources = await this.
|
|
508
|
+
const resources = await this.ready();
|
|
454
509
|
let session: AgentSession;
|
|
455
510
|
let started: { turnId: string };
|
|
456
511
|
try {
|
|
@@ -535,7 +590,7 @@ export class AgentDurableObject {
|
|
|
535
590
|
}
|
|
536
591
|
// Same discipline as /turn: resolve resources before the synchronous
|
|
537
592
|
// resume-then-subscribe section.
|
|
538
|
-
const resources = await this.
|
|
593
|
+
const resources = await this.ready();
|
|
539
594
|
let session: AgentSession;
|
|
540
595
|
try {
|
|
541
596
|
session = this.resolveSession(key);
|