@looopy-ai/core 1.1.6 → 1.2.0
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 +2 -0
- package/dist/core/agent.js +8 -3
- package/dist/core/iteration.js +1 -1
- package/dist/core/loop.js +17 -2
- package/dist/core/tools.d.ts +2 -2
- package/dist/core/tools.js +37 -26
- package/dist/core/types.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/observability/spans/tool.d.ts +3 -3
- package/dist/observability/spans/tool.js +2 -13
- package/dist/providers/litellm-provider.js +4 -4
- package/dist/skills/index.d.ts +1 -0
- package/dist/skills/index.js +1 -0
- package/dist/skills/registry.d.ts +14 -0
- package/dist/skills/registry.js +60 -0
- package/dist/stores/messages/interfaces.d.ts +2 -2
- package/dist/tools/artifact-tools.js +116 -74
- package/dist/tools/local-tools.d.ts +4 -2
- package/dist/tools/local-tools.js +4 -2
- package/dist/types/event.d.ts +17 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/message.d.ts +20 -5
- package/dist/types/skills.d.ts +8 -0
- package/dist/types/skills.js +1 -0
- package/dist/types/tools.d.ts +2 -0
- package/dist/utils/recursive-merge.js +1 -1
- package/package.json +1 -1
package/dist/core/agent.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
|
+
import type { SkillRegistry } from '../skills';
|
|
2
3
|
import type { MessageStore } from '../stores/messages/interfaces';
|
|
3
4
|
import type { AgentState, AgentStore } from '../types/agent';
|
|
4
5
|
import type { AuthContext } from '../types/context';
|
|
@@ -17,6 +18,7 @@ export interface AgentConfig {
|
|
|
17
18
|
autoCompact?: boolean;
|
|
18
19
|
maxMessages?: number;
|
|
19
20
|
systemPrompt?: SystemPromptProp;
|
|
21
|
+
skillRegistry?: SkillRegistry;
|
|
20
22
|
logger?: import('pino').Logger;
|
|
21
23
|
}
|
|
22
24
|
export interface GetMessagesOptions {
|
package/dist/core/agent.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { catchError, concat, Observable, of, tap } from 'rxjs';
|
|
1
|
+
import { catchError, concat, filter, 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';
|
|
@@ -102,7 +102,7 @@ export class Agent {
|
|
|
102
102
|
}
|
|
103
103
|
if (this._state.status === 'error') {
|
|
104
104
|
const error = new Error(`Cannot execute turn: Agent is in error state: ${this._state.error?.message}`);
|
|
105
|
-
logger.error(error
|
|
105
|
+
logger.error(this._state.error, 'Cannot execute turn due to agent error state');
|
|
106
106
|
failAgentTurnSpan(rootSpan, error);
|
|
107
107
|
return of(createTaskStatusEvent({
|
|
108
108
|
contextId: this.config.contextId,
|
|
@@ -170,6 +170,7 @@ export class Agent {
|
|
|
170
170
|
parentContext: turnContext,
|
|
171
171
|
systemPrompt: this.config.systemPrompt,
|
|
172
172
|
toolProviders: this.config.toolProviders,
|
|
173
|
+
skillRegistry: this.config.skillRegistry,
|
|
173
174
|
logger: this.config.logger.child({ taskId, turnNumber }),
|
|
174
175
|
turnNumber,
|
|
175
176
|
}, {
|
|
@@ -210,10 +211,14 @@ export class Agent {
|
|
|
210
211
|
await this.config.messageStore.append(this.config.contextId, [message]);
|
|
211
212
|
break;
|
|
212
213
|
}
|
|
214
|
+
case 'internal:tool-message':
|
|
215
|
+
logger.debug({ message: event.message }, 'Saving internal tool message to message store');
|
|
216
|
+
await this.config.messageStore.append(this.config.contextId, [event.message]);
|
|
217
|
+
break;
|
|
213
218
|
default:
|
|
214
219
|
break;
|
|
215
220
|
}
|
|
216
|
-
}));
|
|
221
|
+
}), filter((event) => event.kind !== 'internal:tool-message'));
|
|
217
222
|
turnEvents$.subscribe({
|
|
218
223
|
next: (event) => {
|
|
219
224
|
observer.next(event);
|
package/dist/core/iteration.js
CHANGED
|
@@ -27,7 +27,7 @@ export const runIteration = (context, config, history) => {
|
|
|
27
27
|
taskId: context.taskId,
|
|
28
28
|
...event,
|
|
29
29
|
})), finishLLMCallSpan);
|
|
30
|
-
}), shareReplay());
|
|
30
|
+
}), shareReplay({ refCount: true }));
|
|
31
31
|
const toolEvents$ = llmEvents$.pipe(filter((event) => event.kind === 'tool-call'), mergeMap((event) => runToolCall({
|
|
32
32
|
...context,
|
|
33
33
|
logger: context.logger.child({ iteration: config.iterationNumber }),
|
package/dist/core/loop.js
CHANGED
|
@@ -27,8 +27,20 @@ export const runLoop = (context, config, history) => {
|
|
|
27
27
|
status: 'working',
|
|
28
28
|
metadata: {},
|
|
29
29
|
});
|
|
30
|
+
const initialMessages = [...history];
|
|
31
|
+
if (context.skillRegistry) {
|
|
32
|
+
const skills = context.skillRegistry.list();
|
|
33
|
+
if (skills.length > 0) {
|
|
34
|
+
const skillList = skills.map((s) => `- **${s.name}**: ${s.description}`).join('\n');
|
|
35
|
+
const skillMessage = {
|
|
36
|
+
role: 'system',
|
|
37
|
+
content: `You can learn new skills by using the 'learn_skill' tool. Available skills:\n\n${skillList}`,
|
|
38
|
+
};
|
|
39
|
+
initialMessages.unshift(skillMessage);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
30
42
|
const merged$ = recursiveMerge({
|
|
31
|
-
messages:
|
|
43
|
+
messages: initialMessages,
|
|
32
44
|
completed: false,
|
|
33
45
|
iteration: 0,
|
|
34
46
|
}, (state) => runIteration({ ...context, parentContext: loopContext }, {
|
|
@@ -37,7 +49,7 @@ export const runLoop = (context, config, history) => {
|
|
|
37
49
|
}, state.messages), (state, { events }) => ({
|
|
38
50
|
...state,
|
|
39
51
|
messages: [...state.messages, ...eventsToMessages(events)],
|
|
40
|
-
}), (e) => e.kind === 'content-complete' && e.finishReason !== 'tool_calls').pipe(shareReplay());
|
|
52
|
+
}), (e) => e.kind === 'content-complete' && e.finishReason !== 'tool_calls').pipe(shareReplay({ refCount: true }));
|
|
41
53
|
const finalSummary$ = merged$.pipe(reduce((last, e) => (e.kind === 'content-complete' ? e : last), null), mergeMap((last) => {
|
|
42
54
|
if (!last)
|
|
43
55
|
return EMPTY;
|
|
@@ -81,6 +93,9 @@ const eventsToMessages = (events) => {
|
|
|
81
93
|
toolCallId: event.toolCallId,
|
|
82
94
|
});
|
|
83
95
|
break;
|
|
96
|
+
case 'internal:tool-message':
|
|
97
|
+
messages.push(event.message);
|
|
98
|
+
break;
|
|
84
99
|
default:
|
|
85
100
|
break;
|
|
86
101
|
}
|
package/dist/core/tools.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type Observable } from 'rxjs';
|
|
2
|
-
import type { ToolCallEvent, ToolExecutionEvent } from '../types/event';
|
|
2
|
+
import type { InternalToolMessageEvent, ToolCallEvent, ToolExecutionEvent } from '../types/event';
|
|
3
3
|
import type { IterationContext } from './types';
|
|
4
|
-
export declare const runToolCall: (context: IterationContext, toolCall: ToolCallEvent) => Observable<ToolExecutionEvent>;
|
|
4
|
+
export declare const runToolCall: (context: IterationContext, toolCall: ToolCallEvent) => Observable<ToolExecutionEvent | InternalToolMessageEvent>;
|
package/dist/core/tools.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { concat, defer, mergeMap, of } from 'rxjs';
|
|
1
|
+
import { catchError, concat, defer, EMPTY, from, mergeMap, of, shareReplay, } from 'rxjs';
|
|
2
2
|
import { startToolExecuteSpan } from '../observability/spans';
|
|
3
3
|
export const runToolCall = (context, toolCall) => {
|
|
4
4
|
const logger = context.logger.child({
|
|
@@ -29,34 +29,45 @@ export const runToolCall = (context, toolCall) => {
|
|
|
29
29
|
timestamp: new Date().toISOString(),
|
|
30
30
|
};
|
|
31
31
|
const { tapFinish } = startToolExecuteSpan(context, toolCall);
|
|
32
|
-
const
|
|
32
|
+
const toolResults$ = defer(async () => {
|
|
33
33
|
logger.trace({ providerName: provider.name }, 'Executing tool');
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}, 'Tool execution complete');
|
|
46
|
-
return result.
|
|
47
|
-
? createToolCompleteEvent(context, toolCall, result.result)
|
|
48
|
-
: createToolErrorEvent(context, toolCall, result.error || 'Unknown error');
|
|
34
|
+
return await provider.execute({
|
|
35
|
+
id: toolCall.toolCallId,
|
|
36
|
+
type: 'function',
|
|
37
|
+
function: {
|
|
38
|
+
name: toolCall.toolName,
|
|
39
|
+
arguments: toolCall.arguments,
|
|
40
|
+
},
|
|
41
|
+
}, context);
|
|
42
|
+
}).pipe(tapFinish, shareReplay({ refCount: true }));
|
|
43
|
+
const toolCompleteEvents$ = toolResults$.pipe(mergeMap((result) => {
|
|
44
|
+
if (result.success) {
|
|
45
|
+
logger.trace({ providerName: provider.name, success: true }, 'Tool execution complete');
|
|
46
|
+
return of(createToolCompleteEvent(context, toolCall, result.result));
|
|
49
47
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
error: err.message,
|
|
54
|
-
stack: err.stack,
|
|
55
|
-
}, 'Tool execution failed');
|
|
56
|
-
return createToolErrorEvent(context, toolCall, err.message);
|
|
48
|
+
else {
|
|
49
|
+
logger.trace({ providerName: provider.name, success: false }, 'Tool execution failed');
|
|
50
|
+
return of(createToolErrorEvent(context, toolCall, result.error || 'Unknown error'));
|
|
57
51
|
}
|
|
58
|
-
})
|
|
59
|
-
|
|
52
|
+
}), catchError((error) => {
|
|
53
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
54
|
+
logger.error({
|
|
55
|
+
providerName: provider.name,
|
|
56
|
+
error: err.message,
|
|
57
|
+
stack: err.stack,
|
|
58
|
+
}, 'Tool execution error');
|
|
59
|
+
return of(createToolErrorEvent(context, toolCall, err.message));
|
|
60
|
+
}));
|
|
61
|
+
const toolMessageEvents$ = toolResults$.pipe(mergeMap((result) => result.success && result.messages
|
|
62
|
+
? from(result.messages?.map((message) => ({
|
|
63
|
+
kind: 'internal:tool-message',
|
|
64
|
+
message,
|
|
65
|
+
timestamp: new Date().toISOString(),
|
|
66
|
+
})))
|
|
67
|
+
: EMPTY), catchError(() => {
|
|
68
|
+
return EMPTY;
|
|
69
|
+
}));
|
|
70
|
+
return concat(of(toolStartEvent), toolCompleteEvents$, toolMessageEvents$);
|
|
60
71
|
}).pipe(mergeMap((obs) => obs));
|
|
61
72
|
};
|
|
62
73
|
const createToolCompleteEvent = (context, toolCall, result) => ({
|
package/dist/core/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type pino from 'pino';
|
|
2
|
+
import type { SkillRegistry } from '../skills';
|
|
2
3
|
import type { AuthContext } from '../types/context';
|
|
3
4
|
import type { LLMProvider } from '../types/llm';
|
|
4
5
|
import type { ToolProvider } from '../types/tools';
|
|
@@ -11,6 +12,7 @@ export type AgentContext = {
|
|
|
11
12
|
toolProviders: ToolProvider[];
|
|
12
13
|
logger: pino.Logger;
|
|
13
14
|
systemPrompt?: SystemPromptProp;
|
|
15
|
+
skillRegistry?: SkillRegistry;
|
|
14
16
|
skillPrompts?: Record<string, string>;
|
|
15
17
|
metadata?: Record<string, unknown>;
|
|
16
18
|
};
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IterationContext } from '../../core/types';
|
|
2
|
-
import type { ToolCallEvent
|
|
3
|
-
import type { ToolCall } from '../../types/tools';
|
|
2
|
+
import type { ToolCallEvent } from '../../types/event';
|
|
3
|
+
import type { ToolCall, ToolResult } from '../../types/tools';
|
|
4
4
|
export interface ToolExecutionSpanParams {
|
|
5
5
|
agentId: string;
|
|
6
6
|
taskId: string;
|
|
@@ -10,5 +10,5 @@ export interface ToolExecutionSpanParams {
|
|
|
10
10
|
export declare const startToolExecuteSpan: (context: IterationContext, toolStart: ToolCallEvent) => {
|
|
11
11
|
span: import("@opentelemetry/api").Span;
|
|
12
12
|
traceContext: import("@opentelemetry/api").Context;
|
|
13
|
-
tapFinish: import("rxjs").MonoTypeOperatorFunction<
|
|
13
|
+
tapFinish: import("rxjs").MonoTypeOperatorFunction<ToolResult>;
|
|
14
14
|
};
|
|
@@ -19,19 +19,8 @@ export const startToolExecuteSpan = (context, toolStart) => {
|
|
|
19
19
|
traceContext,
|
|
20
20
|
tapFinish: tap({
|
|
21
21
|
next: (event) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
span.setAttribute('output', JSON.stringify(event.result));
|
|
25
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
span.setAttribute('output', event.error || 'Tool execution failed');
|
|
29
|
-
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
30
|
-
if (event.error) {
|
|
31
|
-
span.setAttribute('error.message', event.error);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
22
|
+
span.setAttribute('output', JSON.stringify(event.result));
|
|
23
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
35
24
|
},
|
|
36
25
|
complete: () => span.end(),
|
|
37
26
|
error: (err) => {
|
|
@@ -40,7 +40,7 @@ export class LiteLLMProvider {
|
|
|
40
40
|
const rawStream$ = this.createSSEStream(request);
|
|
41
41
|
const stream$ = (this.config.debugLogPath
|
|
42
42
|
? rawStream$.pipe(tap((chunk) => this.debugLogRawChunk(chunk)))
|
|
43
|
-
: rawStream$).pipe(shareReplay());
|
|
43
|
+
: rawStream$).pipe(shareReplay({ refCount: true }));
|
|
44
44
|
const choices$ = stream$.pipe(choices());
|
|
45
45
|
const usage$ = stream$.pipe(usage());
|
|
46
46
|
const { content, tags } = splitInlineXml(choices$.pipe(getContent()));
|
|
@@ -181,11 +181,11 @@ export class LiteLLMProvider {
|
|
|
181
181
|
role: msg.role,
|
|
182
182
|
content: msg.content,
|
|
183
183
|
};
|
|
184
|
-
if (msg.name)
|
|
184
|
+
if ('name' in msg && msg.name)
|
|
185
185
|
baseMsg.name = msg.name;
|
|
186
|
-
if (msg.toolCallId)
|
|
186
|
+
if (msg.role === 'tool' && msg.toolCallId)
|
|
187
187
|
baseMsg.tool_call_id = msg.toolCallId;
|
|
188
|
-
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
188
|
+
if (msg.role === 'assistant' && msg.toolCalls && msg.toolCalls.length > 0) {
|
|
189
189
|
baseMsg.tool_calls = msg.toolCalls.map((tc) => ({
|
|
190
190
|
id: tc.id,
|
|
191
191
|
type: tc.type,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './registry';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './registry';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import type { Skill } from '../types';
|
|
3
|
+
export declare const learnSkillToolName = "learn_skill";
|
|
4
|
+
export declare const skill: (definition: Skill) => Skill;
|
|
5
|
+
export declare class SkillRegistry {
|
|
6
|
+
private skills;
|
|
7
|
+
constructor(skills?: Skill[]);
|
|
8
|
+
register(skill: Skill): void;
|
|
9
|
+
get(name: string): Skill | undefined;
|
|
10
|
+
list(): Skill[];
|
|
11
|
+
tool(): import("..").LocalToolDefinition<z.ZodObject<{
|
|
12
|
+
name: z.ZodString;
|
|
13
|
+
}, z.core.$strip>>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { tool } from '../tools/local-tools';
|
|
3
|
+
export const learnSkillToolName = 'learn_skill';
|
|
4
|
+
const getInstruction = async (instruction) => {
|
|
5
|
+
if (typeof instruction === 'string') {
|
|
6
|
+
return instruction;
|
|
7
|
+
}
|
|
8
|
+
return await instruction();
|
|
9
|
+
};
|
|
10
|
+
export const skill = (definition) => {
|
|
11
|
+
return { ...definition };
|
|
12
|
+
};
|
|
13
|
+
export class SkillRegistry {
|
|
14
|
+
skills = {};
|
|
15
|
+
constructor(skills = []) {
|
|
16
|
+
skills.forEach((skill) => {
|
|
17
|
+
this.skills[skill.name] = skill;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
register(skill) {
|
|
21
|
+
this.skills[skill.name] = skill;
|
|
22
|
+
}
|
|
23
|
+
get(name) {
|
|
24
|
+
return this.skills[name];
|
|
25
|
+
}
|
|
26
|
+
list() {
|
|
27
|
+
return Object.values(this.skills);
|
|
28
|
+
}
|
|
29
|
+
tool() {
|
|
30
|
+
return tool({
|
|
31
|
+
name: learnSkillToolName,
|
|
32
|
+
description: 'Learns a new skill from the available skill registry.',
|
|
33
|
+
schema: z.object({
|
|
34
|
+
name: z.string().describe('The name of the skill to learn.'),
|
|
35
|
+
}),
|
|
36
|
+
handler: async ({ name }) => {
|
|
37
|
+
const foundSkill = this.get(name);
|
|
38
|
+
if (!foundSkill) {
|
|
39
|
+
const availableSkills = this.list()
|
|
40
|
+
.map((s) => `'${s.name}'`)
|
|
41
|
+
.join(', ');
|
|
42
|
+
return {
|
|
43
|
+
success: false,
|
|
44
|
+
result: null,
|
|
45
|
+
error: `Skill '${name}' not found. Available skills are: ${availableSkills}`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const systemMessage = {
|
|
49
|
+
role: 'system',
|
|
50
|
+
content: `You have learned the following skill:\n\n**${foundSkill.name}**\n${await getInstruction(foundSkill.instruction)}`,
|
|
51
|
+
};
|
|
52
|
+
return {
|
|
53
|
+
success: true,
|
|
54
|
+
result: `Successfully learned the '${name}' skill.`,
|
|
55
|
+
messages: [systemMessage],
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Message } from '../../types/message';
|
|
2
|
-
export
|
|
2
|
+
export type StoredMessage = Message & {
|
|
3
3
|
id: string;
|
|
4
4
|
contextId: string;
|
|
5
5
|
index: number;
|
|
@@ -11,7 +11,7 @@ export interface StoredMessage extends Message {
|
|
|
11
11
|
start: number;
|
|
12
12
|
end: number;
|
|
13
13
|
};
|
|
14
|
-
}
|
|
14
|
+
};
|
|
15
15
|
export interface MessageStore {
|
|
16
16
|
append(contextId: string, messages: Message[]): Promise<void>;
|
|
17
17
|
getRecent(contextId: string, options?: {
|
|
@@ -51,12 +51,15 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
51
51
|
});
|
|
52
52
|
await trackArtifactInState(context.taskId, params.artifactId, taskStateStore);
|
|
53
53
|
return {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
:
|
|
54
|
+
success: true,
|
|
55
|
+
result: {
|
|
56
|
+
artifactId: params.artifactId,
|
|
57
|
+
type: 'file',
|
|
58
|
+
status: 'building',
|
|
59
|
+
message: params.override
|
|
60
|
+
? 'File artifact reset. Use append_file_chunk to add content.'
|
|
61
|
+
: 'File artifact created. Use append_file_chunk to add content.',
|
|
62
|
+
},
|
|
60
63
|
};
|
|
61
64
|
},
|
|
62
65
|
}),
|
|
@@ -77,12 +80,15 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
77
80
|
isLastChunk: params.isLastChunk,
|
|
78
81
|
});
|
|
79
82
|
return {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
:
|
|
83
|
+
success: true,
|
|
84
|
+
result: {
|
|
85
|
+
artifactId: params.artifactId,
|
|
86
|
+
chunkAdded: true,
|
|
87
|
+
complete: params.isLastChunk,
|
|
88
|
+
message: params.isLastChunk
|
|
89
|
+
? 'Final chunk appended. Artifact is complete.'
|
|
90
|
+
: 'Chunk appended successfully.',
|
|
91
|
+
},
|
|
86
92
|
};
|
|
87
93
|
},
|
|
88
94
|
}),
|
|
@@ -95,8 +101,11 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
95
101
|
handler: async (params, context) => {
|
|
96
102
|
const content = await scheduledStore.getFileContent(context.contextId, params.artifactId);
|
|
97
103
|
return {
|
|
98
|
-
|
|
99
|
-
|
|
104
|
+
success: true,
|
|
105
|
+
result: {
|
|
106
|
+
artifactId: params.artifactId,
|
|
107
|
+
content,
|
|
108
|
+
},
|
|
100
109
|
};
|
|
101
110
|
},
|
|
102
111
|
}),
|
|
@@ -126,12 +135,15 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
126
135
|
await scheduledStore.writeData(context.contextId, params.artifactId, params.data);
|
|
127
136
|
await trackArtifactInState(context.taskId, params.artifactId, taskStateStore);
|
|
128
137
|
return {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
:
|
|
138
|
+
success: true,
|
|
139
|
+
result: {
|
|
140
|
+
artifactId: params.artifactId,
|
|
141
|
+
type: 'data',
|
|
142
|
+
status: 'complete',
|
|
143
|
+
message: params.override
|
|
144
|
+
? 'Data artifact reset successfully.'
|
|
145
|
+
: 'Data artifact created successfully.',
|
|
146
|
+
},
|
|
135
147
|
};
|
|
136
148
|
},
|
|
137
149
|
}),
|
|
@@ -145,10 +157,13 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
145
157
|
handler: async (params, context) => {
|
|
146
158
|
await scheduledStore.writeData(context.contextId, params.artifactId, params.data);
|
|
147
159
|
return {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
160
|
+
success: true,
|
|
161
|
+
result: {
|
|
162
|
+
artifactId: params.artifactId,
|
|
163
|
+
type: 'data',
|
|
164
|
+
status: 'complete',
|
|
165
|
+
message: 'Data artifact updated successfully.',
|
|
166
|
+
},
|
|
152
167
|
};
|
|
153
168
|
},
|
|
154
169
|
}),
|
|
@@ -161,8 +176,11 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
161
176
|
handler: async (params, context) => {
|
|
162
177
|
const data = await scheduledStore.getDataContent(context.contextId, params.artifactId);
|
|
163
178
|
return {
|
|
164
|
-
|
|
165
|
-
|
|
179
|
+
success: true,
|
|
180
|
+
result: {
|
|
181
|
+
artifactId: params.artifactId,
|
|
182
|
+
data,
|
|
183
|
+
},
|
|
166
184
|
};
|
|
167
185
|
},
|
|
168
186
|
}),
|
|
@@ -175,8 +193,11 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
175
193
|
handler: async (params, context) => {
|
|
176
194
|
const data = await scheduledStore.getDataContent(context.contextId, params.artifactId);
|
|
177
195
|
return {
|
|
178
|
-
|
|
179
|
-
|
|
196
|
+
success: true,
|
|
197
|
+
result: {
|
|
198
|
+
artifactId: params.artifactId,
|
|
199
|
+
data,
|
|
200
|
+
},
|
|
180
201
|
};
|
|
181
202
|
},
|
|
182
203
|
}),
|
|
@@ -212,12 +233,15 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
212
233
|
});
|
|
213
234
|
await trackArtifactInState(context.taskId, params.artifactId, taskStateStore);
|
|
214
235
|
return {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
:
|
|
236
|
+
success: true,
|
|
237
|
+
result: {
|
|
238
|
+
artifactId: params.artifactId,
|
|
239
|
+
type: 'dataset',
|
|
240
|
+
status: 'building',
|
|
241
|
+
message: params.override
|
|
242
|
+
? 'Dataset artifact reset. Use append_dataset_row(s) to add data.'
|
|
243
|
+
: 'Dataset artifact created. Use append_dataset_row(s) to add data.',
|
|
244
|
+
},
|
|
221
245
|
};
|
|
222
246
|
},
|
|
223
247
|
}),
|
|
@@ -231,9 +255,12 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
231
255
|
handler: async (params, context) => {
|
|
232
256
|
await scheduledStore.appendDatasetBatch(context.contextId, params.artifactId, [params.row]);
|
|
233
257
|
return {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
258
|
+
success: true,
|
|
259
|
+
result: {
|
|
260
|
+
artifactId: params.artifactId,
|
|
261
|
+
rowAdded: true,
|
|
262
|
+
message: 'Row appended to dataset.',
|
|
263
|
+
},
|
|
237
264
|
};
|
|
238
265
|
},
|
|
239
266
|
}),
|
|
@@ -250,9 +277,12 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
250
277
|
isLastBatch: params.isLastBatch,
|
|
251
278
|
});
|
|
252
279
|
return {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
280
|
+
success: true,
|
|
281
|
+
result: {
|
|
282
|
+
artifactId: params.artifactId,
|
|
283
|
+
rowsAdded: params.rows.length,
|
|
284
|
+
message: `${params.rows.length} rows appended to dataset.`,
|
|
285
|
+
},
|
|
256
286
|
};
|
|
257
287
|
},
|
|
258
288
|
}),
|
|
@@ -265,9 +295,12 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
265
295
|
handler: async (params, context) => {
|
|
266
296
|
const rows = await scheduledStore.getDatasetRows(context.contextId, params.artifactId);
|
|
267
297
|
return {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
298
|
+
success: true,
|
|
299
|
+
result: {
|
|
300
|
+
artifactId: params.artifactId,
|
|
301
|
+
rows,
|
|
302
|
+
totalRows: rows.length,
|
|
303
|
+
},
|
|
271
304
|
};
|
|
272
305
|
},
|
|
273
306
|
}),
|
|
@@ -282,15 +315,18 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
282
315
|
const artifacts = await Promise.all(artifactIds.map((id) => scheduledStore.getArtifact(context.contextId, id)));
|
|
283
316
|
const validArtifacts = artifacts.filter((a) => a !== null);
|
|
284
317
|
return {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
318
|
+
success: true,
|
|
319
|
+
result: {
|
|
320
|
+
artifacts: validArtifacts.map((a) => ({
|
|
321
|
+
artifactId: a.artifactId,
|
|
322
|
+
type: a.type,
|
|
323
|
+
name: a.name,
|
|
324
|
+
taskId: a.taskId,
|
|
325
|
+
contextId: a.contextId,
|
|
326
|
+
createdAt: a.createdAt,
|
|
327
|
+
})),
|
|
328
|
+
totalCount: validArtifacts.length,
|
|
329
|
+
},
|
|
294
330
|
};
|
|
295
331
|
},
|
|
296
332
|
}),
|
|
@@ -306,25 +342,28 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
306
342
|
throw new Error(`Artifact not found: ${params.artifactId}`);
|
|
307
343
|
}
|
|
308
344
|
return {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
345
|
+
success: true,
|
|
346
|
+
result: {
|
|
347
|
+
artifactId: artifact.artifactId,
|
|
348
|
+
type: artifact.type,
|
|
349
|
+
taskId: artifact.taskId,
|
|
350
|
+
contextId: artifact.contextId,
|
|
351
|
+
name: artifact.name,
|
|
352
|
+
description: artifact.description,
|
|
353
|
+
status: artifact.status,
|
|
354
|
+
createdAt: artifact.createdAt,
|
|
355
|
+
updatedAt: artifact.updatedAt,
|
|
356
|
+
...(artifact.type === 'file' && {
|
|
357
|
+
mimeType: artifact.mimeType,
|
|
358
|
+
encoding: artifact.encoding,
|
|
359
|
+
totalChunks: artifact.totalChunks,
|
|
360
|
+
totalSize: artifact.totalSize,
|
|
361
|
+
}),
|
|
362
|
+
...(artifact.type === 'dataset' && {
|
|
363
|
+
totalRows: artifact.totalSize,
|
|
364
|
+
schema: artifact.schema,
|
|
365
|
+
}),
|
|
366
|
+
},
|
|
328
367
|
};
|
|
329
368
|
},
|
|
330
369
|
}),
|
|
@@ -337,9 +376,12 @@ export function createArtifactTools(artifactStore, taskStateStore) {
|
|
|
337
376
|
handler: async (params, context) => {
|
|
338
377
|
await scheduledStore.deleteArtifact(context.contextId, params.artifactId);
|
|
339
378
|
return {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
379
|
+
success: true,
|
|
380
|
+
result: {
|
|
381
|
+
artifactId: params.artifactId,
|
|
382
|
+
deleted: true,
|
|
383
|
+
message: 'Artifact deleted successfully.',
|
|
384
|
+
},
|
|
343
385
|
};
|
|
344
386
|
},
|
|
345
387
|
}),
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { ExecutionContext } from '../types/context';
|
|
3
|
-
import type { ToolProvider } from '../types/tools';
|
|
4
|
-
|
|
3
|
+
import type { ToolProvider, ToolResult } from '../types/tools';
|
|
4
|
+
type InternalToolResult = Omit<ToolResult, 'toolCallId' | 'toolName'>;
|
|
5
|
+
export type ToolHandler<TParams> = (params: TParams, context: ExecutionContext) => Promise<InternalToolResult> | InternalToolResult;
|
|
5
6
|
export interface LocalToolDefinition<TSchema extends z.ZodObject> {
|
|
6
7
|
name: string;
|
|
7
8
|
description: string;
|
|
@@ -11,3 +12,4 @@ export interface LocalToolDefinition<TSchema extends z.ZodObject> {
|
|
|
11
12
|
}
|
|
12
13
|
export declare function tool<TSchema extends z.ZodObject>(definition: LocalToolDefinition<TSchema>): LocalToolDefinition<TSchema>;
|
|
13
14
|
export declare function localTools(tools: LocalToolDefinition<z.ZodObject>[]): ToolProvider;
|
|
15
|
+
export {};
|
|
@@ -55,8 +55,10 @@ export function localTools(tools) {
|
|
|
55
55
|
return {
|
|
56
56
|
toolCallId: toolCall.id,
|
|
57
57
|
toolName: toolCall.function.name,
|
|
58
|
-
success:
|
|
59
|
-
result,
|
|
58
|
+
success: result.success,
|
|
59
|
+
error: result.error,
|
|
60
|
+
result: result.result,
|
|
61
|
+
messages: result.messages,
|
|
60
62
|
};
|
|
61
63
|
}
|
|
62
64
|
catch (error) {
|
package/dist/types/event.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Message, SystemMessage } from './message';
|
|
1
2
|
import type { ToolCall } from './tools';
|
|
2
3
|
export type TaskStatus = 'working' | 'waiting-input' | 'waiting-auth' | 'waiting-subtask' | 'completed' | 'failed' | 'canceled';
|
|
3
4
|
export type ThoughtVerbosity = 'brief' | 'normal' | 'detailed';
|
|
@@ -306,6 +307,13 @@ export interface InternalLLMCallEvent {
|
|
|
306
307
|
toolCount: number;
|
|
307
308
|
timestamp: string;
|
|
308
309
|
}
|
|
310
|
+
export interface InternalToolMessageEvent {
|
|
311
|
+
kind: 'internal:tool-message';
|
|
312
|
+
contextId: string;
|
|
313
|
+
taskId: string;
|
|
314
|
+
message: SystemMessage;
|
|
315
|
+
timestamp: string;
|
|
316
|
+
}
|
|
309
317
|
export interface InternalCheckpointEvent {
|
|
310
318
|
kind: 'internal:checkpoint';
|
|
311
319
|
contextId: string;
|
|
@@ -331,7 +339,7 @@ export interface InternalToolCompleteEvent {
|
|
|
331
339
|
error?: string;
|
|
332
340
|
timestamp: string;
|
|
333
341
|
}
|
|
334
|
-
export type InternalDebugEvent = InternalLLMCallEvent | InternalCheckpointEvent | InternalToolStartEvent | InternalToolCompleteEvent | InternalThoughtProcessEvent;
|
|
342
|
+
export type InternalDebugEvent = InternalLLMCallEvent | InternalToolMessageEvent | InternalCheckpointEvent | InternalToolStartEvent | InternalToolCompleteEvent | InternalThoughtProcessEvent;
|
|
335
343
|
export interface LLMUsageEvent {
|
|
336
344
|
kind: 'llm-usage';
|
|
337
345
|
contextId: string;
|
|
@@ -347,7 +355,14 @@ export interface LLMUsageEvent {
|
|
|
347
355
|
timestamp: string;
|
|
348
356
|
}
|
|
349
357
|
export type UsageEvent = LLMUsageEvent;
|
|
350
|
-
export
|
|
358
|
+
export interface MessageEvent {
|
|
359
|
+
kind: 'message';
|
|
360
|
+
contextId: string;
|
|
361
|
+
taskId: string;
|
|
362
|
+
message: Message;
|
|
363
|
+
timestamp: string;
|
|
364
|
+
}
|
|
365
|
+
export type AnyEvent = TaskLifecycleEvent | ContentStreamingEvent | ToolExecutionEvent | InputRequestEvent | AuthenticationEvent | ArtifactEvent | SubAgentEvent | ThoughtStreamEvent | InternalDebugEvent | UsageEvent | MessageEvent;
|
|
351
366
|
export type LLMEvent<T> = Omit<T, 'contextId' | 'taskId'>;
|
|
352
367
|
export type ExternalEvent = Exclude<AnyEvent, InternalDebugEvent>;
|
|
353
368
|
export type DebugEvent = InternalDebugEvent;
|
package/dist/types/index.d.ts
CHANGED
package/dist/types/index.js
CHANGED
package/dist/types/message.d.ts
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
import type { ToolCall } from './tools';
|
|
2
|
-
export
|
|
3
|
-
role: 'system'
|
|
2
|
+
export type SystemMessage = {
|
|
3
|
+
role: 'system';
|
|
4
|
+
content: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
};
|
|
7
|
+
export type UserMessage = {
|
|
8
|
+
role: 'user';
|
|
9
|
+
content: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
};
|
|
12
|
+
export type AssistantMessage = {
|
|
13
|
+
role: 'assistant';
|
|
4
14
|
content: string;
|
|
5
15
|
name?: string;
|
|
6
|
-
toolCallId?: string;
|
|
7
16
|
toolCalls?: ToolCall[];
|
|
8
|
-
|
|
9
|
-
|
|
17
|
+
};
|
|
18
|
+
export type ToolMessage = {
|
|
19
|
+
role: 'tool';
|
|
20
|
+
content: string;
|
|
21
|
+
name?: string;
|
|
22
|
+
toolCallId: string;
|
|
23
|
+
};
|
|
24
|
+
export type Message = SystemMessage | UserMessage | AssistantMessage | ToolMessage;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/types/tools.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { ExecutionContext } from './context';
|
|
3
|
+
import type { SystemMessage } from './message';
|
|
3
4
|
export interface ToolCall {
|
|
4
5
|
id: string;
|
|
5
6
|
type: 'function';
|
|
@@ -14,6 +15,7 @@ export interface ToolResult {
|
|
|
14
15
|
success: boolean;
|
|
15
16
|
result: unknown;
|
|
16
17
|
error?: string;
|
|
18
|
+
messages?: SystemMessage[];
|
|
17
19
|
}
|
|
18
20
|
export declare const JsonSchemaPropertySchema: z.ZodType<unknown>;
|
|
19
21
|
export type JsonSchemaProperty = z.infer<typeof JsonSchemaPropertySchema>;
|
|
@@ -3,7 +3,7 @@ export function recursiveMerge(initial, eventsFor, next, isStop) {
|
|
|
3
3
|
const seed = {
|
|
4
4
|
state: initial,
|
|
5
5
|
iteration: 0,
|
|
6
|
-
events$: eventsFor({ ...initial, iteration: 0 }).pipe(shareReplay()),
|
|
6
|
+
events$: eventsFor({ ...initial, iteration: 0 }).pipe(shareReplay({ refCount: true })),
|
|
7
7
|
};
|
|
8
8
|
const iterations$ = of(seed).pipe(expand(({ state, iteration, events$ }) => events$.pipe(reduce((acc, e) => {
|
|
9
9
|
acc.events.push(e);
|