@alexkroman1/aai 0.8.2 → 0.8.4
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/cli/tsconfig.tsbuildinfo +1 -0
- package/dist/cli.js +1368 -1904
- package/dist/sdk/_mock_ws.js +2 -2
- package/dist/sdk/_mock_ws.js.map +1 -1
- package/dist/sdk/_render_check.d.ts.map +1 -1
- package/dist/sdk/_render_check.js +30 -0
- package/dist/sdk/_render_check.js.map +1 -1
- package/dist/sdk/_utils.d.ts +4 -0
- package/dist/sdk/_utils.d.ts.map +1 -0
- package/dist/sdk/_utils.js +7 -0
- package/dist/sdk/_utils.js.map +1 -0
- package/dist/sdk/builtin_tools.d.ts +35 -11
- package/dist/sdk/builtin_tools.d.ts.map +1 -1
- package/dist/sdk/builtin_tools.js +118 -76
- package/dist/sdk/builtin_tools.js.map +1 -1
- package/dist/sdk/capnweb.d.ts +76 -47
- package/dist/sdk/capnweb.d.ts.map +1 -1
- package/dist/sdk/capnweb.js +99 -242
- package/dist/sdk/capnweb.js.map +1 -1
- package/dist/sdk/direct_executor.d.ts.map +1 -1
- package/dist/sdk/direct_executor.js +0 -2
- package/dist/sdk/direct_executor.js.map +1 -1
- package/dist/sdk/host.d.ts +59 -0
- package/dist/sdk/host.d.ts.map +1 -0
- package/dist/sdk/host.js +131 -0
- package/dist/sdk/host.js.map +1 -0
- package/dist/sdk/mod.d.ts +2 -4
- package/dist/sdk/mod.d.ts.map +1 -1
- package/dist/sdk/mod.js +2 -3
- package/dist/sdk/mod.js.map +1 -1
- package/dist/sdk/protocol.d.ts +33 -135
- package/dist/sdk/protocol.d.ts.map +1 -1
- package/dist/sdk/protocol.js +49 -51
- package/dist/sdk/protocol.js.map +1 -1
- package/dist/sdk/runtime.d.ts +0 -1
- package/dist/sdk/runtime.d.ts.map +1 -1
- package/dist/sdk/runtime.js +5 -24
- package/dist/sdk/runtime.js.map +1 -1
- package/dist/sdk/s2s.d.ts +14 -3
- package/dist/sdk/s2s.d.ts.map +1 -1
- package/dist/sdk/s2s.js +72 -113
- package/dist/sdk/s2s.js.map +1 -1
- package/dist/sdk/server.d.ts +1 -1
- package/dist/sdk/server.d.ts.map +1 -1
- package/dist/sdk/server.js +51 -92
- package/dist/sdk/server.js.map +1 -1
- package/dist/sdk/session.d.ts +5 -1
- package/dist/sdk/session.d.ts.map +1 -1
- package/dist/sdk/session.js +131 -137
- package/dist/sdk/session.js.map +1 -1
- package/dist/sdk/tsconfig.tsbuildinfo +1 -0
- package/dist/sdk/types.d.ts +30 -3
- package/dist/sdk/types.d.ts.map +1 -1
- package/dist/sdk/types.js +37 -0
- package/dist/sdk/types.js.map +1 -1
- package/dist/sdk/winterc_server.d.ts.map +1 -1
- package/dist/sdk/winterc_server.js +10 -15
- package/dist/sdk/winterc_server.js.map +1 -1
- package/dist/sdk/worker_entry.d.ts +3 -11
- package/dist/sdk/worker_entry.d.ts.map +1 -1
- package/dist/sdk/worker_entry.js +8 -18
- package/dist/sdk/worker_entry.js.map +1 -1
- package/dist/sdk/worker_shim.d.ts +5 -6
- package/dist/sdk/worker_shim.d.ts.map +1 -1
- package/dist/sdk/worker_shim.js +93 -136
- package/dist/sdk/worker_shim.js.map +1 -1
- package/dist/sdk/ws_handler.d.ts +1 -1
- package/dist/sdk/ws_handler.d.ts.map +1 -1
- package/dist/sdk/ws_handler.js +13 -22
- package/dist/sdk/ws_handler.js.map +1 -1
- package/dist/ui/_cn.d.ts +5 -0
- package/dist/ui/_cn.d.ts.map +1 -0
- package/dist/ui/_cn.js +22 -0
- package/dist/ui/_cn.js.map +1 -0
- package/dist/ui/_components/app.d.ts +3 -1
- package/dist/ui/_components/app.d.ts.map +1 -1
- package/dist/ui/_components/app.js +2 -2
- package/dist/ui/_components/app.js.map +1 -1
- package/dist/ui/_components/button.d.ts +11 -0
- package/dist/ui/_components/button.d.ts.map +1 -0
- package/dist/ui/_components/button.js +17 -0
- package/dist/ui/_components/button.js.map +1 -0
- package/dist/ui/_components/chat_view.d.ts +3 -1
- package/dist/ui/_components/chat_view.d.ts.map +1 -1
- package/dist/ui/_components/chat_view.js +4 -2
- package/dist/ui/_components/chat_view.js.map +1 -1
- package/dist/ui/_components/controls.d.ts +3 -1
- package/dist/ui/_components/controls.d.ts.map +1 -1
- package/dist/ui/_components/controls.js +4 -5
- package/dist/ui/_components/controls.js.map +1 -1
- package/dist/ui/_components/error_banner.d.ts +2 -1
- package/dist/ui/_components/error_banner.d.ts.map +1 -1
- package/dist/ui/_components/error_banner.js +3 -2
- package/dist/ui/_components/error_banner.js.map +1 -1
- package/dist/ui/_components/message_bubble.d.ts +2 -1
- package/dist/ui/_components/message_bubble.d.ts.map +1 -1
- package/dist/ui/_components/message_bubble.js +5 -3
- package/dist/ui/_components/message_bubble.js.map +1 -1
- package/dist/ui/_components/message_list.d.ts +3 -1
- package/dist/ui/_components/message_list.d.ts.map +1 -1
- package/dist/ui/_components/message_list.js +7 -15
- package/dist/ui/_components/message_list.js.map +1 -1
- package/dist/ui/_components/sidebar_layout.d.ts +2 -1
- package/dist/ui/_components/sidebar_layout.d.ts.map +1 -1
- package/dist/ui/_components/sidebar_layout.js +5 -7
- package/dist/ui/_components/sidebar_layout.js.map +1 -1
- package/dist/ui/_components/start_screen.d.ts +2 -1
- package/dist/ui/_components/start_screen.d.ts.map +1 -1
- package/dist/ui/_components/start_screen.js +5 -2
- package/dist/ui/_components/start_screen.js.map +1 -1
- package/dist/ui/_components/state_indicator.d.ts +2 -1
- package/dist/ui/_components/state_indicator.d.ts.map +1 -1
- package/dist/ui/_components/state_indicator.js +3 -2
- package/dist/ui/_components/state_indicator.js.map +1 -1
- package/dist/ui/_components/thinking_indicator.d.ts +3 -1
- package/dist/ui/_components/thinking_indicator.d.ts.map +1 -1
- package/dist/ui/_components/thinking_indicator.js +4 -2
- package/dist/ui/_components/thinking_indicator.js.map +1 -1
- package/dist/ui/_components/tool_call_block.d.ts +2 -1
- package/dist/ui/_components/tool_call_block.d.ts.map +1 -1
- package/dist/ui/_components/tool_call_block.js +13 -25
- package/dist/ui/_components/tool_call_block.js.map +1 -1
- package/dist/ui/_components/transcript.d.ts +2 -1
- package/dist/ui/_components/transcript.d.ts.map +1 -1
- package/dist/ui/_components/transcript.js +3 -2
- package/dist/ui/_components/transcript.js.map +1 -1
- package/dist/ui/_jsdom_setup.d.ts +1 -0
- package/dist/ui/_jsdom_setup.d.ts.map +1 -0
- package/dist/ui/_jsdom_setup.js +6 -0
- package/dist/ui/_jsdom_setup.js.map +1 -0
- package/dist/ui/audio.d.ts.map +1 -1
- package/dist/ui/audio.js +4 -4
- package/dist/ui/audio.js.map +1 -1
- package/dist/ui/components.d.ts +13 -55
- package/dist/ui/components.d.ts.map +1 -1
- package/dist/ui/components.js +13 -42
- package/dist/ui/components.js.map +1 -1
- package/dist/ui/components_mod.d.ts +14 -3
- package/dist/ui/components_mod.d.ts.map +1 -1
- package/dist/ui/components_mod.js +14 -3
- package/dist/ui/components_mod.js.map +1 -1
- package/dist/ui/mod.d.ts +1 -8
- package/dist/ui/mod.d.ts.map +1 -1
- package/dist/ui/mod.js +1 -5
- package/dist/ui/mod.js.map +1 -1
- package/dist/ui/mount.d.ts +1 -1
- package/dist/ui/mount.d.ts.map +1 -1
- package/dist/ui/mount.js +1 -0
- package/dist/ui/mount.js.map +1 -1
- package/dist/ui/session.d.ts +0 -2
- package/dist/ui/session.d.ts.map +1 -1
- package/dist/ui/session.js +9 -6
- package/dist/ui/session.js.map +1 -1
- package/dist/ui/signals.d.ts +8 -3
- package/dist/ui/signals.d.ts.map +1 -1
- package/dist/ui/signals.js +22 -11
- package/dist/ui/signals.js.map +1 -1
- package/dist/ui/tsconfig.tsbuildinfo +1 -0
- package/dist/ui/worklets/playback-processor.js +3 -3
- package/package.json +39 -16
- package/templates/_shared/CLAUDE.md +50 -30
- package/templates/_shared/global.d.ts +1 -0
- package/templates/_shared/package.json +2 -1
- package/templates/dispatch-center/agent.ts +85 -397
- package/templates/solo-rpg/agent.ts +1240 -0
- package/templates/solo-rpg/client.tsx +698 -0
package/dist/sdk/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../sdk/server.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../sdk/server.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EAAE,KAAK,kBAAkB,EAAwB,MAAM,UAAU,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,MAAM,MAAM,aAAa,GAAG;IAC1B,wDAAwD;IACxD,KAAK,EAAE,QAAQ,CAAC;IAChB,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,uCAAuC;IACvC,EAAE,CAAC,EAAE,EAAE,CAAC;IACR,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,4EAA4E;IAC5E,eAAe,CAAC,EAAE,kBAAkB,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,mEAAmE;IACnE,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3C,yCAAyC;IACzC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,uBAAuB;IACvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAyBF;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,WAAW,CA4HhE"}
|
package/dist/sdk/server.js
CHANGED
|
@@ -7,14 +7,18 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
|
+
import { serve } from "@hono/node-server";
|
|
11
|
+
import { serveStatic } from "@hono/node-server/serve-static";
|
|
12
|
+
import { Hono } from "hono";
|
|
10
13
|
import { consoleLogger, DEFAULT_S2S_CONFIG } from "./runtime.js";
|
|
14
|
+
import { wrapOnStyleWebSocket } from "./s2s.js";
|
|
11
15
|
import { createWintercServer } from "./winterc_server.js";
|
|
12
16
|
/** Try to load the `ws` package for WebSocket connections. */
|
|
13
17
|
async function loadWsFactory() {
|
|
14
18
|
try {
|
|
15
19
|
const mod = await import("ws");
|
|
16
20
|
const WS = mod.default ?? mod;
|
|
17
|
-
return (url, opts) => new WS(url, { headers: opts.headers });
|
|
21
|
+
return (url, opts) => wrapOnStyleWebSocket(new WS(url, { headers: opts.headers }));
|
|
18
22
|
}
|
|
19
23
|
catch {
|
|
20
24
|
throw new Error("WebSocket factory not provided and `ws` package not found. " +
|
|
@@ -23,12 +27,7 @@ async function loadWsFactory() {
|
|
|
23
27
|
}
|
|
24
28
|
/** Filter env to only defined string values. */
|
|
25
29
|
function resolveEnv(env) {
|
|
26
|
-
|
|
27
|
-
for (const [key, value] of Object.entries(env)) {
|
|
28
|
-
if (value !== undefined)
|
|
29
|
-
resolved[key] = value;
|
|
30
|
-
}
|
|
31
|
-
return resolved;
|
|
30
|
+
return Object.fromEntries(Object.entries(env).filter(([, v]) => v !== undefined));
|
|
32
31
|
}
|
|
33
32
|
/**
|
|
34
33
|
* Create a self-hostable agent server.
|
|
@@ -78,22 +77,56 @@ export function createServer(options) {
|
|
|
78
77
|
return getWinterc().fetch(request);
|
|
79
78
|
},
|
|
80
79
|
async listen(port = 3000) {
|
|
81
|
-
// Ensure WS factory is loaded before starting
|
|
82
80
|
await getWsFactory();
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
81
|
+
const wintercServer = getWinterc();
|
|
82
|
+
const app = new Hono();
|
|
83
|
+
app.onError((err, c) => {
|
|
84
|
+
logger.error(`${c.req.method} ${new URL(c.req.url).pathname} error: ${err.message}`);
|
|
85
|
+
return c.json({ error: "Internal Server Error" }, 500);
|
|
86
|
+
});
|
|
87
|
+
// Log HTTP requests and errors
|
|
88
|
+
app.use("/*", async (c, next) => {
|
|
89
|
+
const start = Date.now();
|
|
90
|
+
await next();
|
|
91
|
+
const ms = Date.now() - start;
|
|
92
|
+
const status = c.res.status;
|
|
93
|
+
const method = c.req.method;
|
|
94
|
+
const path = new URL(c.req.url).pathname;
|
|
95
|
+
if (status >= 400) {
|
|
96
|
+
logger.error(`${method} ${path} ${status} ${ms}ms`);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
logger.info(`${method} ${path} ${status} ${ms}ms`);
|
|
90
100
|
}
|
|
91
|
-
await nodeHttpHandler(req, res, port, getWinterc);
|
|
92
101
|
});
|
|
93
|
-
|
|
102
|
+
if (clientDir) {
|
|
103
|
+
app.use("/*", serveStatic({ root: clientDir }));
|
|
104
|
+
}
|
|
105
|
+
// Delegate all remaining requests to the winterc server
|
|
106
|
+
app.all("/*", (c) => wintercServer.fetch(c.req.raw));
|
|
107
|
+
const nodeServer = serve({ fetch: app.fetch, port });
|
|
108
|
+
// Wait for server to be ready
|
|
94
109
|
await new Promise((resolve) => {
|
|
95
|
-
nodeServer.
|
|
110
|
+
nodeServer.on("listening", resolve);
|
|
96
111
|
});
|
|
112
|
+
// Attach WebSocket upgrade
|
|
113
|
+
try {
|
|
114
|
+
const wsMod = await import("ws");
|
|
115
|
+
const wss = new wsMod.WebSocketServer({ noServer: true });
|
|
116
|
+
nodeServer.on("upgrade", (req, socket, head) => {
|
|
117
|
+
const reqUrl = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
118
|
+
const resume = reqUrl.searchParams.has("resume");
|
|
119
|
+
logger.info(`WS upgrade ${reqUrl.pathname}${resume ? " (resume)" : ""}`);
|
|
120
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
121
|
+
wintercServer.handleWebSocket(ws, {
|
|
122
|
+
skipGreeting: resume,
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
logger.warn("ws package not available for Node.js WebSocket upgrade");
|
|
129
|
+
}
|
|
97
130
|
serverHandle = {
|
|
98
131
|
async shutdown() {
|
|
99
132
|
await new Promise((resolve, reject) => {
|
|
@@ -108,78 +141,4 @@ export function createServer(options) {
|
|
|
108
141
|
},
|
|
109
142
|
};
|
|
110
143
|
}
|
|
111
|
-
// ─── Static file serving ────────────────────────────────────────────────────
|
|
112
|
-
const MIME_TYPES = {
|
|
113
|
-
".html": "text/html",
|
|
114
|
-
".js": "application/javascript",
|
|
115
|
-
".css": "text/css",
|
|
116
|
-
".json": "application/json",
|
|
117
|
-
".svg": "image/svg+xml",
|
|
118
|
-
".png": "image/png",
|
|
119
|
-
".ico": "image/x-icon",
|
|
120
|
-
".woff": "font/woff",
|
|
121
|
-
".woff2": "font/woff2",
|
|
122
|
-
};
|
|
123
|
-
async function serveStaticFile(reqUrl, clientDir, res) {
|
|
124
|
-
const { readFile } = await import("node:fs/promises");
|
|
125
|
-
const { join, extname, normalize } = await import("node:path");
|
|
126
|
-
const urlPath = new URL(reqUrl, "http://localhost").pathname;
|
|
127
|
-
const relPath = urlPath === "/" ? "index.html" : urlPath.slice(1);
|
|
128
|
-
const filePath = normalize(join(clientDir, relPath));
|
|
129
|
-
// Prevent directory traversal
|
|
130
|
-
if (!filePath.startsWith(clientDir))
|
|
131
|
-
return false;
|
|
132
|
-
try {
|
|
133
|
-
const content = await readFile(filePath);
|
|
134
|
-
const ext = extname(filePath);
|
|
135
|
-
const contentType = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
136
|
-
res.writeHead(200, { "Content-Type": contentType });
|
|
137
|
-
res.end(content);
|
|
138
|
-
return true;
|
|
139
|
-
}
|
|
140
|
-
catch {
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
// ─── Node.js HTTP/WS helpers ─────────────────────────────────────────────────
|
|
145
|
-
async function nodeHttpHandler(req, res, port, getWinterc) {
|
|
146
|
-
try {
|
|
147
|
-
const protocol = req.socket.encrypted ? "https" : "http";
|
|
148
|
-
const host = req.headers.host ?? `localhost:${port}`;
|
|
149
|
-
const url = new URL(req.url ?? "/", `${protocol}://${host}`);
|
|
150
|
-
const headers = new Headers();
|
|
151
|
-
for (const [key, val] of Object.entries(req.headers)) {
|
|
152
|
-
if (val)
|
|
153
|
-
headers.set(key, Array.isArray(val) ? (val[0] ?? "") : val);
|
|
154
|
-
}
|
|
155
|
-
const request = new Request(url, { method: req.method ?? "GET", headers });
|
|
156
|
-
const response = await getWinterc().fetch(request);
|
|
157
|
-
res.writeHead(response.status, Object.fromEntries(response.headers));
|
|
158
|
-
res.end(await response.text());
|
|
159
|
-
}
|
|
160
|
-
catch (err) {
|
|
161
|
-
res.writeHead(500);
|
|
162
|
-
res.end(err instanceof Error ? err.message : "Internal Server Error");
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
function attachWsUpgrade(nodeServer, port, getWinterc, logger) {
|
|
166
|
-
import("ws")
|
|
167
|
-
.then((wsMod) => {
|
|
168
|
-
const WSServer = wsMod.WebSocketServer;
|
|
169
|
-
if (!WSServer)
|
|
170
|
-
return;
|
|
171
|
-
const wss = new WSServer({ noServer: true });
|
|
172
|
-
nodeServer.on("upgrade", (req, socket, head) => {
|
|
173
|
-
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
174
|
-
const reqUrl = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
175
|
-
getWinterc().handleWebSocket(ws, {
|
|
176
|
-
skipGreeting: reqUrl.searchParams.has("resume"),
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
})
|
|
181
|
-
.catch(() => {
|
|
182
|
-
logger.warn("ws package not available for Node.js WebSocket upgrade");
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
144
|
//# sourceMappingURL=server.js.map
|
package/dist/sdk/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../sdk/server.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../sdk/server.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAA2B,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,EAAE,mBAAmB,EAAsB,MAAM,qBAAqB,CAAC;AA+B9E,8DAA8D;AAC9D,KAAK,UAAU,aAAa;IAC1B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC;QAC9B,OAAO,CAAC,GAAW,EAAE,IAAyC,EAAE,EAAE,CAChE,oBAAoB,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,6DAA6D;YAC3D,mEAAmE,CACtE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,gDAAgD;AAChD,SAAS,UAAU,CAAC,GAAuC;IACzD,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAG/E,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,OAAsB;IACjD,MAAM,EACJ,KAAK,EACL,EAAE,EACF,UAAU,EACV,SAAS,EACT,MAAM,GAAG,aAAa,EACtB,SAAS,GAAG,kBAAkB,GAC/B,GAAG,OAAO,CAAC;IAEZ,MAAM,GAAG,GAAG,UAAU,CACpB,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAE,OAAO,CAAC,GAA8B,CAAC,CAAC,CAAC,EAAE,CAAC,CAC/F,CAAC;IAEF,IAAI,SAAS,GAA8B,OAAO,CAAC,eAAe,IAAI,IAAI,CAAC;IAE3E,KAAK,UAAU,YAAY;QACzB,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,SAAS,GAAG,MAAM,aAAa,EAAE,CAAC;QACpC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,8DAA8D;IAC9D,IAAI,OAAO,GAAyB,IAAI,CAAC;IAEzC,SAAS,UAAU;QACjB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,mBAAmB,CAAC;gBAC5B,KAAK;gBACL,GAAG;gBACH,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrB,eAAe,EACb,SAAS;oBACT,CAAC,GAAG,EAAE;wBACJ,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;oBAClD,CAAC,CAAC;gBACJ,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnD,MAAM;gBACN,SAAS;aACV,CAAC,CAAC;QACL,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,YAAY,GAAyC,IAAI,CAAC;IAE9D,OAAO;QACL,KAAK,CAAC,OAAgB;YACpB,OAAO,UAAU,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI;YACtB,MAAM,YAAY,EAAE,CAAC;YACrB,MAAM,aAAa,GAAG,UAAU,EAAE,CAAC;YAEnC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;YAEvB,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;gBACrB,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,WAAW,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBACrF,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,EAAE,GAAG,CAAC,CAAC;YACzD,CAAC,CAAC,CAAC;YAEH,+BAA+B;YAC/B,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;gBAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACzB,MAAM,IAAI,EAAE,CAAC;gBACb,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;gBAC9B,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;gBAC5B,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;gBAC5B,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;gBACzC,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;oBAClB,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,IAAI,IAAI,MAAM,IAAI,EAAE,IAAI,CAAC,CAAC;gBACtD,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,IAAI,IAAI,MAAM,IAAI,EAAE,IAAI,CAAC,CAAC;gBACrD,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,IAAI,SAAS,EAAE,CAAC;gBACd,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;YAClD,CAAC;YAED,wDAAwD;YACxD,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAErD,MAAM,UAAU,GAAG,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAErD,8BAA8B;YAC9B,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBAClC,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACtC,CAAC,CAAC,CAAC;YAEH,2BAA2B;YAC3B,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;gBACjC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,eAAe,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC1D,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;oBAC7C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,oBAAoB,IAAI,EAAE,CAAC,CAAC;oBACnE,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;oBACjD,MAAM,CAAC,IAAI,CAAC,cAAc,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACzE,GAAG,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;wBAC1C,aAAa,CAAC,eAAe,CAAC,EAAiC,EAAE;4BAC/D,YAAY,EAAE,MAAM;yBACrB,CAAC,CAAC;oBACL,CAAC,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;YACxE,CAAC;YAED,YAAY,GAAG;gBACb,KAAK,CAAC,QAAQ;oBACZ,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;wBAC1C,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;oBAC7D,CAAC,CAAC,CAAC;gBACL,CAAC;aACF,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,KAAK;YACT,MAAM,OAAO,EAAE,KAAK,EAAE,CAAC;YACvB,MAAM,YAAY,EAAE,QAAQ,EAAE,CAAC;QACjC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/sdk/session.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type { AgentConfig, ToolSchema } from "./_internal_types.ts";
|
|
|
11
11
|
import type { ClientSink } from "./protocol.ts";
|
|
12
12
|
import type { Logger, Metrics, S2SConfig } from "./runtime.ts";
|
|
13
13
|
import { type CreateS2sWebSocket, connectS2s } from "./s2s.ts";
|
|
14
|
-
import type
|
|
14
|
+
import { type StepInfo } from "./types.ts";
|
|
15
15
|
import type { ExecuteTool } from "./worker_entry.ts";
|
|
16
16
|
/** A voice session managing the S2S connection for one client. */
|
|
17
17
|
export type Session = {
|
|
@@ -63,4 +63,8 @@ export declare const _internals: {
|
|
|
63
63
|
};
|
|
64
64
|
/** Create an S2S-backed session with the same interface as the STT+LLM+TTS session. */
|
|
65
65
|
export declare function createS2sSession(opts: SessionOptions): Session;
|
|
66
|
+
export declare function buildSystemPrompt(config: AgentConfig, opts: {
|
|
67
|
+
hasTools: boolean;
|
|
68
|
+
voice?: boolean;
|
|
69
|
+
}): string;
|
|
66
70
|
//# sourceMappingURL=session.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../sdk/session.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../sdk/session.ts"],"names":[],"mappings":"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"}
|
package/dist/sdk/session.js
CHANGED
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
|
+
import { errorMessage } from "./_utils.js";
|
|
11
12
|
import { HOOK_TIMEOUT_MS } from "./protocol.js";
|
|
12
13
|
import { consoleLogger, noopMetrics } from "./runtime.js";
|
|
13
14
|
import { connectS2s, } from "./s2s.js";
|
|
14
|
-
import {
|
|
15
|
+
import { DEFAULT_INSTRUCTIONS } from "./types.js";
|
|
15
16
|
export const _internals = {
|
|
16
17
|
connectS2s,
|
|
17
18
|
};
|
|
@@ -35,7 +36,6 @@ export function createS2sSession(opts) {
|
|
|
35
36
|
}));
|
|
36
37
|
let s2s = null;
|
|
37
38
|
const sessionAbort = new AbortController();
|
|
38
|
-
let audioReady = false;
|
|
39
39
|
let toolCallCount = 0;
|
|
40
40
|
let turnPromise = null;
|
|
41
41
|
let conversationMessages = [];
|
|
@@ -50,37 +50,24 @@ export function createS2sSession(opts) {
|
|
|
50
50
|
try {
|
|
51
51
|
return await hookInvoker.resolveTurnConfig(id, HOOK_TIMEOUT_MS);
|
|
52
52
|
}
|
|
53
|
-
catch {
|
|
53
|
+
catch (err) {
|
|
54
|
+
log.warn("resolveTurnConfig hook failed", { err: errorMessage(err) });
|
|
54
55
|
return null;
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
function invokeHook(hook, arg) {
|
|
58
59
|
if (!hookInvoker)
|
|
59
60
|
return;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
case "onDisconnect":
|
|
66
|
-
await hookInvoker.onDisconnect(id, HOOK_TIMEOUT_MS);
|
|
67
|
-
break;
|
|
68
|
-
case "onTurn":
|
|
69
|
-
await hookInvoker.onTurn(id, arg, HOOK_TIMEOUT_MS);
|
|
70
|
-
break;
|
|
71
|
-
case "onError":
|
|
72
|
-
await hookInvoker.onError(id, arg, HOOK_TIMEOUT_MS);
|
|
73
|
-
break;
|
|
74
|
-
case "onStep":
|
|
75
|
-
await hookInvoker.onStep(id, arg, HOOK_TIMEOUT_MS);
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
run().catch((err) => {
|
|
80
|
-
log.warn(`${hook} hook failed`, {
|
|
81
|
-
err: err instanceof Error ? err.message : String(err),
|
|
61
|
+
try {
|
|
62
|
+
// biome-ignore lint/complexity/noBannedTypes: dynamic hook dispatch
|
|
63
|
+
const h = hookInvoker[hook];
|
|
64
|
+
Promise.resolve(h.call(hookInvoker, id, arg, HOOK_TIMEOUT_MS)).catch((err) => {
|
|
65
|
+
log.warn(`${hook} hook failed`, { err: errorMessage(err) });
|
|
82
66
|
});
|
|
83
|
-
}
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
log.warn(`${hook} hook failed`, { err: errorMessage(err) });
|
|
70
|
+
}
|
|
84
71
|
}
|
|
85
72
|
/** Check if a tool call should be refused due to turn config limits. Returns a result string to short-circuit, or null. */
|
|
86
73
|
function checkTurnLimits(turnConfig, name) {
|
|
@@ -126,7 +113,7 @@ export function createS2sSession(opts) {
|
|
|
126
113
|
result = await executeTool(name, parsedArgs, id, conversationMessages);
|
|
127
114
|
}
|
|
128
115
|
catch (err) {
|
|
129
|
-
const msg =
|
|
116
|
+
const msg = errorMessage(err);
|
|
130
117
|
log.error("Tool execution failed", { tool: name, error: msg });
|
|
131
118
|
result = JSON.stringify({ error: msg });
|
|
132
119
|
}
|
|
@@ -143,6 +130,84 @@ export function createS2sSession(opts) {
|
|
|
143
130
|
function on(target, event, handler) {
|
|
144
131
|
target.addEventListener(event, handler);
|
|
145
132
|
}
|
|
133
|
+
/** Wire all S2S events to the client sink, hooks, and session state. */
|
|
134
|
+
function setupListeners(handle) {
|
|
135
|
+
on(handle, "ready", (e) => {
|
|
136
|
+
s2sSessionId = e.detail.session_id;
|
|
137
|
+
log.info("S2S session ready", { session_id: s2sSessionId });
|
|
138
|
+
});
|
|
139
|
+
on(handle, "session_expired", () => {
|
|
140
|
+
log.info("S2S session expired, reconnecting fresh");
|
|
141
|
+
s2sSessionId = null;
|
|
142
|
+
handle.close();
|
|
143
|
+
});
|
|
144
|
+
// Simple event forwarding
|
|
145
|
+
for (const type of ["speech_started", "speech_stopped"]) {
|
|
146
|
+
handle.addEventListener(type, () => client.event({ type }));
|
|
147
|
+
}
|
|
148
|
+
on(handle, "user_transcript_delta", (e) => {
|
|
149
|
+
client.event({ type: "transcript", text: e.detail.text, isFinal: false });
|
|
150
|
+
});
|
|
151
|
+
on(handle, "user_transcript", (e) => {
|
|
152
|
+
const { text } = e.detail;
|
|
153
|
+
log.info("S2S user transcript", { text });
|
|
154
|
+
client.event({ type: "transcript", text, isFinal: true });
|
|
155
|
+
client.event({ type: "turn", text });
|
|
156
|
+
conversationMessages.push({ role: "user", content: text });
|
|
157
|
+
invokeHook("onTurn", text);
|
|
158
|
+
});
|
|
159
|
+
handle.addEventListener("reply_started", () => {
|
|
160
|
+
toolCallCount = 0;
|
|
161
|
+
});
|
|
162
|
+
on(handle, "audio", (e) => {
|
|
163
|
+
client.playAudioChunk(e.detail.audio);
|
|
164
|
+
});
|
|
165
|
+
on(handle, "agent_transcript_delta", (e) => {
|
|
166
|
+
client.event({ type: "chat_delta", text: e.detail.text });
|
|
167
|
+
});
|
|
168
|
+
on(handle, "agent_transcript", (e) => {
|
|
169
|
+
const { text } = e.detail;
|
|
170
|
+
client.event({ type: "chat", text });
|
|
171
|
+
conversationMessages.push({ role: "assistant", content: text });
|
|
172
|
+
});
|
|
173
|
+
on(handle, "tool_call", (e) => {
|
|
174
|
+
const p = handleToolCall(e.detail).catch((err) => {
|
|
175
|
+
log.error("Tool call handler failed", { err: errorMessage(err) });
|
|
176
|
+
});
|
|
177
|
+
turnPromise = (turnPromise ?? Promise.resolve()).then(() => p);
|
|
178
|
+
});
|
|
179
|
+
on(handle, "reply_done", (e) => {
|
|
180
|
+
if (e.detail.status === "interrupted") {
|
|
181
|
+
log.info("S2S reply interrupted (barge-in)");
|
|
182
|
+
pendingTools = [];
|
|
183
|
+
client.event({ type: "cancelled" });
|
|
184
|
+
}
|
|
185
|
+
else if (pendingTools.length > 0) {
|
|
186
|
+
for (const tool of pendingTools)
|
|
187
|
+
s2s?.sendToolResult(tool.call_id, tool.result);
|
|
188
|
+
pendingTools = [];
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
client.playAudioDone();
|
|
192
|
+
client.event({ type: "tts_done" });
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
on(handle, "error", (e) => {
|
|
196
|
+
log.error("S2S error", { code: e.detail.code, message: e.detail.message });
|
|
197
|
+
client.event({ type: "error", code: "internal", message: e.detail.message });
|
|
198
|
+
handle.close();
|
|
199
|
+
});
|
|
200
|
+
handle.addEventListener("close", () => {
|
|
201
|
+
log.info("S2S closed");
|
|
202
|
+
s2s = null;
|
|
203
|
+
if (!sessionAbort.signal.aborted) {
|
|
204
|
+
log.info("Attempting S2S reconnect");
|
|
205
|
+
connectAndSetup().catch((err) => {
|
|
206
|
+
log.error("S2S reconnect failed", { error: errorMessage(err) });
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
146
211
|
async function connectAndSetup() {
|
|
147
212
|
if (connecting) {
|
|
148
213
|
pendingReconnect = true;
|
|
@@ -156,113 +221,13 @@ export function createS2sSession(opts) {
|
|
|
156
221
|
createWebSocket,
|
|
157
222
|
logger: log,
|
|
158
223
|
});
|
|
159
|
-
// Register all
|
|
160
|
-
|
|
161
|
-
on(handle, "ready", (e) => {
|
|
162
|
-
s2sSessionId = e.detail.session_id;
|
|
163
|
-
log.info("S2S session ready", { session_id: s2sSessionId });
|
|
164
|
-
});
|
|
165
|
-
on(handle, "session_expired", () => {
|
|
166
|
-
log.info("S2S session expired, reconnecting fresh");
|
|
167
|
-
s2sSessionId = null;
|
|
168
|
-
handle.close();
|
|
169
|
-
});
|
|
170
|
-
handle.addEventListener("speech_started", () => {
|
|
171
|
-
client.event({ type: "speech_started" });
|
|
172
|
-
});
|
|
173
|
-
handle.addEventListener("speech_stopped", () => {
|
|
174
|
-
client.event({ type: "speech_stopped" });
|
|
175
|
-
});
|
|
176
|
-
on(handle, "user_transcript_delta", (e) => {
|
|
177
|
-
client.event({
|
|
178
|
-
type: "transcript",
|
|
179
|
-
text: e.detail.text,
|
|
180
|
-
isFinal: false,
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
on(handle, "user_transcript", (e) => {
|
|
184
|
-
const { text } = e.detail;
|
|
185
|
-
log.info("S2S user transcript", { text });
|
|
186
|
-
client.event({ type: "transcript", text, isFinal: true });
|
|
187
|
-
client.event({ type: "turn", text });
|
|
188
|
-
conversationMessages.push({ role: "user", content: text });
|
|
189
|
-
invokeHook("onTurn", text);
|
|
190
|
-
});
|
|
191
|
-
handle.addEventListener("reply_started", () => {
|
|
192
|
-
toolCallCount = 0;
|
|
193
|
-
});
|
|
194
|
-
on(handle, "audio", (e) => {
|
|
195
|
-
client.playAudioChunk(e.detail.audio);
|
|
196
|
-
});
|
|
197
|
-
on(handle, "agent_transcript_delta", (e) => {
|
|
198
|
-
client.event({ type: "chat_delta", text: e.detail.text });
|
|
199
|
-
});
|
|
200
|
-
on(handle, "agent_transcript", (e) => {
|
|
201
|
-
const { text } = e.detail;
|
|
202
|
-
client.event({ type: "chat", text });
|
|
203
|
-
conversationMessages.push({ role: "assistant", content: text });
|
|
204
|
-
});
|
|
205
|
-
on(handle, "tool_call", (e) => {
|
|
206
|
-
const p = handleToolCall(e.detail).catch((err) => {
|
|
207
|
-
log.error("Tool call handler failed", {
|
|
208
|
-
err: err instanceof Error ? err.message : String(err),
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
turnPromise = (turnPromise ?? Promise.resolve()).then(() => p);
|
|
212
|
-
});
|
|
213
|
-
on(handle, "reply_done", (e) => {
|
|
214
|
-
if (e.detail.status === "interrupted") {
|
|
215
|
-
log.info("S2S reply interrupted (barge-in)");
|
|
216
|
-
// Discard pending tool results on interruption.
|
|
217
|
-
pendingTools = [];
|
|
218
|
-
client.event({ type: "cancelled" });
|
|
219
|
-
}
|
|
220
|
-
else if (pendingTools.length > 0) {
|
|
221
|
-
// Send all accumulated tool results after reply.done.
|
|
222
|
-
for (const tool of pendingTools) {
|
|
223
|
-
s2s?.sendToolResult(tool.call_id, tool.result);
|
|
224
|
-
}
|
|
225
|
-
pendingTools = [];
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
client.playAudioDone();
|
|
229
|
-
client.event({ type: "tts_done" });
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
on(handle, "error", (e) => {
|
|
233
|
-
log.error("S2S error", {
|
|
234
|
-
code: e.detail.code,
|
|
235
|
-
message: e.detail.message,
|
|
236
|
-
});
|
|
237
|
-
client.event({
|
|
238
|
-
type: "error",
|
|
239
|
-
code: "internal",
|
|
240
|
-
message: e.detail.message,
|
|
241
|
-
});
|
|
242
|
-
// Close the S2S connection on error to prevent repeated error floods.
|
|
243
|
-
handle.close();
|
|
244
|
-
});
|
|
245
|
-
handle.addEventListener("close", () => {
|
|
246
|
-
log.info("S2S closed");
|
|
247
|
-
s2s = null;
|
|
248
|
-
if (!sessionAbort.signal.aborted) {
|
|
249
|
-
log.info("Attempting S2S reconnect");
|
|
250
|
-
connectAndSetup().catch((err) => {
|
|
251
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
252
|
-
log.error("S2S reconnect failed", { error: msg });
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
});
|
|
256
|
-
// Now that all listeners are registered, send the initial message.
|
|
224
|
+
// Register all listeners BEFORE sending messages to avoid races.
|
|
225
|
+
setupListeners(handle);
|
|
257
226
|
if (s2sSessionId) {
|
|
258
|
-
|
|
259
|
-
log.info("Attempting S2S session resume", {
|
|
260
|
-
session_id: s2sSessionId,
|
|
261
|
-
});
|
|
227
|
+
log.info("Attempting S2S session resume", { session_id: s2sSessionId });
|
|
262
228
|
handle.resumeSession(s2sSessionId);
|
|
263
229
|
}
|
|
264
230
|
else {
|
|
265
|
-
// Initial connect: send config with greeting.
|
|
266
231
|
handle.updateSession({
|
|
267
232
|
system_prompt: systemPrompt,
|
|
268
233
|
tools: s2sTools,
|
|
@@ -272,7 +237,7 @@ export function createS2sSession(opts) {
|
|
|
272
237
|
s2s = handle;
|
|
273
238
|
}
|
|
274
239
|
catch (err) {
|
|
275
|
-
const msg =
|
|
240
|
+
const msg = errorMessage(err);
|
|
276
241
|
log.error("S2S connect failed", { error: msg });
|
|
277
242
|
client.event({ type: "error", code: "internal", message: msg });
|
|
278
243
|
}
|
|
@@ -281,8 +246,7 @@ export function createS2sSession(opts) {
|
|
|
281
246
|
if (pendingReconnect && !sessionAbort.signal.aborted) {
|
|
282
247
|
pendingReconnect = false;
|
|
283
248
|
connectAndSetup().catch((err) => {
|
|
284
|
-
|
|
285
|
-
log.error("S2S deferred reconnect failed", { error: msg });
|
|
249
|
+
log.error("S2S deferred reconnect failed", { error: errorMessage(err) });
|
|
286
250
|
});
|
|
287
251
|
}
|
|
288
252
|
}
|
|
@@ -308,10 +272,7 @@ export function createS2sSession(opts) {
|
|
|
308
272
|
s2s?.sendAudio(data);
|
|
309
273
|
},
|
|
310
274
|
onAudioReady() {
|
|
311
|
-
|
|
312
|
-
return;
|
|
313
|
-
audioReady = true;
|
|
314
|
-
// Greeting audio + transcript come from S2S automatically.
|
|
275
|
+
// S2S mode: greeting audio comes from S2S automatically. No-op.
|
|
315
276
|
},
|
|
316
277
|
onCancel() {
|
|
317
278
|
// S2S handles barge-in natively.
|
|
@@ -337,4 +298,37 @@ export function createS2sSession(opts) {
|
|
|
337
298
|
},
|
|
338
299
|
};
|
|
339
300
|
}
|
|
301
|
+
// ─── System prompt builder ──────────────────────────────────────────────────
|
|
302
|
+
const VOICE_RULES = "\n\nCRITICAL OUTPUT RULES — you MUST follow these for EVERY response:\n" +
|
|
303
|
+
"Your response will be spoken aloud by a TTS system and displayed as plain text.\n" +
|
|
304
|
+
"- NEVER use markdown: no **, no *, no _, no #, no `, no [](), no ---\n" +
|
|
305
|
+
"- NEVER use bullet points (-, *, •) or numbered lists (1., 2.)\n" +
|
|
306
|
+
"- NEVER use code blocks or inline code\n" +
|
|
307
|
+
"- NEVER mention tools, search, APIs, or technical failures to the user. " +
|
|
308
|
+
"If a tool returns no results, just answer naturally without explaining why.\n" +
|
|
309
|
+
"- Write exactly as you would say it out loud to a friend\n" +
|
|
310
|
+
'- Use short conversational sentences. To list things, say "First," "Next," "Finally,"\n' +
|
|
311
|
+
"- Keep responses concise — 1 to 3 sentences max";
|
|
312
|
+
export function buildSystemPrompt(config, opts) {
|
|
313
|
+
const { hasTools } = opts;
|
|
314
|
+
const agentInstructions = config.instructions && config.instructions !== DEFAULT_INSTRUCTIONS
|
|
315
|
+
? `\n\nAgent-Specific Instructions:\n${config.instructions}`
|
|
316
|
+
: "";
|
|
317
|
+
const toolPreamble = hasTools
|
|
318
|
+
? "\n\nWhen you decide to use a tool, ALWAYS say a brief natural phrase BEFORE the tool call " +
|
|
319
|
+
'(e.g. "Let me look that up" or "One moment while I check"). ' +
|
|
320
|
+
"This fills silence while the tool executes. Keep preambles to one short sentence."
|
|
321
|
+
: "";
|
|
322
|
+
const today = new Date().toLocaleDateString("en-US", {
|
|
323
|
+
weekday: "long",
|
|
324
|
+
year: "numeric",
|
|
325
|
+
month: "long",
|
|
326
|
+
day: "numeric",
|
|
327
|
+
});
|
|
328
|
+
return (DEFAULT_INSTRUCTIONS +
|
|
329
|
+
`\n\nToday's date is ${today}.` +
|
|
330
|
+
agentInstructions +
|
|
331
|
+
toolPreamble +
|
|
332
|
+
(opts.voice ? VOICE_RULES : ""));
|
|
333
|
+
}
|
|
340
334
|
//# sourceMappingURL=session.js.map
|