11import { type } from "arktype" ;
22import type { ToolDefinition } from "@intx/types/runtime" ;
33
4+ import { lazyCallable , memoSchema } from "../schema/lazy.js" ;
5+
46// A task is a unit of work the agent registered for itself. The agent owns the
57// list — it adds, renames, cancels, and status-updates items mid-run.
6- export const TaskStatusSchema = type ( "'todo' | 'doing' | 'done' | 'cancelled'" ) ;
7- export type TaskStatus = typeof TaskStatusSchema . infer ;
8+ function buildTaskStatusSchema ( ) {
9+ return type ( "'todo' | 'doing' | 'done' | 'cancelled'" ) ;
10+ }
11+ const taskStatusSchema = memoSchema ( buildTaskStatusSchema ) ;
12+ export const TaskStatusSchema : ReturnType < typeof buildTaskStatusSchema > =
13+ lazyCallable ( taskStatusSchema ) ;
14+ export type TaskStatus = ReturnType < typeof buildTaskStatusSchema > [ "infer" ] ;
815
916// GLM (and other Claude-shaped) payloads send in_progress; map it at the
1017// boundary so stored tasks stay on the todo/doing/done/cancelled enum.
11- const TaskStatusInput = type (
12- "'todo' | 'doing' | 'done' | 'cancelled' | 'in_progress'" ,
13- ) . pipe ( ( s ) : TaskStatus => ( s === "in_progress" ? "doing" : s ) ) ;
14-
15- export const TaskSchema = type ( {
16- id : "string>0" ,
17- title : "string>0" ,
18- status : TaskStatusSchema ,
19- } ) ;
20- export type Task = typeof TaskSchema . infer ;
18+ const taskStatusInput = memoSchema ( ( ) =>
19+ type ( "'todo' | 'doing' | 'done' | 'cancelled' | 'in_progress'" ) . pipe (
20+ ( s ) : TaskStatus => ( s === "in_progress" ? "doing" : s ) ,
21+ ) ,
22+ ) ;
23+
24+ function buildTaskSchema ( ) {
25+ return type ( {
26+ id : "string>0" ,
27+ title : "string>0" ,
28+ status : taskStatusSchema ( ) ,
29+ } ) ;
30+ }
31+ const taskSchema = memoSchema ( buildTaskSchema ) ;
32+ export const TaskSchema : ReturnType < typeof buildTaskSchema > =
33+ lazyCallable ( taskSchema ) ;
34+ export type Task = ReturnType < typeof buildTaskSchema > [ "infer" ] ;
2135
2236// A task list has active work while any task is still todo or doing. Terminal
2337// tasks (done/cancelled) are resolved, so an all-terminal list is finished.
@@ -27,21 +41,23 @@ export function hasActiveTasks(tasks: Task[]): boolean {
2741
2842// `create` overwrites the list; `update` patches by id and may append new
2943// items (unknown id + title). One multi-purpose tool keeps the schema small.
30- const ManageTasksArgsSchema = type ( {
31- action : "'create' | 'update'" ,
32- "tasks?" : type ( {
33- id : "string>0" ,
34- title : "string>0" ,
35- "status?" : TaskStatusInput ,
36- } ) . array ( ) ,
37- "updates?" : type ( {
38- id : "string>0" ,
39- "title?" : "string>0" ,
40- "status?" : TaskStatusInput ,
41- } ) . array ( ) ,
42- } ) ;
43-
44- export type ManageTasksArgs = typeof ManageTasksArgsSchema . infer ;
44+ const manageTasksArgsSchema = memoSchema ( ( ) =>
45+ type ( {
46+ action : "'create' | 'update'" ,
47+ "tasks?" : type ( {
48+ id : "string>0" ,
49+ title : "string>0" ,
50+ "status?" : taskStatusInput ( ) ,
51+ } ) . array ( ) ,
52+ "updates?" : type ( {
53+ id : "string>0" ,
54+ "title?" : "string>0" ,
55+ "status?" : taskStatusInput ( ) ,
56+ } ) . array ( ) ,
57+ } ) ,
58+ ) ;
59+
60+ export type ManageTasksArgs = ReturnType < typeof manageTasksArgsSchema > [ "infer" ] ;
4561
4662export const manageTasksDefinition : ToolDefinition = {
4763 name : "manage_tasks" ,
@@ -109,7 +125,7 @@ export const manageTasksDefinition: ToolDefinition = {
109125// Clone first: arktype's in_progress→doing morph writes onto the input, and
110126// reactor snapshots deep-freeze tool_call.arguments before decide() runs.
111127export function parseManageTasksArgs ( rawArgs : unknown ) : ManageTasksArgs | null {
112- const result = ManageTasksArgsSchema ( cloneManageTasksInput ( rawArgs ) ) ;
128+ const result = manageTasksArgsSchema ( ) ( cloneManageTasksInput ( rawArgs ) ) ;
113129 return result instanceof type . errors ? null : result ;
114130}
115131
@@ -179,7 +195,7 @@ export type ManageTasksRunner = (rawArgs: Record<string, unknown>) => Promise<{
179195export function createManageTasksRunner ( ) : ManageTasksRunner {
180196 let tasks : Task [ ] = [ ] ;
181197 return async ( rawArgs ) => {
182- const parsed = ManageTasksArgsSchema ( cloneManageTasksInput ( rawArgs ) ) ;
198+ const parsed = manageTasksArgsSchema ( ) ( cloneManageTasksInput ( rawArgs ) ) ;
183199 if ( parsed instanceof type . errors ) {
184200 return {
185201 content : `Error: manage_tasks arguments invalid: ${ parsed . summary } ` ,
0 commit comments