blun-king-cli 9.1.471 → 9.1.473
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);
|
|
@@ -242,6 +271,12 @@ function createAgentApiHttpAdapter(options = {}) {
|
|
|
242
271
|
if (scopeOwners?.size === 0) owners.delete(key);
|
|
243
272
|
}
|
|
244
273
|
|
|
274
|
+
function trackRunningScope(key, principalId, internalSessionId) {
|
|
275
|
+
const scopeOwners = owners.get(key) ?? new Map();
|
|
276
|
+
scopeOwners.set(principalId, internalSessionId);
|
|
277
|
+
owners.set(key, scopeOwners);
|
|
278
|
+
}
|
|
279
|
+
|
|
245
280
|
async function handleStart(input, principalId) {
|
|
246
281
|
const body = requireBody(input.body);
|
|
247
282
|
requireKing(body.model);
|
|
@@ -266,20 +301,24 @@ function createAgentApiHttpAdapter(options = {}) {
|
|
|
266
301
|
);
|
|
267
302
|
}
|
|
268
303
|
const internalSessionId = session.id.trim();
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
304
|
+
const prompt = normalizePrompt(body.input);
|
|
305
|
+
const tools = normalizeTools(body.tools);
|
|
306
|
+
const key = scopeKey(sessionId, requestId);
|
|
307
|
+
trackRunningScope(key, principalId, internalSessionId);
|
|
308
|
+
try {
|
|
309
|
+
const response = publicCompletion(await controller.startTurn({
|
|
310
|
+
session,
|
|
311
|
+
publicSessionId: sessionId,
|
|
312
|
+
requestId,
|
|
313
|
+
prompt,
|
|
314
|
+
tools,
|
|
315
|
+
}));
|
|
316
|
+
trackScope(key, principalId, internalSessionId, response);
|
|
317
|
+
return jsonResponse(200, response);
|
|
318
|
+
} catch (error) {
|
|
319
|
+
trackScope(key, principalId, internalSessionId, null);
|
|
320
|
+
throw error;
|
|
321
|
+
}
|
|
283
322
|
}
|
|
284
323
|
|
|
285
324
|
async function handleContinue(input, principalId, requestId) {
|
|
@@ -313,6 +352,31 @@ function createAgentApiHttpAdapter(options = {}) {
|
|
|
313
352
|
});
|
|
314
353
|
}
|
|
315
354
|
|
|
355
|
+
async function handleCloseSession(principalId, sessionId) {
|
|
356
|
+
if (hasActiveOwner(principalId, sessionId)) {
|
|
357
|
+
throw adapterError(
|
|
358
|
+
'AGENT_API_SESSION_BUSY',
|
|
359
|
+
'Agent session has an active turn.',
|
|
360
|
+
409,
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
const closed = await options.closeSession({ principalId, sessionId });
|
|
364
|
+
if (closed !== true) {
|
|
365
|
+
throw adapterError(
|
|
366
|
+
'AGENT_API_SESSION_NOT_FOUND',
|
|
367
|
+
'Agent session was not found.',
|
|
368
|
+
404,
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
return jsonResponse(200, {
|
|
372
|
+
id: `agent-session-${sessionId}`,
|
|
373
|
+
object: 'agent.session.closed',
|
|
374
|
+
model: PUBLIC_MODEL_ID,
|
|
375
|
+
session_id: sessionId,
|
|
376
|
+
closed: true,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
316
380
|
async function handleRequest(input) {
|
|
317
381
|
if (input === null || typeof input !== 'object') return null;
|
|
318
382
|
const method = String(input.method ?? '').toUpperCase();
|
|
@@ -331,6 +395,9 @@ function createAgentApiHttpAdapter(options = {}) {
|
|
|
331
395
|
}
|
|
332
396
|
const principalId = requireTrustedId(input.principalId, 'principalId');
|
|
333
397
|
if (route.kind === 'start') return await handleStart(input, principalId);
|
|
398
|
+
if (route.kind === 'closeSession') {
|
|
399
|
+
return await handleCloseSession(principalId, route.sessionId);
|
|
400
|
+
}
|
|
334
401
|
if (route.kind === 'continue') {
|
|
335
402
|
return await handleContinue(input, principalId, route.requestId);
|
|
336
403
|
}
|
|
@@ -344,6 +411,7 @@ function createAgentApiHttpAdapter(options = {}) {
|
|
|
344
411
|
}
|
|
345
412
|
|
|
346
413
|
export {
|
|
414
|
+
AGENT_SESSIONS_PATH,
|
|
347
415
|
AGENT_TURNS_PATH,
|
|
348
416
|
AgentApiHttpAdapterError,
|
|
349
417
|
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,
|