@looopy-ai/core 1.0.4 → 1.1.1
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/dist/core/agent.d.ts +0 -4
- package/dist/core/agent.js +0 -47
- package/dist/core/iteration.js +1 -1
- package/dist/core/tools.js +50 -48
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/observability/spans/tool.d.ts +2 -2
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/shutdown.d.ts +7 -0
- package/dist/server/shutdown.js +21 -0
- package/dist/tools/client-tool-provider.d.ts +4 -4
- package/dist/tools/client-tool-provider.js +6 -7
- package/dist/tools/local-tools.d.ts +1 -0
- package/dist/tools/local-tools.js +14 -1
- package/dist/tools/mcp-tool-provider.d.ts +3 -1
- package/dist/tools/mcp-tool-provider.js +8 -3
- package/dist/types/event.d.ts +3 -0
- package/dist/types/tools.d.ts +3 -1
- package/dist/types/tools.js +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +1 -1
- package/dist/utils/process-signals.d.ts +0 -3
- package/dist/utils/process-signals.js +0 -67
package/dist/core/agent.d.ts
CHANGED
|
@@ -26,8 +26,6 @@ export declare class Agent {
|
|
|
26
26
|
private readonly config;
|
|
27
27
|
private _state;
|
|
28
28
|
private logger;
|
|
29
|
-
private sigtermHandler?;
|
|
30
|
-
private sigintHandler?;
|
|
31
29
|
private shuttingDown;
|
|
32
30
|
private shutdownComplete;
|
|
33
31
|
constructor(config: AgentConfig);
|
|
@@ -48,6 +46,4 @@ export declare class Agent {
|
|
|
48
46
|
private loadPersistedState;
|
|
49
47
|
private loadMessages;
|
|
50
48
|
private checkAndCompact;
|
|
51
|
-
private registerSignalHandlers;
|
|
52
|
-
private removeSignalHandlers;
|
|
53
49
|
}
|
package/dist/core/agent.js
CHANGED
|
@@ -2,15 +2,12 @@ import { catchError, concat, Observable, of, tap } from 'rxjs';
|
|
|
2
2
|
import { createTaskStatusEvent } from '../events';
|
|
3
3
|
import { addMessagesCompactedEvent, addMessagesLoadedEvent, completeAgentInitializeSpan, completeAgentTurnSpan, failAgentInitializeSpan, failAgentTurnSpan, setResumeAttributes, setTurnCountAttribute, startAgentInitializeSpan, startAgentTurnSpan, } from '../observability/spans';
|
|
4
4
|
import { serializeError } from '../utils/error';
|
|
5
|
-
import { registerSignalListener, unregisterSignalListener } from '../utils/process-signals';
|
|
6
5
|
import { getLogger } from './logger';
|
|
7
6
|
import { runLoop } from './loop';
|
|
8
7
|
export class Agent {
|
|
9
8
|
config;
|
|
10
9
|
_state;
|
|
11
10
|
logger;
|
|
12
|
-
sigtermHandler;
|
|
13
|
-
sigintHandler;
|
|
14
11
|
shuttingDown = false;
|
|
15
12
|
shutdownComplete = false;
|
|
16
13
|
constructor(config) {
|
|
@@ -31,7 +28,6 @@ export class Agent {
|
|
|
31
28
|
};
|
|
32
29
|
this.logger.debug('Agent created');
|
|
33
30
|
this.persistStateSafely();
|
|
34
|
-
this.registerSignalHandlers();
|
|
35
31
|
}
|
|
36
32
|
get state() {
|
|
37
33
|
return { ...this._state };
|
|
@@ -286,7 +282,6 @@ export class Agent {
|
|
|
286
282
|
this._state.status = 'shutdown';
|
|
287
283
|
this._state.lastActivity = new Date();
|
|
288
284
|
await this.persistState();
|
|
289
|
-
this.removeSignalHandlers();
|
|
290
285
|
this.shutdownComplete = true;
|
|
291
286
|
this.config.logger.info('Agent shutdown complete');
|
|
292
287
|
}
|
|
@@ -371,46 +366,4 @@ export class Agent {
|
|
|
371
366
|
});
|
|
372
367
|
}
|
|
373
368
|
}
|
|
374
|
-
registerSignalHandlers() {
|
|
375
|
-
if (typeof process === 'undefined') {
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
if (this.sigtermHandler || typeof process === 'undefined') {
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
if (!this.sigtermHandler) {
|
|
382
|
-
this.sigtermHandler = async () => {
|
|
383
|
-
this.logger.info('Received SIGTERM signal. Initiating graceful shutdown.');
|
|
384
|
-
try {
|
|
385
|
-
await this.shutdown();
|
|
386
|
-
}
|
|
387
|
-
catch (error) {
|
|
388
|
-
this.logger.error({ error }, 'Failed to shutdown agent after SIGTERM signal');
|
|
389
|
-
}
|
|
390
|
-
};
|
|
391
|
-
registerSignalListener('SIGTERM', this.sigtermHandler);
|
|
392
|
-
}
|
|
393
|
-
if (!this.sigintHandler) {
|
|
394
|
-
const sigintHandler = async () => {
|
|
395
|
-
this.logger.info('Received SIGINT signal. Initiating graceful shutdown.');
|
|
396
|
-
try {
|
|
397
|
-
await this.shutdown();
|
|
398
|
-
}
|
|
399
|
-
catch (error) {
|
|
400
|
-
this.logger.error({ error }, 'Failed to shutdown agent after SIGINT signal');
|
|
401
|
-
}
|
|
402
|
-
};
|
|
403
|
-
registerSignalListener('SIGINT', sigintHandler);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
removeSignalHandlers() {
|
|
407
|
-
if (this.sigtermHandler) {
|
|
408
|
-
unregisterSignalListener('SIGTERM', this.sigtermHandler);
|
|
409
|
-
this.sigtermHandler = undefined;
|
|
410
|
-
}
|
|
411
|
-
if (this.sigintHandler) {
|
|
412
|
-
unregisterSignalListener('SIGINT', this.sigintHandler);
|
|
413
|
-
this.sigintHandler = undefined;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
369
|
}
|
package/dist/core/iteration.js
CHANGED
|
@@ -31,7 +31,7 @@ export const runIteration = (context, config, history) => {
|
|
|
31
31
|
logger: context.logger.child({ iteration: config.iterationNumber }),
|
|
32
32
|
parentContext: iterationContext,
|
|
33
33
|
}, event)));
|
|
34
|
-
return concat(llmEvents
|
|
34
|
+
return concat(llmEvents$.pipe(filter((event) => event.kind !== 'tool-call')), toolEvents$).pipe(finishIterationSpan);
|
|
35
35
|
};
|
|
36
36
|
const prepareMessages = (context, history) => {
|
|
37
37
|
const messages = [];
|
package/dist/core/tools.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { concat, defer, of } from 'rxjs';
|
|
1
|
+
import { concat, defer, mergeMap, of } from 'rxjs';
|
|
2
2
|
import { startToolExecuteSpan } from '../observability/spans';
|
|
3
3
|
export const runToolCall = (context, toolCall) => {
|
|
4
4
|
const logger = context.logger.child({
|
|
@@ -6,54 +6,56 @@ export const runToolCall = (context, toolCall) => {
|
|
|
6
6
|
toolCallId: toolCall.toolCallId,
|
|
7
7
|
toolName: toolCall.toolName,
|
|
8
8
|
});
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const { tapFinish } = startToolExecuteSpan(context, toolStartEvent);
|
|
19
|
-
const toolResultEvents$ = defer(async () => {
|
|
20
|
-
logger.trace('Executing tool');
|
|
21
|
-
const provider = context.toolProviders.find((p) => p.canHandle(toolCall.toolName));
|
|
22
|
-
if (!provider) {
|
|
23
|
-
logger.warn('No provider found for tool');
|
|
24
|
-
const errorMessage = `No provider found for tool: ${toolCall.toolName}`;
|
|
25
|
-
return createToolErrorEvent(context, toolCall, errorMessage);
|
|
26
|
-
}
|
|
27
|
-
try {
|
|
28
|
-
const result = await provider.execute({
|
|
29
|
-
id: toolCall.toolCallId,
|
|
30
|
-
type: 'function',
|
|
31
|
-
function: {
|
|
32
|
-
name: toolCall.toolName,
|
|
33
|
-
arguments: toolCall.arguments,
|
|
34
|
-
},
|
|
35
|
-
}, {
|
|
36
|
-
contextId: context.contextId,
|
|
37
|
-
taskId: context.taskId,
|
|
38
|
-
agentId: context.agentId,
|
|
39
|
-
parentContext: context.parentContext,
|
|
40
|
-
authContext: context.authContext,
|
|
41
|
-
});
|
|
42
|
-
logger.trace({
|
|
43
|
-
success: result.success,
|
|
44
|
-
}, 'Tool execution complete');
|
|
45
|
-
return createToolCompleteEvent(context, toolCall, result.result);
|
|
9
|
+
return defer(async () => {
|
|
10
|
+
const matchingProviders = await Promise.all(context.toolProviders.map(async (p) => ({
|
|
11
|
+
provider: p,
|
|
12
|
+
tool: await p.getTool(toolCall.toolName),
|
|
13
|
+
})));
|
|
14
|
+
const matchingProvider = matchingProviders.find((p) => p.tool !== undefined);
|
|
15
|
+
if (!matchingProvider) {
|
|
16
|
+
logger.warn('No tool provider found for tool');
|
|
17
|
+
return of(toolCall);
|
|
46
18
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
19
|
+
const { provider, tool } = matchingProvider;
|
|
20
|
+
logger.trace({ providerName: provider.name }, 'Found tool provider for tool');
|
|
21
|
+
const toolStartEvent = {
|
|
22
|
+
kind: 'tool-start',
|
|
23
|
+
contextId: context.contextId,
|
|
24
|
+
taskId: context.taskId,
|
|
25
|
+
toolCallId: toolCall.toolCallId,
|
|
26
|
+
icon: tool.icon,
|
|
27
|
+
toolName: toolCall.toolName,
|
|
28
|
+
arguments: toolCall.arguments,
|
|
29
|
+
timestamp: new Date().toISOString(),
|
|
30
|
+
};
|
|
31
|
+
const { tapFinish } = startToolExecuteSpan(context, toolCall);
|
|
32
|
+
const toolResultEvents$ = defer(async () => {
|
|
33
|
+
logger.trace({ providerName: provider.name }, 'Executing tool');
|
|
34
|
+
try {
|
|
35
|
+
const result = await provider.execute({
|
|
36
|
+
id: toolCall.toolCallId,
|
|
37
|
+
type: 'function',
|
|
38
|
+
function: {
|
|
39
|
+
name: toolCall.toolName,
|
|
40
|
+
arguments: toolCall.arguments,
|
|
41
|
+
},
|
|
42
|
+
}, context);
|
|
43
|
+
logger.trace({
|
|
44
|
+
success: result.success,
|
|
45
|
+
}, 'Tool execution complete');
|
|
46
|
+
return createToolCompleteEvent(context, toolCall, result.result);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
50
|
+
logger.error({
|
|
51
|
+
error: err.message,
|
|
52
|
+
stack: err.stack,
|
|
53
|
+
}, 'Tool execution failed');
|
|
54
|
+
return createToolErrorEvent(context, toolCall, err.message);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return concat(of(toolStartEvent), toolResultEvents$).pipe(tapFinish);
|
|
58
|
+
}).pipe(mergeMap((obs) => obs));
|
|
57
59
|
};
|
|
58
60
|
const createToolCompleteEvent = (context, toolCall, result) => ({
|
|
59
61
|
kind: 'tool-complete',
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IterationContext } from '../../core/types';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ToolCallEvent, ToolExecutionEvent } from '../../types/event';
|
|
3
3
|
import type { ToolCall } from '../../types/tools';
|
|
4
4
|
export interface ToolExecutionSpanParams {
|
|
5
5
|
agentId: string;
|
|
@@ -7,7 +7,7 @@ export interface ToolExecutionSpanParams {
|
|
|
7
7
|
toolCall: ToolCall;
|
|
8
8
|
parentContext?: import('@opentelemetry/api').Context;
|
|
9
9
|
}
|
|
10
|
-
export declare const startToolExecuteSpan: (context: IterationContext, toolStart:
|
|
10
|
+
export declare const startToolExecuteSpan: (context: IterationContext, toolStart: ToolCallEvent) => {
|
|
11
11
|
span: import("@opentelemetry/api").Span;
|
|
12
12
|
traceContext: import("@opentelemetry/api").Context;
|
|
13
13
|
tapFinish: import("rxjs").MonoTypeOperatorFunction<ToolExecutionEvent>;
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { type BufferedEvent, EventBuffer, type EventBufferConfig, } from './event-buffer';
|
|
2
2
|
export { type EventFilter, EventRouter, type Subscriber, type SubscriptionConfig, } from './event-router';
|
|
3
|
+
export * from './shutdown';
|
|
3
4
|
export { SSEConnection, type SSEConnectionConfig, type SSEResponse, SSEServer, type SSEServerConfig, } from './sse';
|
package/dist/server/index.js
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getLogger } from '../core';
|
|
2
|
+
export class ShutdownManager {
|
|
3
|
+
watchers = [];
|
|
4
|
+
constructor() {
|
|
5
|
+
process.on('SIGINT', this.signalHandler.bind(this));
|
|
6
|
+
process.on('SIGTERM', this.signalHandler.bind(this));
|
|
7
|
+
}
|
|
8
|
+
registerWatcher(handleShutdown, order = 100) {
|
|
9
|
+
this.watchers.push({ handleShutdown, order });
|
|
10
|
+
this.watchers.sort((a, b) => a.order - b.order);
|
|
11
|
+
}
|
|
12
|
+
async initiateShutdown() {
|
|
13
|
+
for (const watcher of this.watchers) {
|
|
14
|
+
await watcher.handleShutdown();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
signalHandler(signal) {
|
|
18
|
+
getLogger({ component: 'shutdown-manager' }).info({ signal, watchers: this.watchers.length }, 'Received shutdown signal');
|
|
19
|
+
this.initiateShutdown();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -5,18 +5,18 @@ export interface ClientToolConfig {
|
|
|
5
5
|
onInputRequired: (toolCall: ToolCall, context: ExecutionContext) => Promise<ToolResult>;
|
|
6
6
|
}
|
|
7
7
|
export declare class ClientToolProvider implements ToolProvider {
|
|
8
|
+
name: string;
|
|
8
9
|
private readonly tools;
|
|
9
10
|
private readonly toolNames;
|
|
10
11
|
private readonly onInputRequired;
|
|
11
12
|
constructor(config: ClientToolConfig);
|
|
12
13
|
getTools(): Promise<ToolDefinition[]>;
|
|
13
|
-
canHandle(toolName: string): boolean;
|
|
14
14
|
execute(toolCall: ToolCall, context: ExecutionContext): Promise<ToolResult>;
|
|
15
|
-
getTool(name: string): ToolDefinition | undefined
|
|
16
|
-
validateToolArguments(toolCall: ToolCall): {
|
|
15
|
+
getTool(name: string): Promise<ToolDefinition | undefined>;
|
|
16
|
+
validateToolArguments(toolCall: ToolCall): Promise<{
|
|
17
17
|
valid: boolean;
|
|
18
18
|
errors?: string[];
|
|
19
|
-
}
|
|
19
|
+
}>;
|
|
20
20
|
private validateRequiredParams;
|
|
21
21
|
private validateUnknownParams;
|
|
22
22
|
private validateParamTypes;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { validateToolDefinitions, } from '../types/tools';
|
|
2
2
|
export class ClientToolProvider {
|
|
3
|
+
name = 'client-tool-provider';
|
|
3
4
|
tools;
|
|
4
5
|
toolNames;
|
|
5
6
|
onInputRequired;
|
|
@@ -24,11 +25,9 @@ export class ClientToolProvider {
|
|
|
24
25
|
async getTools() {
|
|
25
26
|
return [...this.tools];
|
|
26
27
|
}
|
|
27
|
-
canHandle(toolName) {
|
|
28
|
-
return this.toolNames.has(toolName);
|
|
29
|
-
}
|
|
30
28
|
async execute(toolCall, context) {
|
|
31
|
-
|
|
29
|
+
const tool = await this.getTool(toolCall.function.name);
|
|
30
|
+
if (!tool) {
|
|
32
31
|
return {
|
|
33
32
|
toolCallId: toolCall.id,
|
|
34
33
|
toolName: toolCall.function.name,
|
|
@@ -60,11 +59,11 @@ export class ClientToolProvider {
|
|
|
60
59
|
};
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
|
-
getTool(name) {
|
|
62
|
+
async getTool(name) {
|
|
64
63
|
return this.tools.find((t) => t.name === name);
|
|
65
64
|
}
|
|
66
|
-
validateToolArguments(toolCall) {
|
|
67
|
-
const tool = this.getTool(toolCall.function.name);
|
|
65
|
+
async validateToolArguments(toolCall) {
|
|
66
|
+
const tool = await this.getTool(toolCall.function.name);
|
|
68
67
|
if (!tool) {
|
|
69
68
|
return { valid: false, errors: [`Tool ${toolCall.function.name} not found`] };
|
|
70
69
|
}
|
|
@@ -5,6 +5,7 @@ export type ToolHandler<TParams> = (params: TParams, context: ExecutionContext)
|
|
|
5
5
|
export interface LocalToolDefinition<TSchema extends z.ZodObject> {
|
|
6
6
|
name: string;
|
|
7
7
|
description: string;
|
|
8
|
+
icon?: string;
|
|
8
9
|
schema: TSchema;
|
|
9
10
|
handler: ToolHandler<z.infer<TSchema>>;
|
|
10
11
|
}
|
|
@@ -19,12 +19,25 @@ export function localTools(tools) {
|
|
|
19
19
|
toolMap.set(tool.name, tool);
|
|
20
20
|
}
|
|
21
21
|
return {
|
|
22
|
+
name: 'local-tool-provider',
|
|
22
23
|
getTools: async () => tools.map((t) => ({
|
|
23
24
|
name: t.name,
|
|
24
25
|
description: t.description,
|
|
26
|
+
icon: t.icon,
|
|
25
27
|
parameters: zodToJsonSchema(t.schema),
|
|
26
28
|
})),
|
|
27
|
-
|
|
29
|
+
getTool: async (toolName) => {
|
|
30
|
+
const toolDef = toolMap.get(toolName);
|
|
31
|
+
if (!toolDef) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
name: toolDef.name,
|
|
36
|
+
description: toolDef.description,
|
|
37
|
+
icon: toolDef.icon,
|
|
38
|
+
parameters: zodToJsonSchema(toolDef.schema),
|
|
39
|
+
};
|
|
40
|
+
},
|
|
28
41
|
execute: async (toolCall, context) => {
|
|
29
42
|
const toolDef = toolMap.get(toolCall.function.name);
|
|
30
43
|
if (!toolDef) {
|
|
@@ -8,6 +8,7 @@ export interface MCPProviderConfig {
|
|
|
8
8
|
}
|
|
9
9
|
export declare const mcp: (config: MCPProviderConfig) => McpToolProvider;
|
|
10
10
|
export declare class McpToolProvider implements ToolProvider {
|
|
11
|
+
name: string;
|
|
11
12
|
readonly id: string;
|
|
12
13
|
private readonly client;
|
|
13
14
|
private toolCache;
|
|
@@ -15,8 +16,9 @@ export declare class McpToolProvider implements ToolProvider {
|
|
|
15
16
|
private readonly cacheTTL;
|
|
16
17
|
private ongoingRequest;
|
|
17
18
|
constructor(config: MCPProviderConfig);
|
|
19
|
+
getTool(toolName: string): Promise<ToolDefinition | undefined>;
|
|
20
|
+
executeBatch(toolCalls: ToolCall[], context: ExecutionContext): Promise<ToolResult[]>;
|
|
18
21
|
getTools(): Promise<ToolDefinition[]>;
|
|
19
|
-
canHandle(toolName: string): boolean;
|
|
20
22
|
execute(toolCall: ToolCall, context: ExecutionContext): Promise<ToolResult>;
|
|
21
23
|
private convertMCPTool;
|
|
22
24
|
}
|
|
@@ -3,6 +3,7 @@ export const mcp = (config) => {
|
|
|
3
3
|
return new McpToolProvider(config);
|
|
4
4
|
};
|
|
5
5
|
export class McpToolProvider {
|
|
6
|
+
name = 'mcp-tool-provider';
|
|
6
7
|
id;
|
|
7
8
|
client;
|
|
8
9
|
toolCache = new Map();
|
|
@@ -17,6 +18,13 @@ export class McpToolProvider {
|
|
|
17
18
|
getHeaders: config.getHeaders,
|
|
18
19
|
});
|
|
19
20
|
}
|
|
21
|
+
async getTool(toolName) {
|
|
22
|
+
const tools = await this.getTools();
|
|
23
|
+
return tools.find((tool) => tool.name === toolName);
|
|
24
|
+
}
|
|
25
|
+
async executeBatch(toolCalls, context) {
|
|
26
|
+
return Promise.all(toolCalls.map((call) => this.execute(call, context)));
|
|
27
|
+
}
|
|
20
28
|
async getTools() {
|
|
21
29
|
if (this.toolCache.size > 0 && this.cacheExpiry && Date.now() < this.cacheExpiry) {
|
|
22
30
|
return Array.from(this.toolCache.values());
|
|
@@ -40,9 +48,6 @@ export class McpToolProvider {
|
|
|
40
48
|
});
|
|
41
49
|
return this.ongoingRequest;
|
|
42
50
|
}
|
|
43
|
-
canHandle(toolName) {
|
|
44
|
-
return this.toolCache.has(toolName);
|
|
45
|
-
}
|
|
46
51
|
async execute(toolCall, context) {
|
|
47
52
|
const { name, arguments: args } = toolCall.function;
|
|
48
53
|
if (typeof args !== 'object' || args === null) {
|
package/dist/types/event.d.ts
CHANGED
|
@@ -98,6 +98,7 @@ export interface ToolStartEvent {
|
|
|
98
98
|
contextId: string;
|
|
99
99
|
taskId: string;
|
|
100
100
|
toolCallId: string;
|
|
101
|
+
icon?: string;
|
|
101
102
|
toolName: string;
|
|
102
103
|
arguments: Record<string, unknown>;
|
|
103
104
|
timestamp: string;
|
|
@@ -112,6 +113,7 @@ export interface ToolProgressEvent {
|
|
|
112
113
|
contextId: string;
|
|
113
114
|
taskId: string;
|
|
114
115
|
toolCallId: string;
|
|
116
|
+
icon?: string;
|
|
115
117
|
progress: number;
|
|
116
118
|
message?: string;
|
|
117
119
|
timestamp: string;
|
|
@@ -127,6 +129,7 @@ export interface ToolCompleteEvent {
|
|
|
127
129
|
contextId: string;
|
|
128
130
|
taskId: string;
|
|
129
131
|
toolCallId: string;
|
|
132
|
+
icon?: string;
|
|
130
133
|
toolName: string;
|
|
131
134
|
success: boolean;
|
|
132
135
|
result?: unknown;
|
package/dist/types/tools.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export type FunctionParameters = z.infer<typeof FunctionParametersSchema>;
|
|
|
27
27
|
export declare const ToolDefinitionSchema: z.ZodObject<{
|
|
28
28
|
name: z.ZodString;
|
|
29
29
|
description: z.ZodString;
|
|
30
|
+
icon: z.ZodOptional<z.ZodString>;
|
|
30
31
|
parameters: z.ZodObject<{
|
|
31
32
|
type: z.ZodLiteral<"object">;
|
|
32
33
|
properties: z.ZodRecord<z.ZodString, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
@@ -50,8 +51,9 @@ export declare const ToolCallSchema: z.ZodObject<{
|
|
|
50
51
|
}, z.core.$strip>;
|
|
51
52
|
}, z.core.$strip>;
|
|
52
53
|
export type ToolProvider = {
|
|
54
|
+
get name(): string;
|
|
55
|
+
getTool(toolName: string): Promise<ToolDefinition | undefined>;
|
|
53
56
|
getTools(): Promise<ToolDefinition[]>;
|
|
54
57
|
execute(toolCall: ToolCall, context: ExecutionContext): Promise<ToolResult>;
|
|
55
|
-
canHandle(toolName: string): boolean;
|
|
56
58
|
executeBatch?(toolCalls: ToolCall[], context: ExecutionContext): Promise<ToolResult[]>;
|
|
57
59
|
};
|
package/dist/types/tools.js
CHANGED
|
@@ -31,6 +31,7 @@ export const ToolDefinitionSchema = z.object({
|
|
|
31
31
|
.max(64)
|
|
32
32
|
.regex(/^[a-zA-Z0-9_-]+$/, 'Tool name must contain only alphanumeric characters, underscores, and hyphens'),
|
|
33
33
|
description: z.string().min(1).max(1024),
|
|
34
|
+
icon: z.string().optional(),
|
|
34
35
|
parameters: FunctionParametersSchema,
|
|
35
36
|
});
|
|
36
37
|
export function validateToolDefinitions(tools) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './error';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './error';
|
package/package.json
CHANGED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { getLogger } from '../core/logger';
|
|
2
|
-
import { serializeError } from './error';
|
|
3
|
-
const listeners = new Map();
|
|
4
|
-
const processHandlers = new Map();
|
|
5
|
-
const signalLogger = getLogger({ component: 'process-signal-coordinator' });
|
|
6
|
-
function isProcessAvailable() {
|
|
7
|
-
return typeof process !== 'undefined' && typeof process.on === 'function';
|
|
8
|
-
}
|
|
9
|
-
export function registerSignalListener(signal, listener) {
|
|
10
|
-
if (!isProcessAvailable()) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
const signalListeners = listeners.get(signal) ?? new Set();
|
|
14
|
-
signalListeners.add(listener);
|
|
15
|
-
listeners.set(signal, signalListeners);
|
|
16
|
-
ensureProcessHandler(signal);
|
|
17
|
-
}
|
|
18
|
-
export function unregisterSignalListener(signal, listener) {
|
|
19
|
-
if (!isProcessAvailable()) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
const signalListeners = listeners.get(signal);
|
|
23
|
-
if (!signalListeners) {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
signalListeners.delete(listener);
|
|
27
|
-
if (signalListeners.size === 0) {
|
|
28
|
-
listeners.delete(signal);
|
|
29
|
-
removeProcessHandler(signal);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
function ensureProcessHandler(signal) {
|
|
33
|
-
if (processHandlers.has(signal)) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
const handler = () => {
|
|
37
|
-
const signalListeners = listeners.get(signal);
|
|
38
|
-
if (!signalListeners || signalListeners.size === 0) {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
signalLogger.info({ signal, listenerCount: signalListeners.size }, 'Received process signal; notifying registered listeners');
|
|
42
|
-
const listenersSnapshot = Array.from(signalListeners);
|
|
43
|
-
void Promise.allSettled(listenersSnapshot.map(async (listener) => {
|
|
44
|
-
try {
|
|
45
|
-
await listener();
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
signalLogger.error({ signal, error: serializeError(error) }, 'Signal listener failed');
|
|
49
|
-
}
|
|
50
|
-
}));
|
|
51
|
-
};
|
|
52
|
-
process.on(signal, handler);
|
|
53
|
-
processHandlers.set(signal, handler);
|
|
54
|
-
}
|
|
55
|
-
function removeProcessHandler(signal) {
|
|
56
|
-
const handler = processHandlers.get(signal);
|
|
57
|
-
if (!handler) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
if (typeof process.off === 'function') {
|
|
61
|
-
process.off(signal, handler);
|
|
62
|
-
}
|
|
63
|
-
else if (typeof process.removeListener === 'function') {
|
|
64
|
-
process.removeListener(signal, handler);
|
|
65
|
-
}
|
|
66
|
-
processHandlers.delete(signal);
|
|
67
|
-
}
|