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 type TaskStatus = ReturnType < typeof buildTaskStatusSchema > [ "infer" ] ;
813
914// GLM (and other Claude-shaped) payloads send in_progress; map it at the
1015// 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 ;
16+ const taskStatusInput = memoSchema ( ( ) =>
17+ type ( "'todo' | 'doing' | 'done' | 'cancelled' | 'in_progress'" ) . pipe (
18+ ( s ) : TaskStatus => ( s === "in_progress" ? "doing" : s ) ,
19+ ) ,
20+ ) ;
21+
22+ function buildTaskSchema ( ) {
23+ return type ( {
24+ id : "string>0" ,
25+ title : "string>0" ,
26+ status : taskStatusSchema ( ) ,
27+ } ) ;
28+ }
29+ const taskSchema = memoSchema ( buildTaskSchema ) ;
30+ export const TaskSchema : ReturnType < typeof buildTaskSchema > =
31+ lazyCallable ( taskSchema ) ;
32+ export type Task = ReturnType < typeof buildTaskSchema > [ "infer" ] ;
2133
2234// A task list has active work while any task is still todo or doing. Terminal
2335// tasks (done/cancelled) are resolved, so an all-terminal list is finished.
@@ -27,21 +39,23 @@ export function hasActiveTasks(tasks: Task[]): boolean {
2739
2840// `create` overwrites the list; `update` patches by id and may append new
2941// 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 ;
42+ const manageTasksArgsSchema = memoSchema ( ( ) =>
43+ type ( {
44+ action : "'create' | 'update'" ,
45+ "tasks?" : type ( {
46+ id : "string>0" ,
47+ title : "string>0" ,
48+ "status?" : taskStatusInput ( ) ,
49+ } ) . array ( ) ,
50+ "updates?" : type ( {
51+ id : "string>0" ,
52+ "title?" : "string>0" ,
53+ "status?" : taskStatusInput ( ) ,
54+ } ) . array ( ) ,
55+ } ) ,
56+ ) ;
57+
58+ export type ManageTasksArgs = ReturnType < typeof manageTasksArgsSchema > [ "infer" ] ;
4559
4660export const manageTasksDefinition : ToolDefinition = {
4761 name : "manage_tasks" ,
@@ -109,7 +123,7 @@ export const manageTasksDefinition: ToolDefinition = {
109123// Clone first: arktype's in_progress→doing morph writes onto the input, and
110124// reactor snapshots deep-freeze tool_call.arguments before decide() runs.
111125export function parseManageTasksArgs ( rawArgs : unknown ) : ManageTasksArgs | null {
112- const result = ManageTasksArgsSchema ( cloneManageTasksInput ( rawArgs ) ) ;
126+ const result = manageTasksArgsSchema ( ) ( cloneManageTasksInput ( rawArgs ) ) ;
113127 return result instanceof type . errors ? null : result ;
114128}
115129
@@ -179,7 +193,7 @@ export type ManageTasksRunner = (rawArgs: Record<string, unknown>) => Promise<{
179193export function createManageTasksRunner ( ) : ManageTasksRunner {
180194 let tasks : Task [ ] = [ ] ;
181195 return async ( rawArgs ) => {
182- const parsed = ManageTasksArgsSchema ( cloneManageTasksInput ( rawArgs ) ) ;
196+ const parsed = manageTasksArgsSchema ( ) ( cloneManageTasksInput ( rawArgs ) ) ;
183197 if ( parsed instanceof type . errors ) {
184198 return {
185199 content : `Error: manage_tasks arguments invalid: ${ parsed . summary } ` ,
0 commit comments