Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/agentscope/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
"types": "./dist/storage/index.d.ts",
"import": "./dist/storage/index.mjs",
"require": "./dist/storage/index.js"
},
"./state": {
"types": "./dist/state/index.d.ts",
"import": "./dist/state/index.mjs",
"require": "./dist/state/index.js"
}
},
"scripts": {
Expand Down
16 changes: 15 additions & 1 deletion packages/agentscope/src/event/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export enum EventType {

USER_CONFIRM_RESULT = 'USER_CONFIRM_RESULT',
EXTERNAL_EXECUTION_RESULT = 'EXTERNAL_EXECUTION_RESULT',

CUSTOM = 'CUSTOM',
}

export interface EventBase {
Expand Down Expand Up @@ -217,6 +219,16 @@ export interface ExternalExecutionResultEvent extends EventBase {
execution_results: ToolResultBlock[];
}

/**
* A custom event carrying an arbitrary name and payload.
* Mirrors the Python `agentscope.event.CustomEvent` model.
*/
export interface CustomEvent extends EventBase {
type: EventType.CUSTOM;
name: string;
value: Record<string, unknown>;
}

export type AgentEvent =
// The control events for the whole run
| ReplyStartEvent
Expand Down Expand Up @@ -245,4 +257,6 @@ export type AgentEvent =
| ToolResultEndEvent
// The events from the external execution or user confirmation
| UserConfirmResultEvent
| ExternalExecutionResultEvent;
| ExternalExecutionResultEvent
// Custom events
| CustomEvent;
23 changes: 23 additions & 0 deletions packages/agentscope/src/state/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Task represents a unit of work tracked in an agent's task context.
* Mirrors the Python `agentscope.state.Task` model.
*/
export interface Task {
id: string;
subject: string;
description: string;
metadata: Record<string, unknown>;
created_at: string;
state: 'pending' | 'in_progress' | 'completed';
owner: string | null;
blocks: string[];
blocked_by: string[];
}

/**
* TaskContext holds the list of tasks associated with an agent session.
* Mirrors the Python `agentscope.state.TaskContext` model.
*/
export interface TaskContext {
tasks: Task[];
}
46 changes: 21 additions & 25 deletions packages/agentscope/src/tool/task.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ describe('Task Tools', () => {
};

describe('TaskCreate', () => {
it('creates a task with pending status', () => {
it('creates a task with pending state', () => {
const response = taskCreate.call!({
subject: 'Fix bug',
description: 'Fix the authentication bug',
}) as ToolResponse;
const result = getTextFromResponse(response);
expect(result).toContain('Task #1 created successfully');
expect(result).toContain('Task 1 created successfully');
expect(result).toContain('Fix bug');
});

Expand All @@ -39,18 +39,17 @@ describe('Task Tools', () => {
description: 'Second task',
}) as ToolResponse;
const result = getTextFromResponse(response);
expect(result).toContain('Task #2 created successfully');
expect(result).toContain('Task 2 created successfully');
});

it('supports optional activeForm and metadata', () => {
it('supports optional metadata', () => {
const response = taskCreate.call!({
subject: 'Run tests',
description: 'Execute test suite',
activeForm: 'Running tests',
metadata: { priority: 'high' },
}) as ToolResponse;
const result = getTextFromResponse(response);
expect(result).toContain('Task #1 created successfully');
expect(result).toContain('Task 1 created successfully');
});
});

Expand All @@ -59,18 +58,18 @@ describe('Task Tools', () => {
taskCreate.call!({ subject: 'Task 1', description: 'First task' });
});

it('updates task status', () => {
it('updates task state', () => {
const response = taskUpdate.call!({
taskId: '1',
status: 'in_progress',
}) as ToolResponse;
const result = getTextFromResponse(response);
expect(result).toContain('Task #1 updated successfully');
expect(result).toContain('Task 1 updated successfully');

// Verify the update by getting the task
const getResponse = taskGet.call!({ taskId: '1' }) as ToolResponse;
const getResult = getTextFromResponse(getResponse);
expect(getResult).toContain('Status: in_progress');
expect(getResult).toContain('State: in_progress');
});

it('updates task subject and description', () => {
Expand Down Expand Up @@ -182,7 +181,7 @@ describe('Task Tools', () => {
status: 'deleted',
}) as ToolResponse;
const result = getTextFromResponse(response);
expect(result).toContain('Task #1 deleted successfully');
expect(result).toContain('Task 1 deleted successfully');

// Verify task is gone
expect(() => taskGet.call!({ taskId: '1' })).toThrow('Task not found: 1');
Expand All @@ -194,21 +193,18 @@ describe('Task Tools', () => {
taskCreate.call!({
subject: 'Test task',
description: 'Test description',
activeForm: 'Testing',
metadata: { priority: 'high' },
});

const response = taskGet.call!({ taskId: '1' }) as ToolResponse;
const result = getTextFromResponse(response);

expect(result).toContain('Task #1: Test task');
expect(result).toContain('Status: pending');
expect(result).toContain('Task 1: Test task');
expect(result).toContain('State: pending');
expect(result).toContain('Description: Test description');
expect(result).toContain('Active Form: Testing');
expect(result).toContain('priority');
expect(result).toContain('high');
expect(result).toContain('Created:');
expect(result).toContain('Updated:');
});

it('throws on non-existent task', () => {
Expand All @@ -220,7 +216,7 @@ describe('Task Tools', () => {
it('returns empty message when no tasks exist', () => {
const response = taskList.call!({}) as ToolResponse;
const result = getTextFromResponse(response);
expect(result).toBe('No active tasks found');
expect(result).toBe('No tasks available.');
});

it('lists pending and in_progress tasks', () => {
Expand All @@ -231,8 +227,8 @@ describe('Task Tools', () => {
const response = taskList.call!({}) as ToolResponse;
const result = getTextFromResponse(response);

expect(result).toContain('#1 [pending] Task 1');
expect(result).toContain('#2 [in_progress] Task 2');
expect(result).toContain('1 [pending] Task 1');
expect(result).toContain('2 [in_progress] Task 2');
});

it('filters out completed tasks', () => {
Expand All @@ -244,7 +240,7 @@ describe('Task Tools', () => {
const result = getTextFromResponse(response);

expect(result).not.toContain('Task 1');
expect(result).toContain('#2 [pending] Task 2');
expect(result).toContain('2 [pending] Task 2');
});

it('filters out deleted tasks', () => {
Expand All @@ -256,7 +252,7 @@ describe('Task Tools', () => {
const result = getTextFromResponse(response);

expect(result).not.toContain('Task 1');
expect(result).toContain('#2 [pending] Task 2');
expect(result).toContain('2 [pending] Task 2');
});

it('shows blocked tasks with dependencies', () => {
Expand All @@ -267,7 +263,7 @@ describe('Task Tools', () => {
const response = taskList.call!({}) as ToolResponse;
const result = getTextFromResponse(response);

expect(result).toContain('#2 [pending] Task 2 (blocked by: #1)');
expect(result).toContain('2 [pending] Task 2[blocked by 1]');
});

it('sorts tasks by ID', () => {
Expand All @@ -279,9 +275,9 @@ describe('Task Tools', () => {
const result = getTextFromResponse(response);

const lines = result.split('\n');
expect(lines[0]).toContain('#1');
expect(lines[1]).toContain('#2');
expect(lines[2]).toContain('#3');
expect(lines[0]).toContain('1');
expect(lines[1]).toContain('2');
expect(lines[2]).toContain('3');
});

it('returns empty when all tasks are completed', () => {
Expand All @@ -293,7 +289,7 @@ describe('Task Tools', () => {
const response = taskList.call!({}) as ToolResponse;
const result = getTextFromResponse(response);

expect(result).toBe('No active tasks found');
expect(result).toBe('No tasks available.');
});
});
});
Loading
Loading