Skip to content

Commit b7d8d4b

Browse files
Bound Assistant bridge HTTP sessions
1 parent 5c17a5e commit b7d8d4b

2 files changed

Lines changed: 51 additions & 10 deletions

File tree

js/agent_bridge_client.js

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -978,14 +978,42 @@ C8O.assistantAgentBridge = C8O.assistantAgentBridge || {};
978978
return String(sb.toString());
979979
}
980980

981-
function currentHttpSessionCookie() {
981+
var BRIDGE_SESSION_COOKIE_ATTR = "convertigo.assistant.bridge.session.";
982+
983+
function bridgeSessionSlot(params) {
984+
return params && trim(params.__sequence) === "agent_events" ? "events" : "commands";
985+
}
986+
987+
function bridgeSessionCookie(slot) {
982988
try {
983989
var session = context && context.httpSession;
984-
var sessionId = session && session.getId ? trim(session.getId()) : "";
985-
return sessionId.length ? "JSESSIONID=" + sessionId : "";
986-
} catch (_ignoreHttpSession) {
990+
var value = session && session.getAttribute ? session.getAttribute(BRIDGE_SESSION_COOKIE_ATTR + slot) : null;
991+
return value === null || typeof value === "undefined" ? "" : trim(value);
992+
} catch (_ignoreBridgeSession) {
993+
return "";
994+
}
995+
}
996+
997+
function responseSessionCookie(header) {
998+
var value = trim(header);
999+
var match = /(?:^|[,;]\s*)(JSESSIONID=[^;,\s]+)/i.exec(value);
1000+
return match ? match[1] : "";
1001+
}
1002+
1003+
function rememberBridgeSessionCookie(slot, header) {
1004+
var cookie = responseSessionCookie(header);
1005+
if (!cookie.length) {
9871006
return "";
9881007
}
1008+
try {
1009+
var session = context && context.httpSession;
1010+
if (session && session.setAttribute) {
1011+
session.setAttribute(BRIDGE_SESSION_COOKIE_ATTR + slot, cookie);
1012+
}
1013+
} catch (_ignoreBridgeSession) {
1014+
// A request without an outer session keeps the historical stateless behavior.
1015+
}
1016+
return cookie;
9891017
}
9901018

9911019
function postForm(urlText, params, timeoutMs) {
@@ -995,7 +1023,8 @@ C8O.assistantAgentBridge = C8O.assistantAgentBridge || {};
9951023
conn.setReadTimeout(timeoutMs);
9961024
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
9971025
conn.setRequestProperty("Accept", "application/json");
998-
var sessionCookie = currentHttpSessionCookie();
1026+
var sessionSlot = bridgeSessionSlot(params);
1027+
var sessionCookie = bridgeSessionCookie(sessionSlot);
9991028
if (sessionCookie.length) {
10001029
conn.setRequestProperty("Cookie", sessionCookie);
10011030
}
@@ -1008,6 +1037,7 @@ C8O.assistantAgentBridge = C8O.assistantAgentBridge || {};
10081037
out.close();
10091038

10101039
var code = conn.getResponseCode();
1040+
rememberBridgeSessionCookie(sessionSlot, conn.getHeaderField("Set-Cookie"));
10111041
var text = readStream(code >= 400 ? conn.getErrorStream() : conn.getInputStream());
10121042
if (code >= 400) {
10131043
throw new Error("HTTP " + code + " from agent bridge: " + text);

tests/assistant_routing.test.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ global.C8O = {};
2626
let source = fs.readFileSync("js/agent_bridge_client.js", "utf8");
2727
source = source.replace(
2828
/\}\(\)\);\s*$/,
29-
"C8O.assistantAgentBridge._test = { assistantProfileDescriptor, buildSequencePrompt, currentHttpSessionCookie };}());"
29+
"C8O.assistantAgentBridge._test = { assistantProfileDescriptor, buildSequencePrompt, bridgeSessionSlot, bridgeSessionCookie, responseSessionCookie, rememberBridgeSessionCookie };}());"
3030
);
3131
vm.runInThisContext(source, { filename: "agent_bridge_client.js" });
3232

@@ -47,15 +47,26 @@ assert.match(prompt, /managed `convertigo-studio` routing skill/);
4747
assert.match(prompt, /Explicit Flow\/FlowScript\/Flow Svelte intent selects `convertigo-flow`/);
4848
assert.doesNotMatch(prompt, /Authoring policy: legacy-only/);
4949

50+
const sessionAttributes = new Map();
5051
global.context = {
5152
httpSession: {
52-
getId() {
53-
return "studio-session";
53+
getAttribute(name) {
54+
return sessionAttributes.get(name) ?? null;
55+
},
56+
setAttribute(name, value) {
57+
sessionAttributes.set(name, value);
5458
}
5559
}
5660
};
57-
assert.equal(testApi.currentHttpSessionCookie(), "JSESSIONID=studio-session");
61+
assert.equal(testApi.bridgeSessionSlot({ __sequence: "agent_events" }), "events");
62+
assert.equal(testApi.bridgeSessionSlot({ __sequence: "agent_settings" }), "commands");
63+
assert.equal(testApi.bridgeSessionCookie("commands"), "");
64+
assert.equal(testApi.responseSessionCookie("JSESSIONID=bridge-1; Path=/convertigo; HttpOnly"), "JSESSIONID=bridge-1");
65+
assert.equal(testApi.rememberBridgeSessionCookie("commands", "JSESSIONID=bridge-1; Path=/convertigo; HttpOnly"), "JSESSIONID=bridge-1");
66+
assert.equal(testApi.bridgeSessionCookie("commands"), "JSESSIONID=bridge-1");
67+
assert.equal(testApi.bridgeSessionCookie("events"), "");
68+
assert.equal(testApi.rememberBridgeSessionCookie("events", "ignored=value; Path=/"), "");
5869
global.context = {};
59-
assert.equal(testApi.currentHttpSessionCookie(), "");
70+
assert.equal(testApi.bridgeSessionCookie("commands"), "");
6071

6172
console.log("Assistant routing contract OK");

0 commit comments

Comments
 (0)