@junejs/server 0.1.0-dev.4 → 0.1.0-dev.5
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.d.ts +55 -0
- package/dist/adapter.js +204 -0
- package/dist/agent-discover.d.ts +5 -0
- package/dist/agent-discover.js +75 -0
- package/dist/agent-durable.d.ts +60 -0
- package/dist/agent-durable.js +106 -0
- package/dist/agent-native.d.ts +40 -0
- package/dist/agent-native.js +179 -0
- package/dist/app.d.ts +15 -0
- package/dist/app.js +218 -0
- package/dist/blob.d.ts +23 -0
- package/dist/blob.js +78 -0
- package/dist/build.d.ts +40 -0
- package/dist/build.js +551 -0
- package/dist/client-bundle.d.ts +15 -0
- package/dist/client-bundle.js +91 -0
- package/dist/config-loader.d.ts +9 -0
- package/dist/config-loader.js +25 -0
- package/dist/content.d.ts +39 -0
- package/dist/content.js +201 -0
- package/dist/css-modules-ambient.d.ts +10 -0
- package/dist/css-modules.d.ts +24 -0
- package/dist/css-modules.js +127 -0
- package/dist/css.d.ts +14 -0
- package/dist/css.js +114 -0
- package/dist/d1-BkdUg9kg.d.ts +24 -0
- package/dist/d1-migrate.d.ts +31 -0
- package/dist/d1-migrate.js +156 -0
- package/dist/d1.d.ts +2 -0
- package/dist/d1.js +32 -0
- package/dist/db.d.ts +11 -0
- package/dist/db.js +20 -0
- package/dist/deploy.d.ts +25 -0
- package/dist/deploy.js +158 -0
- package/dist/dev-reload.d.ts +5 -0
- package/dist/dev-reload.js +123 -0
- package/dist/dev.d.ts +13 -0
- package/dist/dev.js +55 -0
- package/dist/host.d.ts +25 -0
- package/dist/host.js +107 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +26 -0
- package/dist/instrumentation.d.ts +4 -0
- package/dist/instrumentation.js +15 -0
- package/dist/island-registry.d.ts +8 -0
- package/dist/island-registry.js +117 -0
- package/dist/kv.d.ts +8 -0
- package/dist/kv.js +35 -0
- package/dist/migrate-BbWt-PuB.d.ts +32 -0
- package/dist/migrate.d.ts +2 -0
- package/dist/migrate.js +115 -0
- package/dist/mysql-driver-BsrWVqbp.d.ts +12 -0
- package/dist/mysql-driver.d.ts +2 -0
- package/dist/mysql-driver.js +52 -0
- package/dist/negotiate.d.ts +11 -0
- package/dist/negotiate.js +39 -0
- package/dist/pipeline-B2V6tKfO.d.ts +49 -0
- package/dist/pipeline.d.ts +2 -0
- package/dist/pipeline.js +235 -0
- package/dist/postgres-driver-DkkBFikA.d.ts +15 -0
- package/dist/postgres-driver.d.ts +2 -0
- package/dist/postgres-driver.js +50 -0
- package/dist/resources.d.ts +15 -0
- package/dist/resources.js +31 -0
- package/dist/router.d.ts +32 -0
- package/dist/router.js +183 -0
- package/dist/rsc-build.d.ts +17 -0
- package/dist/rsc-build.js +68 -0
- package/dist/rsc-bundle.d.ts +8 -0
- package/dist/rsc-bundle.js +39 -0
- package/dist/rsc-manifest.d.ts +8 -0
- package/dist/rsc-manifest.js +67 -0
- package/dist/rsc-runtime/flight-render-routes.d.ts +5 -0
- package/dist/rsc-runtime/flight-render-routes.js +26 -0
- package/dist/rsc-runtime/flight-render.d.ts +4 -0
- package/dist/rsc-runtime/flight-render.js +21 -0
- package/dist/rsc-runtime/flight-to-html.d.ts +4 -0
- package/dist/rsc-runtime/flight-to-html.js +32 -0
- package/dist/rsc-runtime/rsc-worker.d.ts +6 -0
- package/dist/rsc-runtime/rsc-worker.js +46 -0
- package/dist/rsc-runtime/rsdw-shims.d.ts +42 -0
- package/dist/segment.d.ts +14 -0
- package/dist/segment.js +33 -0
- package/dist/sqlite-driver.d.ts +25 -0
- package/dist/sqlite-driver.js +102 -0
- package/dist/tsconfig-jsx.d.ts +15 -0
- package/dist/tsconfig-jsx.js +35 -0
- package/dist/turso-driver-C1wEigMZ.d.ts +22 -0
- package/dist/turso-driver.d.ts +2 -0
- package/dist/turso-driver.js +68 -0
- package/dist/worker.d.ts +55 -0
- package/dist/worker.js +209 -0
- package/package.json +115 -23
- package/src/adapter.ts +4 -4
- package/src/client-bundle.ts +3 -1
- package/src/rsc-bundle.ts +3 -2
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { JuneConfig } from "@junejs/core/config";
|
|
2
|
+
//#region src/adapter.d.ts
|
|
3
|
+
type AdapterCapabilities = {
|
|
4
|
+
runtime: "edge" | "node" | "serverless" | "native" | "static";
|
|
5
|
+
persistentConnections: boolean;
|
|
6
|
+
assets: "platform" | "server" | "none";
|
|
7
|
+
};
|
|
8
|
+
type AdapterEntry = {
|
|
9
|
+
imports: string[];
|
|
10
|
+
wrap(pipelineVar: string): string;
|
|
11
|
+
};
|
|
12
|
+
type ResourcePlan = {
|
|
13
|
+
db?: {
|
|
14
|
+
binding: string;
|
|
15
|
+
databaseName: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
type AdapterEmitContext = {
|
|
19
|
+
appRoot: string;
|
|
20
|
+
outDir: string;
|
|
21
|
+
hasAssets: boolean;
|
|
22
|
+
linkHeader: string | null;
|
|
23
|
+
config: JuneConfig;
|
|
24
|
+
plan: ResourcePlan;
|
|
25
|
+
defaultName: string;
|
|
26
|
+
};
|
|
27
|
+
interface JuneAdapter {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly capabilities: AdapterCapabilities;
|
|
30
|
+
readonly conditions: string[];
|
|
31
|
+
readonly buildExternal?: string[];
|
|
32
|
+
validate?(ctx: {
|
|
33
|
+
plan: ResourcePlan;
|
|
34
|
+
config: JuneConfig;
|
|
35
|
+
}): void;
|
|
36
|
+
entry(opts: {
|
|
37
|
+
linkHeader: string | null;
|
|
38
|
+
}): AdapterEntry;
|
|
39
|
+
emit(ctx: AdapterEmitContext): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
declare function workers(opts?: {
|
|
42
|
+
name?: string;
|
|
43
|
+
domain?: string;
|
|
44
|
+
}): JuneAdapter;
|
|
45
|
+
declare function vercel(opts?: {
|
|
46
|
+
runtime?: "node" | "edge";
|
|
47
|
+
regions?: string[];
|
|
48
|
+
}): JuneAdapter;
|
|
49
|
+
declare function deno(opts?: {
|
|
50
|
+
org?: string;
|
|
51
|
+
app?: string;
|
|
52
|
+
}): JuneAdapter;
|
|
53
|
+
declare function staticSite(): JuneAdapter;
|
|
54
|
+
//#endregion
|
|
55
|
+
export { AdapterCapabilities, AdapterEmitContext, AdapterEntry, JuneAdapter, ResourcePlan, deno, staticSite, vercel, workers };
|
package/dist/adapter.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { copyFile, cp, mkdir, readdir, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
//#region src/adapter.ts
|
|
5
|
+
function workers(opts) {
|
|
6
|
+
return {
|
|
7
|
+
name: "workers",
|
|
8
|
+
capabilities: {
|
|
9
|
+
runtime: "edge",
|
|
10
|
+
persistentConnections: true,
|
|
11
|
+
assets: "platform"
|
|
12
|
+
},
|
|
13
|
+
conditions: [
|
|
14
|
+
"source",
|
|
15
|
+
"workerd",
|
|
16
|
+
"edge",
|
|
17
|
+
"import",
|
|
18
|
+
"default"
|
|
19
|
+
],
|
|
20
|
+
buildExternal: ["workers-og"],
|
|
21
|
+
entry({ linkHeader }) {
|
|
22
|
+
return {
|
|
23
|
+
imports: [`import { withAssets } from "@junejs/server/worker";`],
|
|
24
|
+
wrap: (pipelineVar) => `export default withAssets(${pipelineVar}, { link: ${JSON.stringify(linkHeader)} });`
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
async emit({ appRoot, outDir, hasAssets, config, plan, defaultName }) {
|
|
28
|
+
if (existsSync(join(appRoot, "wrangler.toml")) || existsSync(join(appRoot, "wrangler.jsonc"))) return;
|
|
29
|
+
const deployCfg = config.deploy;
|
|
30
|
+
await writeFile(join(outDir, "wrangler.jsonc"), JSON.stringify({
|
|
31
|
+
name: opts?.name ?? deployCfg?.name ?? defaultName,
|
|
32
|
+
main: "./worker.js",
|
|
33
|
+
compatibility_date: "2025-01-01",
|
|
34
|
+
compatibility_flags: ["nodejs_compat"],
|
|
35
|
+
...hasAssets ? { assets: {
|
|
36
|
+
directory: "./assets",
|
|
37
|
+
binding: "ASSETS",
|
|
38
|
+
run_worker_first: true
|
|
39
|
+
} } : {},
|
|
40
|
+
...plan.db ? { d1_databases: [{
|
|
41
|
+
binding: plan.db.binding,
|
|
42
|
+
database_name: plan.db.databaseName,
|
|
43
|
+
database_id: ""
|
|
44
|
+
}] } : {},
|
|
45
|
+
...opts?.domain ?? deployCfg?.domain ? { routes: [{
|
|
46
|
+
pattern: opts?.domain ?? deployCfg?.domain,
|
|
47
|
+
custom_domain: true
|
|
48
|
+
}] } : {}
|
|
49
|
+
}, null, 2) + "\n");
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const VERCEL_FUNCTION = "__june";
|
|
54
|
+
function vercel(opts) {
|
|
55
|
+
const isEdge = (opts?.runtime ?? "node") === "edge";
|
|
56
|
+
return {
|
|
57
|
+
name: "vercel",
|
|
58
|
+
capabilities: {
|
|
59
|
+
runtime: isEdge ? "edge" : "node",
|
|
60
|
+
persistentConnections: !isEdge,
|
|
61
|
+
assets: "platform"
|
|
62
|
+
},
|
|
63
|
+
conditions: [
|
|
64
|
+
"source",
|
|
65
|
+
"edge-light",
|
|
66
|
+
"edge",
|
|
67
|
+
"import",
|
|
68
|
+
"default"
|
|
69
|
+
],
|
|
70
|
+
validate({ config }) {
|
|
71
|
+
const kind = config.resources?.db?.kind;
|
|
72
|
+
if (kind && kind !== "turso") throw new Error(`vercel(): the '${kind}' db isn't supported on Vercel (D1 is Cloudflare-only).\n Use turso() (libsql over HTTPS) for a Vercel db, or deploy to Workers.`);
|
|
73
|
+
},
|
|
74
|
+
entry() {
|
|
75
|
+
const env = `const __env = typeof process !== "undefined" && process.env ? process.env : {};\n`;
|
|
76
|
+
return {
|
|
77
|
+
imports: [],
|
|
78
|
+
wrap: (pipelineVar) => isEdge ? env + `export default (request) => ${pipelineVar}.fetch(request, __env);` : env + `export default { fetch: (request) => ${pipelineVar}.fetch(request, __env) };`
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
async emit({ appRoot, outDir, hasAssets }) {
|
|
82
|
+
const out = join(appRoot, ".vercel", "output");
|
|
83
|
+
const fnDir = join(out, "functions", `${VERCEL_FUNCTION}.func`);
|
|
84
|
+
await rm(out, {
|
|
85
|
+
recursive: true,
|
|
86
|
+
force: true
|
|
87
|
+
});
|
|
88
|
+
await mkdir(fnDir, { recursive: true });
|
|
89
|
+
const jsFiles = (await readdir(outDir)).filter((f) => f.endsWith(".js"));
|
|
90
|
+
for (const f of jsFiles) await copyFile(join(outDir, f), join(fnDir, f));
|
|
91
|
+
const regions = opts?.regions ? { regions: opts.regions } : {};
|
|
92
|
+
const vcConfig = isEdge ? {
|
|
93
|
+
runtime: "edge",
|
|
94
|
+
entrypoint: "worker.js",
|
|
95
|
+
...regions
|
|
96
|
+
} : {
|
|
97
|
+
runtime: "nodejs22.x",
|
|
98
|
+
handler: "worker.js",
|
|
99
|
+
launcherType: "Nodejs",
|
|
100
|
+
supportsResponseStreaming: true,
|
|
101
|
+
...regions
|
|
102
|
+
};
|
|
103
|
+
await writeFile(join(fnDir, ".vc-config.json"), JSON.stringify(vcConfig, null, 2) + "\n");
|
|
104
|
+
if (!isEdge) await writeFile(join(fnDir, "package.json"), JSON.stringify({ type: "module" }, null, 2) + "\n");
|
|
105
|
+
if (hasAssets) {
|
|
106
|
+
const src = join(outDir, "assets", "_june");
|
|
107
|
+
if (existsSync(src)) await cp(src, join(out, "static", "_june"), { recursive: true });
|
|
108
|
+
}
|
|
109
|
+
await writeFile(join(out, "config.json"), JSON.stringify({
|
|
110
|
+
version: 3,
|
|
111
|
+
routes: [
|
|
112
|
+
{
|
|
113
|
+
src: "^/_june/(.*)$",
|
|
114
|
+
headers: { "cache-control": "public, max-age=31536000, immutable" },
|
|
115
|
+
continue: true
|
|
116
|
+
},
|
|
117
|
+
{ handle: "filesystem" },
|
|
118
|
+
{
|
|
119
|
+
src: "^/.*$",
|
|
120
|
+
dest: `/${VERCEL_FUNCTION}`
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
}, null, 2) + "\n");
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function deno(opts) {
|
|
128
|
+
return {
|
|
129
|
+
name: "deno",
|
|
130
|
+
capabilities: {
|
|
131
|
+
runtime: "edge",
|
|
132
|
+
persistentConnections: true,
|
|
133
|
+
assets: "server"
|
|
134
|
+
},
|
|
135
|
+
conditions: [
|
|
136
|
+
"source",
|
|
137
|
+
"deno",
|
|
138
|
+
"edge-light",
|
|
139
|
+
"edge",
|
|
140
|
+
"import",
|
|
141
|
+
"default"
|
|
142
|
+
],
|
|
143
|
+
validate({ config }) {
|
|
144
|
+
const kind = config.resources?.db?.kind;
|
|
145
|
+
if (kind && kind !== "turso") throw new Error(`deno(): the '${kind}' db isn't supported on Deno Deploy (D1 is Cloudflare-only).\n Use turso() (libsql over HTTPS) for a Deno db, or deploy to Workers.`);
|
|
146
|
+
},
|
|
147
|
+
entry() {
|
|
148
|
+
return {
|
|
149
|
+
imports: [`import { withDenoAssets } from "@junejs/server/worker";`],
|
|
150
|
+
wrap: (pipelineVar) => `export default { fetch: withDenoAssets(${pipelineVar}) };`
|
|
151
|
+
};
|
|
152
|
+
},
|
|
153
|
+
async emit({ outDir }) {
|
|
154
|
+
await writeFile(join(outDir, "deno.json"), JSON.stringify({ deploy: {
|
|
155
|
+
...opts?.org ? { org: opts.org } : {},
|
|
156
|
+
...opts?.app ? { app: opts.app } : {},
|
|
157
|
+
runtime: {
|
|
158
|
+
type: "dynamic",
|
|
159
|
+
entrypoint: "worker.js"
|
|
160
|
+
}
|
|
161
|
+
} }, null, 2) + "\n");
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function staticSite() {
|
|
166
|
+
return {
|
|
167
|
+
name: "static",
|
|
168
|
+
capabilities: {
|
|
169
|
+
runtime: "static",
|
|
170
|
+
persistentConnections: false,
|
|
171
|
+
assets: "none"
|
|
172
|
+
},
|
|
173
|
+
conditions: [
|
|
174
|
+
"source",
|
|
175
|
+
"edge-light",
|
|
176
|
+
"edge",
|
|
177
|
+
"import",
|
|
178
|
+
"default"
|
|
179
|
+
],
|
|
180
|
+
buildExternal: ["workers-og"],
|
|
181
|
+
validate({ config }) {
|
|
182
|
+
const kind = config.resources?.db?.kind;
|
|
183
|
+
if (kind) throw new Error(`static(): a '${kind}' db needs a server — a static site has no runtime.\n Drop the db resource, or deploy to workers()/vercel()/deno().`);
|
|
184
|
+
},
|
|
185
|
+
entry() {
|
|
186
|
+
return {
|
|
187
|
+
imports: [],
|
|
188
|
+
wrap: (pipelineVar) => `export default { fetch: (request) => ${pipelineVar}.fetch(request) };`
|
|
189
|
+
};
|
|
190
|
+
},
|
|
191
|
+
async emit({ outDir }) {
|
|
192
|
+
const src = join(outDir, "assets");
|
|
193
|
+
const site = join(outDir, "static");
|
|
194
|
+
await rm(site, {
|
|
195
|
+
recursive: true,
|
|
196
|
+
force: true
|
|
197
|
+
});
|
|
198
|
+
await cp(src, site, { recursive: true });
|
|
199
|
+
await writeFile(join(site, ".nojekyll"), "");
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
//#endregion
|
|
204
|
+
export { deno, staticSite, vercel, workers };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
3
|
+
import { basename, extname, join } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { defineAgent } from "@junejs/core/agent-config";
|
|
6
|
+
import { connectAll } from "@junejs/core/connections";
|
|
7
|
+
//#region src/agent-discover.ts
|
|
8
|
+
async function scan(dir, ext) {
|
|
9
|
+
if (!existsSync(dir)) return [];
|
|
10
|
+
return (await readdir(dir, { withFileTypes: true })).filter((e) => e.isFile() && extname(e.name) === ext).map((e) => join(dir, e.name)).sort();
|
|
11
|
+
}
|
|
12
|
+
function parseSkill(name, text) {
|
|
13
|
+
if (text.startsWith("---")) {
|
|
14
|
+
const end = text.indexOf("\n---", 3);
|
|
15
|
+
if (end !== -1) {
|
|
16
|
+
const front = text.slice(3, end);
|
|
17
|
+
const body = text.slice(end + 4).replace(/^\s*\n/, "");
|
|
18
|
+
const meta = {};
|
|
19
|
+
for (const line of front.split("\n")) {
|
|
20
|
+
const m = line.match(/^\s*(\w+)\s*:\s*(.+?)\s*$/);
|
|
21
|
+
if (m) meta[m[1]] = m[2];
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
name: meta.name ?? name,
|
|
25
|
+
description: meta.description ?? "",
|
|
26
|
+
body
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
name,
|
|
32
|
+
description: (text.split("\n").find((l) => l.trim()) ?? "").replace(/^#\s*/, ""),
|
|
33
|
+
body: text
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
async function discoverAgent(dir) {
|
|
37
|
+
const configFile = join(dir, "agent.ts");
|
|
38
|
+
const config = existsSync(configFile) ? (await import(pathToFileURL(configFile).href)).default : { name: basename(dir) };
|
|
39
|
+
const instructionsFile = join(dir, "instructions.md");
|
|
40
|
+
const instructions = existsSync(instructionsFile) ? await readFile(instructionsFile, "utf8") : config.instructions ?? "";
|
|
41
|
+
const tools = [];
|
|
42
|
+
for (const f of await scan(join(dir, "tools"), ".ts")) {
|
|
43
|
+
const mod = await import(pathToFileURL(f).href);
|
|
44
|
+
if (mod.default) tools.push(mod.default);
|
|
45
|
+
}
|
|
46
|
+
const skills = [];
|
|
47
|
+
for (const f of await scan(join(dir, "skills"), ".md")) skills.push(parseSkill(basename(f, ".md"), await readFile(f, "utf8")));
|
|
48
|
+
const channels = [];
|
|
49
|
+
for (const f of await scan(join(dir, "channels"), ".ts")) {
|
|
50
|
+
const mod = await import(pathToFileURL(f).href);
|
|
51
|
+
if (mod.default) channels.push(mod.default);
|
|
52
|
+
}
|
|
53
|
+
const connectionDefs = [];
|
|
54
|
+
for (const f of await scan(join(dir, "connections"), ".ts")) {
|
|
55
|
+
const mod = await import(pathToFileURL(f).href);
|
|
56
|
+
if (mod.default) connectionDefs.push(mod.default);
|
|
57
|
+
}
|
|
58
|
+
const { actions: connectionActions, report: connections } = connectionDefs.length ? await connectAll(connectionDefs) : {
|
|
59
|
+
actions: [],
|
|
60
|
+
report: []
|
|
61
|
+
};
|
|
62
|
+
tools.push(...connectionActions);
|
|
63
|
+
return defineAgent({
|
|
64
|
+
name: config.name,
|
|
65
|
+
model: config.model,
|
|
66
|
+
description: config.description,
|
|
67
|
+
instructions,
|
|
68
|
+
tools,
|
|
69
|
+
skills,
|
|
70
|
+
channels,
|
|
71
|
+
connections
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { discoverAgent };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Model, Msg, SessionStore, Tool } from "@junejs/core/agent-runtime";
|
|
2
|
+
//#region src/agent-durable.d.ts
|
|
3
|
+
interface SqlStorageCursor<T = Record<string, unknown>> {
|
|
4
|
+
toArray(): T[];
|
|
5
|
+
one(): T;
|
|
6
|
+
}
|
|
7
|
+
interface SqlStorage {
|
|
8
|
+
exec<T = Record<string, unknown>>(query: string, ...bindings: unknown[]): SqlStorageCursor<T>;
|
|
9
|
+
}
|
|
10
|
+
interface DurableStorage {
|
|
11
|
+
sql: SqlStorage;
|
|
12
|
+
transactionSync<T>(fn: () => T): T;
|
|
13
|
+
}
|
|
14
|
+
interface DurableObjectState {
|
|
15
|
+
storage: DurableStorage;
|
|
16
|
+
}
|
|
17
|
+
interface DurableObjectStub {
|
|
18
|
+
fetch(request: Request): Promise<Response>;
|
|
19
|
+
}
|
|
20
|
+
interface DurableObjectNamespace {
|
|
21
|
+
idFromName(name: string): unknown;
|
|
22
|
+
get(id: unknown): DurableObjectStub;
|
|
23
|
+
}
|
|
24
|
+
declare class DoSessionStore implements SessionStore {
|
|
25
|
+
private readonly storage;
|
|
26
|
+
constructor(storage: DurableStorage);
|
|
27
|
+
private get sql();
|
|
28
|
+
appendMessage(m: Msg): void;
|
|
29
|
+
messages(): Msg[];
|
|
30
|
+
hasUserTurn(turnId: string): boolean;
|
|
31
|
+
getStep(id: string): unknown | undefined;
|
|
32
|
+
putStep(id: string, output: unknown): void;
|
|
33
|
+
getStatus(): string;
|
|
34
|
+
setStatus(s: string): void;
|
|
35
|
+
tx<T>(fn: () => T): T;
|
|
36
|
+
unwrap<H = unknown>(): H;
|
|
37
|
+
}
|
|
38
|
+
type DoAgentDef = {
|
|
39
|
+
name?: string;
|
|
40
|
+
model: Model;
|
|
41
|
+
tools: Tool[];
|
|
42
|
+
instructions?: string;
|
|
43
|
+
};
|
|
44
|
+
declare class AgentDurableObject {
|
|
45
|
+
private session;
|
|
46
|
+
constructor(state: DurableObjectState, def: DoAgentDef);
|
|
47
|
+
turn(input: {
|
|
48
|
+
turnId?: string;
|
|
49
|
+
userText: string;
|
|
50
|
+
}): Promise<string>;
|
|
51
|
+
transcript(): import("@junejs/core/agent-runtime").Turn[];
|
|
52
|
+
fetch(req: Request): Promise<Response>;
|
|
53
|
+
}
|
|
54
|
+
declare function durableFetch(namespace: DurableObjectNamespace, agent: string, session: string, req: Request): Promise<Response>;
|
|
55
|
+
declare function durableAgentSurface(getNamespace: () => DurableObjectNamespace | undefined, opts: {
|
|
56
|
+
agentName: string;
|
|
57
|
+
chatPath?: string;
|
|
58
|
+
}): (req: Request) => Promise<Response | null>;
|
|
59
|
+
//#endregion
|
|
60
|
+
export { AgentDurableObject, DoAgentDef, DoSessionStore, DurableObjectNamespace, DurableObjectState, DurableObjectStub, DurableStorage, SqlStorage, SqlStorageCursor, durableAgentSurface, durableFetch };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { AgentSession, withSystem } from "@junejs/core/agent-runtime";
|
|
2
|
+
//#region src/agent-durable.ts
|
|
3
|
+
var DoSessionStore = class {
|
|
4
|
+
storage;
|
|
5
|
+
constructor(storage) {
|
|
6
|
+
this.storage = storage;
|
|
7
|
+
const sql = storage.sql;
|
|
8
|
+
sql.exec(`CREATE TABLE IF NOT EXISTS agent_messages (seq INTEGER PRIMARY KEY AUTOINCREMENT, body TEXT)`);
|
|
9
|
+
sql.exec(`CREATE TABLE IF NOT EXISTS agent_steps (id TEXT PRIMARY KEY, output TEXT)`);
|
|
10
|
+
sql.exec(`CREATE TABLE IF NOT EXISTS agent_meta (k TEXT PRIMARY KEY, v TEXT)`);
|
|
11
|
+
}
|
|
12
|
+
get sql() {
|
|
13
|
+
return this.storage.sql;
|
|
14
|
+
}
|
|
15
|
+
appendMessage(m) {
|
|
16
|
+
this.sql.exec("INSERT INTO agent_messages (body) VALUES (?)", JSON.stringify(m));
|
|
17
|
+
}
|
|
18
|
+
messages() {
|
|
19
|
+
return this.sql.exec("SELECT body FROM agent_messages ORDER BY seq").toArray().map((r) => JSON.parse(r.body));
|
|
20
|
+
}
|
|
21
|
+
hasUserTurn(turnId) {
|
|
22
|
+
return this.messages().some((m) => m.role === "user" && m.turnId === turnId);
|
|
23
|
+
}
|
|
24
|
+
getStep(id) {
|
|
25
|
+
const rows = this.sql.exec("SELECT output FROM agent_steps WHERE id = ?", id).toArray();
|
|
26
|
+
return rows.length ? JSON.parse(rows[0].output) : void 0;
|
|
27
|
+
}
|
|
28
|
+
putStep(id, output) {
|
|
29
|
+
this.sql.exec("INSERT INTO agent_steps (id, output) VALUES (?, ?)", id, JSON.stringify(output));
|
|
30
|
+
}
|
|
31
|
+
getStatus() {
|
|
32
|
+
const rows = this.sql.exec("SELECT v FROM agent_meta WHERE k = 'status'").toArray();
|
|
33
|
+
return rows.length ? rows[0].v : "new";
|
|
34
|
+
}
|
|
35
|
+
setStatus(s) {
|
|
36
|
+
this.sql.exec("INSERT INTO agent_meta (k, v) VALUES ('status', ?) ON CONFLICT(k) DO UPDATE SET v = ?", s, s);
|
|
37
|
+
}
|
|
38
|
+
tx(fn) {
|
|
39
|
+
return this.storage.transactionSync(fn);
|
|
40
|
+
}
|
|
41
|
+
unwrap() {
|
|
42
|
+
return this.sql;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
var InProcBroadcaster = class {
|
|
46
|
+
subs = /* @__PURE__ */ new Set();
|
|
47
|
+
publish(turnId) {
|
|
48
|
+
this.subs.forEach((cb) => {
|
|
49
|
+
try {
|
|
50
|
+
cb(turnId);
|
|
51
|
+
} catch {}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
subscribe(cb) {
|
|
55
|
+
this.subs.add(cb);
|
|
56
|
+
return () => this.subs.delete(cb);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const crossDoUnsupported = { session() {
|
|
60
|
+
throw new Error("subagents on the Durable Object target require cross-DO wiring (not yet implemented)");
|
|
61
|
+
} };
|
|
62
|
+
var AgentDurableObject = class {
|
|
63
|
+
session;
|
|
64
|
+
constructor(state, def) {
|
|
65
|
+
const store = new DoSessionStore(state.storage);
|
|
66
|
+
const model = def.instructions ? withSystem(def.model, def.instructions) : def.model;
|
|
67
|
+
this.session = new AgentSession(def.name ?? "agent", "self", store, new InProcBroadcaster(), model, def.tools, crossDoUnsupported);
|
|
68
|
+
}
|
|
69
|
+
turn(input) {
|
|
70
|
+
return this.session.turn(input);
|
|
71
|
+
}
|
|
72
|
+
transcript() {
|
|
73
|
+
return this.session.transcript();
|
|
74
|
+
}
|
|
75
|
+
async fetch(req) {
|
|
76
|
+
const url = new URL(req.url);
|
|
77
|
+
if (req.method === "POST" && url.pathname.endsWith("/turn")) {
|
|
78
|
+
const { userText, turnId } = await req.json();
|
|
79
|
+
return Response.json({ text: await this.turn({
|
|
80
|
+
userText,
|
|
81
|
+
turnId
|
|
82
|
+
}) });
|
|
83
|
+
}
|
|
84
|
+
if (url.pathname.endsWith("/transcript")) return Response.json({ transcript: this.transcript() });
|
|
85
|
+
return new Response("agent DO — POST /turn or GET /transcript", { status: 404 });
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
function durableFetch(namespace, agent, session, req) {
|
|
89
|
+
return namespace.get(namespace.idFromName(`${agent}:${session}`)).fetch(req);
|
|
90
|
+
}
|
|
91
|
+
function durableAgentSurface(getNamespace, opts) {
|
|
92
|
+
const chatPath = opts.chatPath ?? "/message";
|
|
93
|
+
return async (req) => {
|
|
94
|
+
const url = new URL(req.url);
|
|
95
|
+
if (req.method !== "POST" || url.pathname !== chatPath) return null;
|
|
96
|
+
const namespace = getNamespace();
|
|
97
|
+
if (!namespace) return null;
|
|
98
|
+
const { message, session } = await req.json();
|
|
99
|
+
return durableFetch(namespace, opts.agentName, session ?? "default", new Request("https://do/turn", {
|
|
100
|
+
method: "POST",
|
|
101
|
+
body: JSON.stringify({ userText: message })
|
|
102
|
+
}));
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
export { AgentDurableObject, DoSessionStore, durableAgentSurface, durableFetch };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { SyncSqlite } from "./sqlite-driver.js";
|
|
2
|
+
import { AgentDefinition, ChannelContext } from "@junejs/core/agent-config";
|
|
3
|
+
import { AgentSession, Model, Runtime, Tool } from "@junejs/core/agent-runtime";
|
|
4
|
+
//#region src/agent-native.d.ts
|
|
5
|
+
type AgentDef = {
|
|
6
|
+
model: Model;
|
|
7
|
+
tools: Tool[];
|
|
8
|
+
instructions?: string;
|
|
9
|
+
};
|
|
10
|
+
declare class NativeRuntime implements Runtime {
|
|
11
|
+
private actors;
|
|
12
|
+
private readonly agents;
|
|
13
|
+
private readonly db;
|
|
14
|
+
constructor(agents: Record<string, AgentDef>, db: SyncSqlite);
|
|
15
|
+
session(agent: string, id: string): AgentSession;
|
|
16
|
+
}
|
|
17
|
+
declare function createNativeRuntime(agents: Record<string, AgentDef>, path?: string): Promise<NativeRuntime>;
|
|
18
|
+
declare class MemoryRuntime implements Runtime {
|
|
19
|
+
private actors;
|
|
20
|
+
private stores;
|
|
21
|
+
private readonly agents;
|
|
22
|
+
constructor(agents: Record<string, AgentDef>);
|
|
23
|
+
session(agent: string, id: string): AgentSession;
|
|
24
|
+
}
|
|
25
|
+
type AgentBackend = "native" | "memory" | "durable";
|
|
26
|
+
declare function createAgentRuntime(agents: Record<string, AgentDef>, opts?: {
|
|
27
|
+
backend?: AgentBackend;
|
|
28
|
+
path?: string;
|
|
29
|
+
}): Promise<Runtime>;
|
|
30
|
+
declare function mountAgent(agent: AgentDefinition, runtime: Runtime, opts?: {
|
|
31
|
+
chatPath?: string;
|
|
32
|
+
channels?: boolean;
|
|
33
|
+
}): {
|
|
34
|
+
surface: (req: Request) => Promise<Response | null>;
|
|
35
|
+
fetch: (req: Request) => Promise<Response | null>;
|
|
36
|
+
startAll: () => Promise<void>;
|
|
37
|
+
ctx: ChannelContext;
|
|
38
|
+
};
|
|
39
|
+
//#endregion
|
|
40
|
+
export { AgentBackend, AgentDef, MemoryRuntime, NativeRuntime, createAgentRuntime, createNativeRuntime, mountAgent };
|