@kuralle-agents/core 0.3.12 → 0.3.13

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.
@@ -48,6 +48,7 @@ export declare class Runtime {
48
48
  private readonly terminalHandoffTargets;
49
49
  private readonly hooks?;
50
50
  private readonly activeTurnAborts;
51
+ private readonly sessionMutex;
51
52
  constructor(config: HarnessConfig);
52
53
  run(opts: RunOptions): TurnHandle;
53
54
  stream(opts: RunOptions): TurnHandle;
@@ -15,6 +15,7 @@ import { loadRecordedSteps } from './durable/replay.js';
15
15
  import { markSessionOutcome } from './outcomeMarking.js';
16
16
  import { resolveAgentPolicies } from './policies/resolvePolicies.js';
17
17
  import { buildAutoRetrieveProvider, buildKnowledgeProvider, buildMemoryService, runMemoryIngest, } from './grounding/index.js';
18
+ import { SessionMutex } from './SessionMutex.js';
18
19
  export class Runtime {
19
20
  config;
20
21
  agentsById;
@@ -24,6 +25,7 @@ export class Runtime {
24
25
  terminalHandoffTargets;
25
26
  hooks;
26
27
  activeTurnAborts = new Map();
28
+ sessionMutex = new SessionMutex();
27
29
  constructor(config) {
28
30
  this.config = config;
29
31
  this.agentsById = indexAgents(config.agents);
@@ -202,10 +204,19 @@ export class Runtime {
202
204
  }
203
205
  return { text: collectAssistantText(runCtx.runState.messages), toolResults: [] };
204
206
  };
207
+ const gated = async () => {
208
+ const release = await this.sessionMutex.acquire(sessionId);
209
+ try {
210
+ return await execute();
211
+ }
212
+ finally {
213
+ release();
214
+ }
215
+ };
205
216
  return createTurnHandle({
206
217
  bus,
207
218
  abortController,
208
- run: execute,
219
+ run: gated,
209
220
  });
210
221
  }
211
222
  stream(opts) {
@@ -47,8 +47,7 @@ export class SessionMutex {
47
47
  // Set the new tail BEFORE awaiting — so the next concurrent caller
48
48
  // sees this promise in the chain
49
49
  this.locks.set(sessionId, newTail);
50
- // Wait for the previous lock holder to release
51
- await currentTail;
50
+ await currentTail.catch(() => { });
52
51
  return releaseFn;
53
52
  }
54
53
  /** Number of sessions currently locked. For testing/debugging. */
@@ -1,19 +1,27 @@
1
1
  const PENDING_INPUT_KEY = '__v2_pendingUserInput';
2
+ function queue(session) {
3
+ const v = session.workingMemory[PENDING_INPUT_KEY];
4
+ if (Array.isArray(v))
5
+ return v;
6
+ if (typeof v === 'string' && v.length > 0)
7
+ return [v];
8
+ return [];
9
+ }
2
10
  export function setPendingUserInput(session, input) {
3
- session.workingMemory[PENDING_INPUT_KEY] = input;
11
+ session.workingMemory[PENDING_INPUT_KEY] = [...queue(session), input];
4
12
  }
5
13
  export function consumePendingUserInput(session) {
6
- const value = session.workingMemory[PENDING_INPUT_KEY];
7
- delete session.workingMemory[PENDING_INPUT_KEY];
8
- if (typeof value !== 'string' || value.length === 0) {
9
- throw new Error('No buffered user input for awaitUser');
10
- }
11
- return value;
14
+ const q = queue(session);
15
+ const next = q.shift() ?? '';
16
+ if (q.length === 0)
17
+ delete session.workingMemory[PENDING_INPUT_KEY];
18
+ else
19
+ session.workingMemory[PENDING_INPUT_KEY] = q;
20
+ return next;
12
21
  }
13
22
  export function peekPendingUserInput(session) {
14
- const value = session.workingMemory[PENDING_INPUT_KEY];
15
- return typeof value === 'string' ? value : undefined;
23
+ return queue(session)[0];
16
24
  }
17
25
  export function hasPendingUserInput(session) {
18
- return peekPendingUserInput(session) !== undefined;
26
+ return queue(session).length > 0;
19
27
  }
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "url": "git+https://github.com/kuralle/kuralle-agents.git",
7
7
  "directory": "packages/kuralle-core"
8
8
  },
9
- "version": "0.3.12",
9
+ "version": "0.3.13",
10
10
  "description": "A framework for structured conversational AI agents",
11
11
  "publishConfig": {
12
12
  "access": "public"
@@ -97,7 +97,7 @@
97
97
  "dotenv": "^16.4.0",
98
98
  "typescript": "^5.3.0",
99
99
  "zod": "^3.23.0",
100
- "@kuralle-agents/realtime-audio": "0.3.12"
100
+ "@kuralle-agents/realtime-audio": "0.3.13"
101
101
  },
102
102
  "dependencies": {
103
103
  "chrono-node": "^2.6.0",