blun-king-cli 9.1.471 → 9.1.472
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.
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const AGENT_TURNS_PATH = '/v1/agent/turns';
|
|
2
|
+
const AGENT_SESSIONS_PATH = '/v1/agent/sessions';
|
|
2
3
|
const PUBLIC_MODEL_ID = 'king';
|
|
3
4
|
const PUBLIC_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/u;
|
|
4
5
|
|
|
@@ -70,9 +71,26 @@ function decodeRequestId(value) {
|
|
|
70
71
|
return requirePublicId(decoded, 'request ID');
|
|
71
72
|
}
|
|
72
73
|
|
|
74
|
+
function decodeSessionId(value) {
|
|
75
|
+
let decoded;
|
|
76
|
+
try {
|
|
77
|
+
decoded = decodeURIComponent(value);
|
|
78
|
+
} catch {
|
|
79
|
+
throw adapterError('AGENT_API_INVALID_ID', 'session ID is not valid URL encoding');
|
|
80
|
+
}
|
|
81
|
+
return requirePublicId(decoded, 'session ID');
|
|
82
|
+
}
|
|
83
|
+
|
|
73
84
|
function routeFor(method, rawPath) {
|
|
74
85
|
const path = String(rawPath ?? '').split('?', 1)[0];
|
|
75
86
|
if (method === 'POST' && path === AGENT_TURNS_PATH) return { kind: 'start' };
|
|
87
|
+
if (path.startsWith(`${AGENT_SESSIONS_PATH}/`)) {
|
|
88
|
+
const tail = path.slice(AGENT_SESSIONS_PATH.length + 1);
|
|
89
|
+
if (method === 'DELETE' && !tail.includes('/')) {
|
|
90
|
+
return { kind: 'closeSession', sessionId: decodeSessionId(tail) };
|
|
91
|
+
}
|
|
92
|
+
return { kind: 'unknown' };
|
|
93
|
+
}
|
|
76
94
|
if (!path.startsWith(`${AGENT_TURNS_PATH}/`)) {
|
|
77
95
|
if (path.startsWith('/v1/agent/')) return { kind: 'unknown' };
|
|
78
96
|
return null;
|
|
@@ -207,8 +225,19 @@ function createAgentApiHttpAdapter(options = {}) {
|
|
|
207
225
|
if (typeof options.resolveSession !== 'function') {
|
|
208
226
|
throw new TypeError('resolveSession must be a function');
|
|
209
227
|
}
|
|
228
|
+
if (typeof options.closeSession !== 'function') {
|
|
229
|
+
throw new TypeError('closeSession must be a function');
|
|
230
|
+
}
|
|
210
231
|
const owners = new Map();
|
|
211
232
|
|
|
233
|
+
function hasActiveOwner(principalId, sessionId) {
|
|
234
|
+
const prefix = `${sessionId}\0`;
|
|
235
|
+
for (const [key, scopeOwners] of owners) {
|
|
236
|
+
if (key.startsWith(prefix) && scopeOwners.has(principalId)) return true;
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
|
|
212
241
|
function requireOwner(principalId, sessionId, requestId) {
|
|
213
242
|
const key = scopeKey(sessionId, requestId);
|
|
214
243
|
const scopeOwners = owners.get(key);
|
|
@@ -313,6 +342,31 @@ function createAgentApiHttpAdapter(options = {}) {
|
|
|
313
342
|
});
|
|
314
343
|
}
|
|
315
344
|
|
|
345
|
+
async function handleCloseSession(principalId, sessionId) {
|
|
346
|
+
if (hasActiveOwner(principalId, sessionId)) {
|
|
347
|
+
throw adapterError(
|
|
348
|
+
'AGENT_API_SESSION_BUSY',
|
|
349
|
+
'Agent session has an active turn.',
|
|
350
|
+
409,
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
const closed = await options.closeSession({ principalId, sessionId });
|
|
354
|
+
if (closed !== true) {
|
|
355
|
+
throw adapterError(
|
|
356
|
+
'AGENT_API_SESSION_NOT_FOUND',
|
|
357
|
+
'Agent session was not found.',
|
|
358
|
+
404,
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
return jsonResponse(200, {
|
|
362
|
+
id: `agent-session-${sessionId}`,
|
|
363
|
+
object: 'agent.session.closed',
|
|
364
|
+
model: PUBLIC_MODEL_ID,
|
|
365
|
+
session_id: sessionId,
|
|
366
|
+
closed: true,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
|
|
316
370
|
async function handleRequest(input) {
|
|
317
371
|
if (input === null || typeof input !== 'object') return null;
|
|
318
372
|
const method = String(input.method ?? '').toUpperCase();
|
|
@@ -331,6 +385,9 @@ function createAgentApiHttpAdapter(options = {}) {
|
|
|
331
385
|
}
|
|
332
386
|
const principalId = requireTrustedId(input.principalId, 'principalId');
|
|
333
387
|
if (route.kind === 'start') return await handleStart(input, principalId);
|
|
388
|
+
if (route.kind === 'closeSession') {
|
|
389
|
+
return await handleCloseSession(principalId, route.sessionId);
|
|
390
|
+
}
|
|
334
391
|
if (route.kind === 'continue') {
|
|
335
392
|
return await handleContinue(input, principalId, route.requestId);
|
|
336
393
|
}
|
|
@@ -344,6 +401,7 @@ function createAgentApiHttpAdapter(options = {}) {
|
|
|
344
401
|
}
|
|
345
402
|
|
|
346
403
|
export {
|
|
404
|
+
AGENT_SESSIONS_PATH,
|
|
347
405
|
AGENT_TURNS_PATH,
|
|
348
406
|
AgentApiHttpAdapterError,
|
|
349
407
|
PUBLIC_MODEL_ID,
|
|
@@ -125,6 +125,7 @@ function createAgentApiServiceHost(options = {}) {
|
|
|
125
125
|
const adapter = createAgentApiHttpAdapter({
|
|
126
126
|
controller,
|
|
127
127
|
resolveSession: sessionRegistry.resolveSession,
|
|
128
|
+
closeSession: sessionRegistry.closeSession,
|
|
128
129
|
});
|
|
129
130
|
const privateServer = createAgentApiPrivateHttpServer({
|
|
130
131
|
adapter,
|