@robota-sdk/agent-transport-http 3.0.0-beta.100
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/CHANGELOG.md +332 -0
- package/LICENSE +661 -0
- package/README.md +123 -0
- package/dist/node/index.cjs +1 -0
- package/dist/node/index.d.cts +127 -0
- package/dist/node/index.d.cts.map +1 -0
- package/dist/node/index.d.ts +127 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +2 -0
- package/dist/node/index.js.map +1 -0
- package/package.json +78 -0
- package/src/__tests__/admission-loopback-scenario.test.ts +198 -0
- package/src/__tests__/http-base-path.test.ts +33 -0
- package/src/__tests__/http-transport.test.ts +174 -0
- package/src/__tests__/prompt-routes.test.ts +299 -0
- package/src/__tests__/routes-streamsse-throw.test.ts +49 -0
- package/src/__tests__/routes.test.ts +1063 -0
- package/src/__tests__/submit-stream.test.ts +126 -0
- package/src/__tests__/turn-claims.test.ts +102 -0
- package/src/http-session.ts +29 -0
- package/src/http-transport.ts +95 -0
- package/src/index.ts +6 -0
- package/src/open-prompts.ts +56 -0
- package/src/prompt-routes.ts +101 -0
- package/src/routes.ts +190 -0
- package/src/submit-route.ts +196 -0
- package/src/submit-stream.ts +289 -0
- package/src/turn-claims.ts +62 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RUNTIME-38 — who currently holds the one turn a session can run.
|
|
3
|
+
*
|
|
4
|
+
* Split out of `routes.ts`, which had grown past its size ceiling: routing is one job and deciding
|
|
5
|
+
* whether a second turn may start on a session is another, and the second is the only part of that
|
|
6
|
+
* file with state of its own.
|
|
7
|
+
*
|
|
8
|
+
* PER SESSION, not one flag for the router. `sessionFactory` resolves a session per request (the
|
|
9
|
+
* documented multi-tenant shape), so a single flag made one tenant's turn refuse every other
|
|
10
|
+
* tenant's — a busy neighbour is not a reason to refuse you, and that is a worse defect than the
|
|
11
|
+
* race it closed.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { IHttpTransportSession } from './http-session.js';
|
|
15
|
+
|
|
16
|
+
export interface ITurnClaims {
|
|
17
|
+
/** The key this session is claimed under, or `undefined` when it will not name itself. */
|
|
18
|
+
keyFor(session: IHttpTransportSession): string | undefined;
|
|
19
|
+
isHeld(key: string): boolean;
|
|
20
|
+
hold(key: string): void;
|
|
21
|
+
release(key: string): void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A claim registry keyed by the session's declared ID, not by object identity.
|
|
26
|
+
*
|
|
27
|
+
* Keying on the OBJECT makes identity-stability a requirement of every caller that nothing can
|
|
28
|
+
* check: a `sessionFactory` returning a fresh wrapper per call for the same logical session — a
|
|
29
|
+
* proxy, an adapter, a spread copy — defeats the guard in silence, and every request looks
|
|
30
|
+
* unclaimed. `getSession(): { getSessionId(): string }` already names the session, so asking for the
|
|
31
|
+
* id turns an unenforceable requirement into no requirement at all.
|
|
32
|
+
*
|
|
33
|
+
* A claim is released in the caller's `finally`, so this does not grow with the number of sessions
|
|
34
|
+
* the host has ever served — which is what weak keying would otherwise buy.
|
|
35
|
+
*/
|
|
36
|
+
export function createTurnClaims(): ITurnClaims {
|
|
37
|
+
const held = new Set<string>();
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
keyFor(session) {
|
|
41
|
+
try {
|
|
42
|
+
// No `?.`: `getSession(): { getSessionId(): string }` is non-nullable, and optional chaining
|
|
43
|
+
// here would suggest the contract allows an absent session when it does not. A session that
|
|
44
|
+
// breaks the contract anyway is caught below.
|
|
45
|
+
const id = session.getSession().getSessionId();
|
|
46
|
+
return typeof id === 'string' && id !== '' ? id : undefined;
|
|
47
|
+
} catch {
|
|
48
|
+
// allow-fallback: an unnameable session must not be guessed at
|
|
49
|
+
// A session that throws while naming itself has not told us who it is, and guessing would
|
|
50
|
+
// claim the wrong turn. The CALLER refuses on `undefined`, so nothing is swallowed here.
|
|
51
|
+
//
|
|
52
|
+
// `undefined` rather than a placeholder — a shared fallback key would collide every
|
|
53
|
+
// unnameable session into one claim and refuse them all as each other's neighbours. There is
|
|
54
|
+
// no `isExecuting()` fallback on the submit path, and an earlier comment said there was.
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
isHeld: (key) => held.has(key),
|
|
59
|
+
hold: (key) => void held.add(key),
|
|
60
|
+
release: (key) => void held.delete(key),
|
|
61
|
+
};
|
|
62
|
+
}
|