@junejs/server 1.0.0-dev.29 → 1.0.0-dev.42
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-compile.d.ts +8 -9
- package/dist/agent-discover.d.ts +3 -4
- package/dist/agent-durable.d.ts +38 -20
- package/dist/agent-durable.js +159 -13
- package/dist/agent-native.d.ts +15 -12
- package/dist/agent-native.js +72 -8
- package/dist/app.d.ts +4 -5
- package/dist/app.js +2 -1
- package/dist/blob.d.ts +4 -5
- package/dist/build.d.ts +6 -6
- package/dist/build.js +38 -7
- package/dist/client-bundle.d.ts +8 -9
- package/dist/{config-freeze-DwI-Rmvq.d.ts → config-freeze-ZWC_Qd4h.d.ts} +1 -1
- package/dist/config-freeze.d.ts +1 -1
- package/dist/config-loader.d.ts +3 -4
- package/dist/connection-auth.d.ts +8 -9
- package/dist/content.d.ts +9 -10
- package/dist/core-version.d.ts +3 -4
- package/dist/core-version.js +1 -1
- package/dist/css-modules-ambient.d.ts +2 -1
- package/dist/css-modules.d.ts +10 -11
- package/dist/css.d.ts +9 -10
- package/dist/d1-migrate.d.ts +6 -7
- package/dist/d1-migrate.js +3 -2
- package/dist/db.d.ts +2 -2
- package/dist/deploy.d.ts +3 -4
- package/dist/deploy.js +3 -2
- package/dist/dev-reload.d.ts +3 -4
- package/dist/dev.d.ts +4 -5
- package/dist/favicon.d.ts +16 -17
- package/dist/host.d.ts +5 -5
- package/dist/icon-letter.d.ts +2 -3
- package/dist/index.d.ts +4 -4
- package/dist/instrumentation.d.ts +2 -3
- package/dist/instrumentation.js +2 -1
- package/dist/island-registry.d.ts +6 -7
- package/dist/isolate-local.d.ts +4 -5
- package/dist/kv.d.ts +3 -4
- package/dist/llms-links.d.ts +8 -5
- package/dist/llms-links.js +31 -1
- package/dist/{manifest-gcNWqWoI.d.ts → manifest-DSNX4I-G.d.ts} +2 -2
- package/dist/manifest.d.ts +1 -1
- package/dist/negotiate.d.ts +4 -3
- package/dist/negotiate.js +24 -14
- package/dist/{pipeline-cCR6MGNK.d.ts → pipeline-BHUjBO0G.d.ts} +5 -1
- package/dist/pipeline.d.ts +2 -2
- package/dist/pipeline.js +260 -41
- package/dist/resources.d.ts +5 -6
- package/dist/router.d.ts +12 -13
- package/dist/rsc-build.d.ts +6 -7
- package/dist/rsc-bundle.d.ts +6 -7
- package/dist/rsc-manifest.d.ts +5 -6
- package/dist/rsc-runtime/flight-render-routes.d.ts +3 -4
- package/dist/rsc-runtime/flight-render.d.ts +2 -3
- package/dist/rsc-runtime/flight-to-html.d.ts +2 -3
- package/dist/rsc-runtime/flight-to-html.js +3 -2
- package/dist/rsc-runtime/rsdw-shims.d.ts +2 -1
- package/dist/segment.d.ts +4 -5
- package/dist/sqlite-driver.d.ts +10 -11
- package/dist/static-files.d.ts +4 -5
- package/dist/tsconfig-jsx.d.ts +4 -5
- package/dist/turn-events.d.ts +2 -3
- package/dist/web-manifest.d.ts +3 -4
- package/dist/web-manifest.js +2 -6
- package/dist/{worker-BkFHGtxp.d.ts → worker-Dv4l6Ybs.d.ts} +4 -2
- package/dist/worker.d.ts +1 -1
- package/dist/worker.js +35 -18
- package/package.json +5 -5
- package/src/agent-durable.ts +203 -21
- package/src/agent-native.ts +94 -7
- package/src/build.ts +67 -5
- package/src/core-version.ts +1 -1
- package/src/llms-links.ts +46 -1
- package/src/negotiate.ts +39 -15
- package/src/pipeline.ts +433 -45
- package/src/web-manifest.ts +2 -6
- package/src/worker.ts +55 -17
package/dist/agent-compile.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/agent-compile.d.ts
|
|
2
|
-
declare const AGENT_MODULE_FILE = "_agent.gen.ts";
|
|
3
|
-
type AgentDirScan = {
|
|
2
|
+
export declare const AGENT_MODULE_FILE = "_agent.gen.ts";
|
|
3
|
+
export type AgentDirScan = {
|
|
4
4
|
dir: string;
|
|
5
5
|
name: string;
|
|
6
6
|
hasConfig: boolean;
|
|
@@ -21,13 +21,13 @@ type AgentDirScan = {
|
|
|
21
21
|
}[];
|
|
22
22
|
connections: string[];
|
|
23
23
|
};
|
|
24
|
-
declare function scanAgentDir(dir: string): AgentDirScan | null;
|
|
25
|
-
type EmitOptions = {
|
|
24
|
+
export declare function scanAgentDir(dir: string): AgentDirScan | null;
|
|
25
|
+
export type EmitOptions = {
|
|
26
26
|
tsExtensions?: boolean;
|
|
27
27
|
};
|
|
28
|
-
declare function emitAgentModule(scan: AgentDirScan, opts?: EmitOptions): string;
|
|
29
|
-
declare function findAgentDir(root: string, dirName?: string): string | null;
|
|
30
|
-
declare function generateAgentModule(dir: string, opts?: {
|
|
28
|
+
export declare function emitAgentModule(scan: AgentDirScan, opts?: EmitOptions): string;
|
|
29
|
+
export declare function findAgentDir(root: string, dirName?: string): string | null;
|
|
30
|
+
export declare function generateAgentModule(dir: string, opts?: {
|
|
31
31
|
check?: boolean;
|
|
32
32
|
} & EmitOptions): {
|
|
33
33
|
file: string;
|
|
@@ -35,5 +35,4 @@ declare function generateAgentModule(dir: string, opts?: {
|
|
|
35
35
|
stale: boolean;
|
|
36
36
|
written: boolean;
|
|
37
37
|
} | null;
|
|
38
|
-
//#endregion
|
|
39
|
-
export { AGENT_MODULE_FILE, AgentDirScan, EmitOptions, emitAgentModule, findAgentDir, generateAgentModule, scanAgentDir };
|
|
38
|
+
//#endregion
|
package/dist/agent-discover.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { AgentDefinition, AgentModule } from "@junejs/core/agent-config";
|
|
2
2
|
//#region src/agent-discover.d.ts
|
|
3
|
-
declare function discoverAgentModule(dir: string): Promise<AgentModule>;
|
|
4
|
-
declare function discoverAgent(dir: string): Promise<AgentDefinition>;
|
|
5
|
-
//#endregion
|
|
6
|
-
export { discoverAgent, discoverAgentModule };
|
|
3
|
+
export declare function discoverAgentModule(dir: string): Promise<AgentModule>;
|
|
4
|
+
export declare function discoverAgent(dir: string): Promise<AgentDefinition>;
|
|
5
|
+
//#endregion
|
package/dist/agent-durable.d.ts
CHANGED
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
import { Channel, ChannelFactory } from "@junejs/core/agent-config";
|
|
2
|
-
import { ChannelPolicy, InboundEvent, Model, Msg, ProactiveTrigger, SessionStore, Tool, TurnError, TurnEvent, TurnFailurePhase } from "@junejs/core/agent-runtime";
|
|
2
|
+
import { AuthorizeAnswer, ChannelPolicy, InboundEvent, InputAnnouncement, Model, Msg, NoteKind, ProactiveTrigger, SessionStore, Tool, TurnError, TurnEvent, TurnFailurePhase } from "@junejs/core/agent-runtime";
|
|
3
3
|
import { Connection } from "@junejs/core/connections";
|
|
4
4
|
import { Resources } from "@junejs/core/resources";
|
|
5
5
|
//#region src/agent-durable.d.ts
|
|
6
|
-
type SqlStorageValue = ArrayBuffer | string | number | null;
|
|
7
|
-
interface SqlStorageCursor<T extends Record<string, SqlStorageValue> = Record<string, SqlStorageValue>> {
|
|
6
|
+
export type SqlStorageValue = ArrayBuffer | string | number | null;
|
|
7
|
+
export interface SqlStorageCursor<T extends Record<string, SqlStorageValue> = Record<string, SqlStorageValue>> {
|
|
8
8
|
toArray(): T[];
|
|
9
9
|
one(): T;
|
|
10
10
|
}
|
|
11
|
-
interface SqlStorage {
|
|
11
|
+
export interface SqlStorage {
|
|
12
12
|
exec<T extends Record<string, SqlStorageValue> = Record<string, SqlStorageValue>>(query: string, ...bindings: unknown[]): SqlStorageCursor<T>;
|
|
13
13
|
}
|
|
14
|
-
interface DurableStorage {
|
|
14
|
+
export interface DurableStorage {
|
|
15
15
|
sql: SqlStorage;
|
|
16
16
|
transactionSync<T>(fn: () => T): T;
|
|
17
|
+
setAlarm?(scheduledTime: number): unknown;
|
|
17
18
|
}
|
|
18
|
-
interface DurableObjectState {
|
|
19
|
+
export interface DurableObjectState {
|
|
19
20
|
storage: DurableStorage;
|
|
20
21
|
}
|
|
21
|
-
interface DurableObjectStub {
|
|
22
|
+
export interface DurableObjectStub {
|
|
22
23
|
fetch(request: Request): Promise<Response>;
|
|
23
24
|
}
|
|
24
|
-
interface DurableObjectNamespace {
|
|
25
|
+
export interface DurableObjectNamespace {
|
|
25
26
|
idFromName(name: string): unknown;
|
|
26
27
|
get(id: unknown): DurableObjectStub;
|
|
27
28
|
}
|
|
28
|
-
declare class DoSessionStore implements SessionStore {
|
|
29
|
+
export declare class DoSessionStore implements SessionStore {
|
|
29
30
|
private readonly storage;
|
|
30
31
|
constructor(storage: DurableStorage);
|
|
31
32
|
private get sql();
|
|
@@ -40,10 +41,10 @@ declare class DoSessionStore implements SessionStore {
|
|
|
40
41
|
getSessionKey(): string | undefined;
|
|
41
42
|
setSessionKey(key: string): void;
|
|
42
43
|
tx<T>(fn: () => T): T;
|
|
43
|
-
reset(): number;
|
|
44
|
+
reset(inTx?: () => void): number;
|
|
44
45
|
unwrap<H = unknown>(): H;
|
|
45
46
|
}
|
|
46
|
-
type DoAgentDef = {
|
|
47
|
+
export type DoAgentDef = {
|
|
47
48
|
name?: string;
|
|
48
49
|
model: Model;
|
|
49
50
|
tools: Tool[];
|
|
@@ -60,8 +61,10 @@ type DoAgentDef = {
|
|
|
60
61
|
phase?: TurnFailurePhase;
|
|
61
62
|
step?: string;
|
|
62
63
|
}) => void | Promise<void>;
|
|
64
|
+
authorizeAnswer?: AuthorizeAnswer;
|
|
65
|
+
onInputAnnouncement?: (a: InputAnnouncement) => void | Promise<void>;
|
|
63
66
|
};
|
|
64
|
-
declare class AgentDurableObject {
|
|
67
|
+
export declare class AgentDurableObject {
|
|
65
68
|
private session;
|
|
66
69
|
private sessionKey;
|
|
67
70
|
private readonly name;
|
|
@@ -77,11 +80,19 @@ declare class AgentDurableObject {
|
|
|
77
80
|
private connectionsOpened;
|
|
78
81
|
private readonly doEnv;
|
|
79
82
|
private readonly services;
|
|
83
|
+
private readonly authorizeAnswer?;
|
|
84
|
+
private readonly onInputAnnouncement?;
|
|
85
|
+
private readonly storage;
|
|
86
|
+
private announceFailures;
|
|
80
87
|
private resolveResources;
|
|
81
88
|
private resolveConnections;
|
|
82
89
|
private ready;
|
|
83
90
|
constructor(state: DurableObjectState, def: DoAgentDef);
|
|
84
91
|
private resolveSession;
|
|
92
|
+
alarm(): Promise<void>;
|
|
93
|
+
private armWatchdog;
|
|
94
|
+
private scheduleAlarm;
|
|
95
|
+
private deliverHeld;
|
|
85
96
|
turn(input: {
|
|
86
97
|
turnId?: string;
|
|
87
98
|
userText: string;
|
|
@@ -98,6 +109,14 @@ declare class AgentDurableObject {
|
|
|
98
109
|
}): Promise<{
|
|
99
110
|
turnId: string;
|
|
100
111
|
}>;
|
|
112
|
+
note(input: {
|
|
113
|
+
by: string;
|
|
114
|
+
kind: NoteKind;
|
|
115
|
+
text: string;
|
|
116
|
+
session?: string;
|
|
117
|
+
}): Promise<{
|
|
118
|
+
noteId: string;
|
|
119
|
+
}>;
|
|
101
120
|
reset(opts?: {
|
|
102
121
|
session?: string;
|
|
103
122
|
}): Promise<{
|
|
@@ -107,20 +126,19 @@ declare class AgentDurableObject {
|
|
|
107
126
|
transcript(): import("@junejs/core/agent-runtime").Turn[];
|
|
108
127
|
fetch(req: Request): Promise<Response>;
|
|
109
128
|
}
|
|
110
|
-
declare function sseTurnFinalText(res: Response): Promise<string>;
|
|
111
|
-
declare function sseTurnEvents(res: Response): AsyncIterable<TurnEvent>;
|
|
112
|
-
declare const SESSION_HEADER = "x-june-session";
|
|
113
|
-
declare function durableFetch(namespace: DurableObjectNamespace, agent: string, session: string, req: Request): Promise<Response>;
|
|
114
|
-
declare function durableAgentSurface(getNamespace: () => DurableObjectNamespace | undefined, opts: {
|
|
129
|
+
export declare function sseTurnFinalText(res: Response): Promise<string>;
|
|
130
|
+
export declare function sseTurnEvents(res: Response): AsyncIterable<TurnEvent>;
|
|
131
|
+
export declare const SESSION_HEADER = "x-june-session";
|
|
132
|
+
export declare function durableFetch(namespace: DurableObjectNamespace, agent: string, session: string, req: Request): Promise<Response>;
|
|
133
|
+
export declare function durableAgentSurface(getNamespace: () => DurableObjectNamespace | undefined, opts: {
|
|
115
134
|
agentName: string;
|
|
116
135
|
chatPath?: string;
|
|
117
136
|
}): (req: Request) => Promise<Response | null>;
|
|
118
|
-
declare function durableChannelSurface(getNamespace: () => DurableObjectNamespace | undefined, opts: {
|
|
137
|
+
export declare function durableChannelSurface(getNamespace: () => DurableObjectNamespace | undefined, opts: {
|
|
119
138
|
agentName: string;
|
|
120
139
|
channels: (Channel | ChannelFactory)[];
|
|
121
140
|
env: unknown;
|
|
122
141
|
services?: (env: unknown) => unknown;
|
|
123
142
|
waitUntil?: (p: Promise<unknown>) => void;
|
|
124
143
|
}): (req: Request) => Promise<Response | null>;
|
|
125
|
-
//#endregion
|
|
126
|
-
export { AgentDurableObject, DoAgentDef, DoSessionStore, DurableObjectNamespace, DurableObjectState, DurableObjectStub, DurableStorage, SESSION_HEADER, SqlStorage, SqlStorageCursor, SqlStorageValue, durableAgentSurface, durableChannelSurface, durableFetch, sseTurnEvents, sseTurnFinalText };
|
|
144
|
+
//#endregion
|
package/dist/agent-durable.js
CHANGED
|
@@ -2,7 +2,7 @@ import { observeTurnEvents } from "./turn-events.js";
|
|
|
2
2
|
import { isolateLocal } from "./isolate-local.js";
|
|
3
3
|
import { assertCoreRuntimeVersion } from "./core-version.js";
|
|
4
4
|
import { DeliverUnsupportedError, actionToTool, channelDispatch, resolveChannel } from "@junejs/core/agent-config";
|
|
5
|
-
import { AgentSession, ResumeAuthorizationError, withSystem } from "@junejs/core/agent-runtime";
|
|
5
|
+
import { AgentSession, ResumeAuthorizationError, grantAnswer, withSystem } from "@junejs/core/agent-runtime";
|
|
6
6
|
import { connectAll } from "@junejs/core/connections";
|
|
7
7
|
import { ensureScope, runInScope } from "@junejs/db";
|
|
8
8
|
//#region src/agent-durable.ts
|
|
@@ -54,7 +54,7 @@ var DoSessionStore = class {
|
|
|
54
54
|
tx(fn) {
|
|
55
55
|
return this.storage.transactionSync(fn);
|
|
56
56
|
}
|
|
57
|
-
reset() {
|
|
57
|
+
reset(inTx) {
|
|
58
58
|
return this.storage.transactionSync(() => {
|
|
59
59
|
const sql = this.sql;
|
|
60
60
|
sql.exec(`CREATE TABLE IF NOT EXISTS agent_messages_archive (generation INTEGER, seq INTEGER, body TEXT)`);
|
|
@@ -67,6 +67,7 @@ var DoSessionStore = class {
|
|
|
67
67
|
sql.exec("DELETE FROM agent_steps");
|
|
68
68
|
this.setStatus("new");
|
|
69
69
|
sql.exec("INSERT INTO agent_meta (k, v) VALUES ('generation', ?) ON CONFLICT(k) DO UPDATE SET v = ?", String(generation + 1), String(generation + 1));
|
|
70
|
+
inTx?.();
|
|
70
71
|
return generation;
|
|
71
72
|
});
|
|
72
73
|
}
|
|
@@ -107,6 +108,10 @@ var AgentDurableObject = class {
|
|
|
107
108
|
connectionsOpened;
|
|
108
109
|
doEnv;
|
|
109
110
|
services;
|
|
111
|
+
authorizeAnswer;
|
|
112
|
+
onInputAnnouncement;
|
|
113
|
+
storage;
|
|
114
|
+
announceFailures = 0;
|
|
110
115
|
resolveResources() {
|
|
111
116
|
return this.resourcesOpened ??= Promise.resolve(typeof this.resourcesInput === "function" ? this.resourcesInput(this.doEnv) : this.resourcesInput ?? {});
|
|
112
117
|
}
|
|
@@ -136,8 +141,14 @@ var AgentDurableObject = class {
|
|
|
136
141
|
this.connectionsInput = def.connections;
|
|
137
142
|
this.doEnv = def.env;
|
|
138
143
|
this.services = def.services;
|
|
144
|
+
this.authorizeAnswer = def.authorizeAnswer;
|
|
145
|
+
this.onInputAnnouncement = def.onInputAnnouncement;
|
|
146
|
+
this.storage = state.storage;
|
|
139
147
|
const name = def.name ?? "agent";
|
|
140
148
|
const sink = new InProcEventSink();
|
|
149
|
+
sink.subscribe((e) => {
|
|
150
|
+
if (e.type === "turn.started") this.armWatchdog();
|
|
151
|
+
});
|
|
141
152
|
sink.subscribe((e) => {
|
|
142
153
|
if (e.type !== "turn.failed") return;
|
|
143
154
|
const defaultLog = () => console.error(`[june] agent "${name}" turn ${e.turnId} failed${e.step ? ` at ${e.step}` : ""}: ${e.error.stack ?? e.error.message}${e.error.causeChain?.length ? `\ncaused by: ${e.error.causeChain.join(" ← ")}` : ""}`);
|
|
@@ -191,8 +202,71 @@ var AgentDurableObject = class {
|
|
|
191
202
|
if (key !== void 0 && key !== "self" && stored === void 0) this.store.setSessionKey(key);
|
|
192
203
|
this.sessionKey = resolved;
|
|
193
204
|
this.session = new AgentSession(this.name, resolved, this.store, this.sink, this.model, this.tools, crossDoUnsupported, this.channelInstructions);
|
|
205
|
+
this.session.onDequeue = (heldTurnId, held) => {
|
|
206
|
+
if (held.hostContext?.deliver && held.event) this.deliverHeld(this.session, heldTurnId, held.event);
|
|
207
|
+
};
|
|
208
|
+
const announce = this.onInputAnnouncement;
|
|
209
|
+
if (announce) {
|
|
210
|
+
this.session.onAnnounce = async (a) => {
|
|
211
|
+
await ensureScope();
|
|
212
|
+
const resources = await this.ready();
|
|
213
|
+
try {
|
|
214
|
+
await runInScope({
|
|
215
|
+
resources,
|
|
216
|
+
services: this.services
|
|
217
|
+
}, () => announce(a));
|
|
218
|
+
} catch (err) {
|
|
219
|
+
this.scheduleAlarm(Math.min(5e3 * 2 ** this.announceFailures, 3e5));
|
|
220
|
+
this.announceFailures++;
|
|
221
|
+
throw err;
|
|
222
|
+
}
|
|
223
|
+
this.announceFailures = 0;
|
|
224
|
+
};
|
|
225
|
+
this.session.flushAnnouncements();
|
|
226
|
+
}
|
|
194
227
|
return this.session;
|
|
195
228
|
}
|
|
229
|
+
async alarm() {
|
|
230
|
+
if (!this.onInputAnnouncement) return;
|
|
231
|
+
await this.resolveSession().flushAnnouncements();
|
|
232
|
+
}
|
|
233
|
+
armWatchdog() {
|
|
234
|
+
if (this.onInputAnnouncement) this.scheduleAlarm(6e4);
|
|
235
|
+
}
|
|
236
|
+
scheduleAlarm(inMs) {
|
|
237
|
+
const failed = (err) => console.error(`[june] agent "${this.name}": could not schedule the announcement alarm — delivery waits for the next announcement, turn or rebuild:`, err);
|
|
238
|
+
try {
|
|
239
|
+
Promise.resolve(this.storage.setAlarm?.(Date.now() + inMs)).catch(failed);
|
|
240
|
+
} catch (err) {
|
|
241
|
+
failed(err);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
deliverHeld(session, turnId, event) {
|
|
245
|
+
const logRenderFailure = (err) => console.error(`[june] agent "${this.name}": delivered render for held turn ${turnId} failed:`, err);
|
|
246
|
+
try {
|
|
247
|
+
const channel = this.channels.find((c) => c.name === event.source);
|
|
248
|
+
if (!channel?.deliver) {
|
|
249
|
+
logRenderFailure(/* @__PURE__ */ new Error(`no deliver()-capable channel named "${event.source}" is wired into this DO — the held turn runs, but its reply is not rendered`));
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const it = observeTurnEvents(session, turnId)[Symbol.asyncIterator]();
|
|
253
|
+
const events = { [Symbol.asyncIterator]: () => it };
|
|
254
|
+
const target = {
|
|
255
|
+
channelId: event.channelId,
|
|
256
|
+
threadId: event.threadId,
|
|
257
|
+
recipientUserId: event.user?.id,
|
|
258
|
+
recipientTeamId: event.teamId
|
|
259
|
+
};
|
|
260
|
+
this.ready().then((resources) => runInScope({
|
|
261
|
+
resources,
|
|
262
|
+
services: this.services
|
|
263
|
+
}, () => channel.deliver(target, events, { session: this.sessionKey }))).catch(logRenderFailure).finally(() => {
|
|
264
|
+
it.return?.();
|
|
265
|
+
});
|
|
266
|
+
} catch (err) {
|
|
267
|
+
logRenderFailure(err);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
196
270
|
async turn(input) {
|
|
197
271
|
await ensureScope();
|
|
198
272
|
const resources = await this.ready();
|
|
@@ -211,8 +285,14 @@ var AgentDurableObject = class {
|
|
|
211
285
|
services: this.services
|
|
212
286
|
}, () => session.start(input));
|
|
213
287
|
}
|
|
288
|
+
note(input) {
|
|
289
|
+
const { session, ...note } = input;
|
|
290
|
+
return this.resolveSession(session).note(note);
|
|
291
|
+
}
|
|
214
292
|
reset(opts) {
|
|
215
|
-
|
|
293
|
+
const session = this.resolveSession(opts?.session);
|
|
294
|
+
this.armWatchdog();
|
|
295
|
+
return session.reset();
|
|
216
296
|
}
|
|
217
297
|
transcript() {
|
|
218
298
|
if (this.session) return this.session.transcript();
|
|
@@ -223,10 +303,13 @@ var AgentDurableObject = class {
|
|
|
223
303
|
const url = new URL(req.url);
|
|
224
304
|
const key = req.headers.get("x-june-session") ?? void 0;
|
|
225
305
|
if (req.method === "POST" && url.pathname.endsWith("/turn")) {
|
|
226
|
-
const { userText, turnId, event, trigger } = await req.json();
|
|
306
|
+
const { userText, turnId, event, trigger, ifSuspended } = await req.json();
|
|
227
307
|
await ensureScope();
|
|
228
308
|
const replace = url.searchParams.get("replace") === "1";
|
|
229
309
|
const wantsDeliver = url.searchParams.get("deliver") === "1";
|
|
310
|
+
const detached = url.searchParams.get("detach") === "1";
|
|
311
|
+
if (ifSuspended === "queue" && !wantsDeliver && !detached) return Response.json({ error: `ifSuspended "queue" needs deliver=1 or detach=1: a held turn runs later, when no one is streaming it` }, { status: 400 });
|
|
312
|
+
if (ifSuspended === "queue" && replace) return Response.json({ error: `ifSuspended "queue" and replace=1 cannot be combined — replacing would drop held turns that were accepted` }, { status: 400 });
|
|
230
313
|
let deliverChannel;
|
|
231
314
|
if (wantsDeliver) {
|
|
232
315
|
if (!event?.channelId) return Response.json({ error: "deliver=1 needs an inbound event (event.channelId names the reply target)" }, { status: 400 });
|
|
@@ -238,6 +321,7 @@ var AgentDurableObject = class {
|
|
|
238
321
|
let started;
|
|
239
322
|
try {
|
|
240
323
|
session = this.resolveSession(key);
|
|
324
|
+
this.armWatchdog();
|
|
241
325
|
started = runInScope({
|
|
242
326
|
resources,
|
|
243
327
|
services: this.services
|
|
@@ -246,11 +330,17 @@ var AgentDurableObject = class {
|
|
|
246
330
|
turnId,
|
|
247
331
|
event,
|
|
248
332
|
trigger,
|
|
249
|
-
replace
|
|
333
|
+
replace,
|
|
334
|
+
ifSuspended,
|
|
335
|
+
hostContext: wantsDeliver ? { deliver: true } : void 0
|
|
250
336
|
}));
|
|
251
337
|
} catch (err) {
|
|
252
338
|
return Response.json({ error: err instanceof Error ? err.message : String(err) }, { status: 409 });
|
|
253
339
|
}
|
|
340
|
+
if (started.queued) return Response.json({
|
|
341
|
+
turnId: started.turnId,
|
|
342
|
+
queued: true
|
|
343
|
+
}, { status: 202 });
|
|
254
344
|
if (wantsDeliver) {
|
|
255
345
|
const logRenderFailure = (err) => console.error(`[june] agent "${this.name}": delivered render for turn ${started.turnId} failed:`, err);
|
|
256
346
|
try {
|
|
@@ -273,11 +363,11 @@ var AgentDurableObject = class {
|
|
|
273
363
|
}
|
|
274
364
|
return Response.json({ turnId: started.turnId }, { status: 202 });
|
|
275
365
|
}
|
|
276
|
-
if (
|
|
366
|
+
if (detached) return Response.json({ turnId: started.turnId }, { status: 202 });
|
|
277
367
|
return new Response(sseTurnStream(session, started.turnId), { headers: SSE_HEADERS });
|
|
278
368
|
}
|
|
279
369
|
if (req.method === "POST" && url.pathname.endsWith("/resume")) {
|
|
280
|
-
const { turnId, inputId, input, by, source, target } = await req.json();
|
|
370
|
+
const { turnId, inputId, input, by, principal, source, target } = await req.json();
|
|
281
371
|
await ensureScope();
|
|
282
372
|
const wantsDeliver = url.searchParams.get("deliver") === "1";
|
|
283
373
|
let resumeChannel;
|
|
@@ -290,10 +380,33 @@ var AgentDurableObject = class {
|
|
|
290
380
|
let session;
|
|
291
381
|
try {
|
|
292
382
|
session = this.resolveSession(key);
|
|
383
|
+
} catch (err) {
|
|
384
|
+
return Response.json({ error: err instanceof Error ? err.message : String(err) }, { status: 409 });
|
|
385
|
+
}
|
|
386
|
+
let granted;
|
|
387
|
+
try {
|
|
388
|
+
granted = await runInScope({
|
|
389
|
+
resources,
|
|
390
|
+
services: this.services
|
|
391
|
+
}, () => grantAnswer(session, {
|
|
392
|
+
turnId,
|
|
393
|
+
inputId,
|
|
394
|
+
by,
|
|
395
|
+
principal
|
|
396
|
+
}, this.authorizeAnswer));
|
|
397
|
+
} catch (err) {
|
|
398
|
+
console.error(`[june] agent "${this.name}": authorizeAnswer failed for input "${inputId}" of turn ${turnId}:`, err);
|
|
399
|
+
return Response.json({ error: `authorizeAnswer failed: ${err instanceof Error ? err.message : String(err)} — the answer was NOT applied` }, { status: 500 });
|
|
400
|
+
}
|
|
401
|
+
this.armWatchdog();
|
|
402
|
+
try {
|
|
293
403
|
runInScope({
|
|
294
404
|
resources,
|
|
295
405
|
services: this.services
|
|
296
|
-
}, () => session.resume(turnId, inputId, input, {
|
|
406
|
+
}, () => session.resume(turnId, inputId, input, {
|
|
407
|
+
by,
|
|
408
|
+
granted
|
|
409
|
+
}));
|
|
297
410
|
} catch (err) {
|
|
298
411
|
const message = err instanceof Error ? err.message : String(err);
|
|
299
412
|
return Response.json({ error: message }, { status: err instanceof ResumeAuthorizationError ? 403 : 409 });
|
|
@@ -323,12 +436,33 @@ var AgentDurableObject = class {
|
|
|
323
436
|
} catch (err) {
|
|
324
437
|
return Response.json({ error: err instanceof Error ? err.message : String(err) }, { status: 409 });
|
|
325
438
|
}
|
|
439
|
+
this.armWatchdog();
|
|
326
440
|
try {
|
|
327
441
|
return Response.json(await session.reset());
|
|
328
442
|
} catch (err) {
|
|
329
443
|
return Response.json({ error: err instanceof Error ? err.message : String(err) }, { status: 409 });
|
|
330
444
|
}
|
|
331
445
|
}
|
|
446
|
+
if (req.method === "POST" && url.pathname.endsWith("/note")) {
|
|
447
|
+
let input;
|
|
448
|
+
try {
|
|
449
|
+
input = await req.json();
|
|
450
|
+
} catch {
|
|
451
|
+
return Response.json({ error: "note: the body must be JSON { by, kind, text }" }, { status: 400 });
|
|
452
|
+
}
|
|
453
|
+
let session;
|
|
454
|
+
try {
|
|
455
|
+
session = this.resolveSession(key);
|
|
456
|
+
} catch (err) {
|
|
457
|
+
return Response.json({ error: err instanceof Error ? err.message : String(err) }, { status: 409 });
|
|
458
|
+
}
|
|
459
|
+
try {
|
|
460
|
+
return Response.json(await session.note(input));
|
|
461
|
+
} catch (err) {
|
|
462
|
+
if (err instanceof TypeError) return Response.json({ error: err.message }, { status: 400 });
|
|
463
|
+
throw err;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
332
466
|
if (url.pathname.endsWith("/transcript")) {
|
|
333
467
|
if (key !== void 0) try {
|
|
334
468
|
return Response.json({ transcript: this.resolveSession(key).transcript() });
|
|
@@ -337,7 +471,7 @@ var AgentDurableObject = class {
|
|
|
337
471
|
}
|
|
338
472
|
return Response.json({ transcript: this.transcript() });
|
|
339
473
|
}
|
|
340
|
-
return new Response("agent DO — POST /turn, POST /resume, POST /reset, or GET /transcript", { status: 404 });
|
|
474
|
+
return new Response("agent DO — POST /turn, POST /resume, POST /reset, POST /note, or GET /transcript", { status: 404 });
|
|
341
475
|
}
|
|
342
476
|
};
|
|
343
477
|
const SSE_HEADERS = {
|
|
@@ -466,7 +600,8 @@ function resolveServices(factory, env, agentName) {
|
|
|
466
600
|
return perAgent.get(agentName);
|
|
467
601
|
}
|
|
468
602
|
function durableChannelSurface(getNamespace, opts) {
|
|
469
|
-
|
|
603
|
+
const resolved = opts.channels.map((c) => resolveChannel(c, opts.env));
|
|
604
|
+
const ctx = {
|
|
470
605
|
agent: {
|
|
471
606
|
name: opts.agentName,
|
|
472
607
|
instructions: "",
|
|
@@ -552,7 +687,8 @@ function durableChannelSurface(getNamespace, opts) {
|
|
|
552
687
|
}
|
|
553
688
|
return await res.json();
|
|
554
689
|
}
|
|
555
|
-
}
|
|
690
|
+
};
|
|
691
|
+
return channelDispatch(resolved, ctx);
|
|
556
692
|
}
|
|
557
693
|
function serializeResume(o) {
|
|
558
694
|
try {
|
|
@@ -561,11 +697,20 @@ function serializeResume(o) {
|
|
|
561
697
|
inputId: o.inputId,
|
|
562
698
|
input: o.input,
|
|
563
699
|
by: o.by,
|
|
700
|
+
principal: o.principal,
|
|
564
701
|
source: o.source,
|
|
565
702
|
target: o.target
|
|
566
703
|
});
|
|
567
704
|
} catch (err) {
|
|
568
|
-
|
|
705
|
+
const culprit = ["input", "principal"].find((field) => {
|
|
706
|
+
try {
|
|
707
|
+
JSON.stringify(o[field]);
|
|
708
|
+
return false;
|
|
709
|
+
} catch {
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
}) ?? "payload";
|
|
713
|
+
throw new Error(`resume: ${culprit} is not JSON-serializable (${err.message}) — a resume must round-trip to the DO`);
|
|
569
714
|
}
|
|
570
715
|
}
|
|
571
716
|
function serializeTurn(userText, o) {
|
|
@@ -573,7 +718,8 @@ function serializeTurn(userText, o) {
|
|
|
573
718
|
userText,
|
|
574
719
|
turnId: o?.turnId,
|
|
575
720
|
event: o?.event,
|
|
576
|
-
trigger: o?.trigger
|
|
721
|
+
trigger: o?.trigger,
|
|
722
|
+
ifSuspended: o?.ifSuspended
|
|
577
723
|
};
|
|
578
724
|
try {
|
|
579
725
|
return JSON.stringify(payload);
|
package/dist/agent-native.d.ts
CHANGED
|
@@ -1,44 +1,48 @@
|
|
|
1
1
|
import { SyncSqlite } from "./sqlite-driver.js";
|
|
2
2
|
import { AgentDefinition, ChannelContext } from "@junejs/core/agent-config";
|
|
3
|
-
import { AgentSession, ChannelPolicy, Model, Runtime, Tool } from "@junejs/core/agent-runtime";
|
|
3
|
+
import { AgentSession, ChannelPolicy, InputAnnouncement, Model, Runtime, Tool } from "@junejs/core/agent-runtime";
|
|
4
4
|
//#region src/agent-native.d.ts
|
|
5
|
-
type AgentDef = {
|
|
5
|
+
export type AgentDef = {
|
|
6
6
|
model: Model;
|
|
7
7
|
tools: Tool[];
|
|
8
8
|
instructions?: string;
|
|
9
9
|
channelInstructions?: Record<string, string | ChannelPolicy>;
|
|
10
|
+
onInputAnnouncement?: (a: InputAnnouncement) => void | Promise<void>;
|
|
10
11
|
};
|
|
11
|
-
declare function toAgentDef(agent: AgentDefinition, model: Model): AgentDef;
|
|
12
|
-
type NativeRuntimeOptions = {
|
|
12
|
+
export declare function toAgentDef(agent: AgentDefinition, model: Model): AgentDef;
|
|
13
|
+
export type NativeRuntimeOptions = {
|
|
13
14
|
maxSessions?: number;
|
|
14
15
|
};
|
|
15
|
-
declare class NativeRuntime implements Runtime {
|
|
16
|
+
export declare class NativeRuntime implements Runtime {
|
|
16
17
|
private actors;
|
|
17
18
|
private readonly agents;
|
|
18
19
|
private readonly db;
|
|
20
|
+
private readonly announceRetry;
|
|
19
21
|
private readonly maxSessions;
|
|
20
22
|
constructor(agents: Record<string, AgentDef>, db: SyncSqlite, opts?: NativeRuntimeOptions);
|
|
21
23
|
agentDef(name: string): AgentDef | undefined;
|
|
22
24
|
session(agent: string, id: string): AgentSession;
|
|
23
25
|
get sessionCount(): number;
|
|
26
|
+
recoverAnnouncements(): void;
|
|
24
27
|
private evictIdle;
|
|
25
28
|
}
|
|
26
|
-
declare function createNativeRuntime(agents: Record<string, AgentDef>, path?: string, opts?: NativeRuntimeOptions): Promise<NativeRuntime>;
|
|
27
|
-
declare class MemoryRuntime implements Runtime {
|
|
29
|
+
export declare function createNativeRuntime(agents: Record<string, AgentDef>, path?: string, opts?: NativeRuntimeOptions): Promise<NativeRuntime>;
|
|
30
|
+
export declare class MemoryRuntime implements Runtime {
|
|
28
31
|
private actors;
|
|
29
32
|
private stores;
|
|
30
33
|
private readonly agents;
|
|
34
|
+
private readonly announceRetry;
|
|
31
35
|
constructor(agents: Record<string, AgentDef>);
|
|
32
36
|
agentDef(name: string): AgentDef | undefined;
|
|
33
37
|
session(agent: string, id: string): AgentSession;
|
|
34
38
|
}
|
|
35
|
-
type AgentBackend = "native" | "memory" | "durable";
|
|
36
|
-
declare function createAgentRuntime(agents: Record<string, AgentDef>, opts?: {
|
|
39
|
+
export type AgentBackend = "native" | "memory" | "durable";
|
|
40
|
+
export declare function createAgentRuntime(agents: Record<string, AgentDef>, opts?: {
|
|
37
41
|
backend?: AgentBackend;
|
|
38
42
|
path?: string;
|
|
39
43
|
maxSessions?: number;
|
|
40
44
|
}): Promise<Runtime>;
|
|
41
|
-
declare function mountAgent(agent: AgentDefinition, runtime: Runtime, opts?: {
|
|
45
|
+
export declare function mountAgent(agent: AgentDefinition, runtime: Runtime, opts?: {
|
|
42
46
|
chatPath?: string;
|
|
43
47
|
channels?: boolean;
|
|
44
48
|
services?: unknown;
|
|
@@ -48,5 +52,4 @@ declare function mountAgent(agent: AgentDefinition, runtime: Runtime, opts?: {
|
|
|
48
52
|
startAll: () => Promise<void>;
|
|
49
53
|
ctx: ChannelContext;
|
|
50
54
|
};
|
|
51
|
-
//#endregion
|
|
52
|
-
export { AgentBackend, AgentDef, MemoryRuntime, NativeRuntime, NativeRuntimeOptions, createAgentRuntime, createNativeRuntime, mountAgent, toAgentDef };
|
|
55
|
+
//#endregion
|