Skip to content

Commit 2c158ec

Browse files
committed
busy-fn
1 parent ed9bc73 commit 2c158ec

9 files changed

Lines changed: 187 additions & 6 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "agent-swarm-kit",
3-
"version": "1.1.106",
3+
"version": "1.1.107",
44
"description": "A TypeScript library for building orchestrated framework-agnostic multi-agent AI systems",
55
"author": {
66
"name": "Petr Tripolsky",

src/client/ClientSwarm.ts

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import { IToolRequest } from "../model/Tool.model";
1616
const AGENT_NEED_FETCH = Symbol("agent-need-fetch");
1717
const STACK_NEED_FETCH = Symbol("stack-need-fetch");
1818

19+
const SET_BUSY_FN = Symbol("set-busy-fn");
20+
1921
/**
2022
* A no-operation (noop) agent that serves as a fallback when an agent is not found in the swarm.
2123
* Implements the {@link IAgent} interface and logs calls to its methods, indicating that the requested agent is unavailable,
@@ -219,6 +221,8 @@ const WAIT_FOR_OUTPUT_FN = async (self: ClientSwarm): Promise<string> => {
219221
`ClientSwarm swarmName=${self.params.swarmName} clientId=${self.params.clientId} waitForOutput`
220222
);
221223

224+
self[SET_BUSY_FN](true);
225+
222226
const [awaiter, { resolve }] = createAwaiter<{
223227
agentName: AgentName;
224228
output: string;
@@ -275,6 +279,8 @@ const WAIT_FOR_OUTPUT_FN = async (self: ClientSwarm): Promise<string> => {
275279
clientId: self.params.clientId,
276280
});
277281

282+
self[SET_BUSY_FN](false);
283+
278284
return output;
279285
};
280286

@@ -287,6 +293,37 @@ const WAIT_FOR_OUTPUT_FN = async (self: ClientSwarm): Promise<string> => {
287293
* @implements {ISwarm}
288294
*/
289295
export class ClientSwarm implements ISwarm {
296+
private _isBusy = false;
297+
298+
/**
299+
* Returns the current busy state of the swarm.
300+
* Used to check if the swarm is currently processing an operation (e.g., waiting for output or switching agents).
301+
* Supports debugging and flow control in client applications.
302+
* @returns {Promise<boolean>} True if the swarm is busy, false otherwise.
303+
*/
304+
public getCheckBusy() {
305+
GLOBAL_CONFIG.CC_LOGGER_ENABLE_DEBUG &&
306+
this.params.logger.debug(
307+
`ClientSwarm swarmName=${this.params.swarmName} clientId=${this.params.clientId} getCheckBusy`
308+
);
309+
return Promise.resolve(this._isBusy);
310+
}
311+
312+
/**
313+
* Sets the busy state of the swarm.
314+
* Used internally to indicate when the swarm is processing an operation, such as waiting for output.
315+
* Enables coordinated state management and debugging.
316+
* @param {boolean} isBusy - True to mark the swarm as busy, false to mark it as idle.
317+
*/
318+
public [SET_BUSY_FN](isBusy: boolean) {
319+
GLOBAL_CONFIG.CC_LOGGER_ENABLE_DEBUG &&
320+
this.params.logger.debug(
321+
`ClientSwarm swarmName=${this.params.swarmName} clientId=${this.params.clientId} setCheckBusy`,
322+
{ isBusy }
323+
);
324+
this._isBusy = isBusy;
325+
}
326+
290327
/**
291328
* Subject that emits when an agent reference changes, providing the agent name and instance.
292329
* Used by setAgentRef to notify subscribers (e.g., waitForOutput) of updates to agent instances.
@@ -424,8 +461,8 @@ export class ClientSwarm implements ISwarm {
424461
agentName: await this.getAgentName(),
425462
output: "",
426463
});
427-
await Promise.all(this._agentList
428-
.map(async ([, agent]) => {
464+
await Promise.all(
465+
this._agentList.map(async ([, agent]) => {
429466
await agent.commitCancelOutput();
430467
})
431468
);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import beginContext from "../../utils/beginContext";
2+
import { GLOBAL_CONFIG } from "../../config/params";
3+
import swarm from "../../lib";
4+
5+
const METHOD_NAME = "function.common.getCheckBusy";
6+
7+
/**
8+
* Function implementation
9+
*/
10+
const getCheckBusyInternal = beginContext(async (clientId: string) => {
11+
GLOBAL_CONFIG.CC_LOGGER_ENABLE_LOG &&
12+
swarm.loggerService.log(METHOD_NAME, {
13+
clientId,
14+
});
15+
16+
swarm.sessionValidationService.validate(clientId, METHOD_NAME);
17+
const swarmName = swarm.sessionValidationService.getSwarm(clientId);
18+
swarm.swarmValidationService.validate(swarmName, METHOD_NAME);
19+
20+
return await swarm.swarmPublicService.getCheckBusy(
21+
METHOD_NAME,
22+
clientId,
23+
swarmName
24+
);
25+
});
26+
27+
/**
28+
* Checks if the swarm associated with the given client ID is currently busy.
29+
*
30+
* @param {string} clientId - The unique identifier of the client whose swarm status is being checked.
31+
* @returns {Promise<boolean>} A promise that resolves to true if the swarm is busy, or false otherwise.
32+
*/
33+
export async function getCheckBusy(clientId: string) {
34+
return await getCheckBusyInternal(clientId);
35+
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export * from "./functions/target/disposeConnection";
8080
export * from "./functions/common/hasSession";
8181
export * from "./functions/common/hasNavigation";
8282
export * from "./functions/common/getPayload";
83+
export * from "./functions/common/getCheckBusy";
8384
export * from "./functions/common/getAgentName";
8485
export * from "./functions/common/getAgentHistory";
8586
export * from "./functions/common/getSessionMode";

src/interfaces/Swarm.interface.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,14 @@ export interface ISwarm {
253253
* @throws {Error} If the emission fails due to connection issues or invalid message format.
254254
*/
255255
emit(message: string): Promise<void>;
256+
257+
/**
258+
* Returns the current busy state of the swarm.
259+
* Used to check if the swarm is currently processing an operation (e.g., waiting for output or switching agents).
260+
* Supports debugging and flow control in client applications.
261+
* @returns {Promise<boolean>} True if the swarm is busy, false otherwise.
262+
*/
263+
getCheckBusy(): Promise<boolean>;
256264
}
257265

258266
/**

src/lib/services/connection/SwarmConnectionService.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,21 @@ export class SwarmConnectionService implements ISwarm {
151151
).navigationPop();
152152
};
153153

154+
/**
155+
* Returns the current busy state of the swarm.
156+
* Used to check if the swarm is currently processing an operation (e.g., waiting for output or switching agents).
157+
* Supports debugging and flow control in client applications.
158+
* @returns {Promise<boolean>} True if the swarm is busy, false otherwise.
159+
*/
160+
public getCheckBusy = async () => {
161+
GLOBAL_CONFIG.CC_LOGGER_ENABLE_INFO &&
162+
this.loggerService.info(`swarmConnectionService getCheckBusy`);
163+
return await this.getSwarm(
164+
this.methodContextService.context.clientId,
165+
this.methodContextService.context.swarmName
166+
).getCheckBusy();
167+
};
168+
154169
/**
155170
* Cancels the pending output by emitting an empty string, interrupting waitForOutput.
156171
* Delegates to ClientSwarm.cancelOutput, using context from MethodContextService, logging via LoggerService if GLOBAL_CONFIG.CC_LOGGER_ENABLE_INFO is true.

src/lib/services/public/SwarmPublicService.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,43 @@ export class SwarmPublicService implements TSwarmConnectionService {
135135
);
136136
};
137137

138+
/**
139+
* Returns the current busy state of the swarm.
140+
* Used to check if the swarm is currently processing an operation (e.g., waiting for output or switching agents).
141+
* Supports debugging and flow control in client applications.
142+
* @param {string} methodName - The name of the method invoking the operation, logged and scoped in context.
143+
* @param {string} clientId - The client ID, tying to ClientAgent sessions and PerfService tracking, scoping the operation to a specific client.
144+
* @param {SwarmName} swarmName - The name of the swarm, sourced from Swarm.interface, used in SwarmMetaService context.
145+
* @returns {Promise<boolean>} True if the swarm is busy, false otherwise.
146+
*/
147+
public getCheckBusy = async (
148+
methodName: string,
149+
clientId: string,
150+
swarmName: SwarmName
151+
) => {
152+
GLOBAL_CONFIG.CC_LOGGER_ENABLE_INFO &&
153+
this.loggerService.info("swarmPublicService getCheckBusy", {
154+
clientId,
155+
swarmName,
156+
});
157+
return await MethodContextService.runInContext(
158+
async () => {
159+
return await this.swarmConnectionService.getCheckBusy();
160+
},
161+
{
162+
methodName,
163+
clientId,
164+
swarmName,
165+
policyName: "",
166+
agentName: "",
167+
storageName: "",
168+
stateName: "",
169+
mcpName: "",
170+
computeName: "",
171+
}
172+
);
173+
};
174+
138175
/**
139176
* Cancels the await of output in the swarm by emitting an empty string, scoped to a client.
140177
* Wraps SwarmConnectionService.cancelOutput with MethodContextService, logging via LoggerService if GLOBAL_CONFIG.CC_LOGGER_ENABLE_INFO is true.

0 commit comments

Comments
 (0)