@@ -9,7 +9,7 @@ public enum Limits {
99}
1010
1111public final class Agent {
12- public static let version = " 0.6 .0 "
12+ public static let version = " 0.7 .0 "
1313
1414 private static let todoReminderThreshold = 3
1515
@@ -21,7 +21,8 @@ public final class Agent {
2121 private let shellExecutor : ShellExecutor
2222 private let skillLoader : SkillLoader
2323 private let contextCompactor : ContextCompactor
24- private let todoManager = TodoManager ( )
24+ private let todoManager : TodoManager
25+ private let taskManager : TaskManager
2526
2627 private var messages : [ Message ] = [ ]
2728
@@ -42,6 +43,8 @@ public final class Agent {
4243 transcriptDirectory: " \( workingDirectory) /.transcripts " ,
4344 tokenThreshold: tokenThreshold
4445 )
46+ self . todoManager = TodoManager ( )
47+ self . taskManager = TaskManager ( directory: " \( workingDirectory) /.tasks " )
4548 self . systemPrompt =
4649 systemPrompt
4750 ?? Self . buildSystemPrompt (
@@ -153,6 +156,8 @@ public final class Agent {
153156 - Prefer read_file/write_file/edit_file over bash for file operations
154157 - Always check tool results before proceeding
155158 - Use the todo tool to plan multi-step tasks. Mark in_progress before starting, completed when done.
159+ - Use task tools for persistent multi-step work with dependencies. \
160+ Tasks survive context compaction and process restarts.
156161 """
157162
158163 if !skillDescriptions. isEmpty {
@@ -311,6 +316,76 @@ extension Agent {
311316 ] ) ,
312317 " required " : . array( [ ] )
313318 ] )
319+ ) ,
320+ ToolDefinition (
321+ name: " task_create " ,
322+ description: " Create a persistent task. Tasks survive context compaction and process restarts. " ,
323+ inputSchema: . object( [
324+ " type " : " object " ,
325+ " properties " : . object( [
326+ " subject " : . object( [
327+ " type " : " string " ,
328+ " description " : " Short title for the task "
329+ ] ) ,
330+ " description " : . object( [
331+ " type " : " string " ,
332+ " description " : " Detailed description of the task "
333+ ] )
334+ ] ) ,
335+ " required " : . array( [ " subject " ] )
336+ ] )
337+ ) ,
338+ ToolDefinition (
339+ name: " task_update " ,
340+ description: " Update a task's status or dependencies. " ,
341+ inputSchema: . object( [
342+ " type " : " object " ,
343+ " properties " : . object( [
344+ " task_id " : . object( [
345+ " type " : " integer " ,
346+ " description " : " The task ID to update "
347+ ] ) ,
348+ " status " : . object( [
349+ " type " : " string " ,
350+ " enum " : . array( [ " pending " , " in_progress " , " completed " ] ) ,
351+ " description " : " New status for the task "
352+ ] ) ,
353+ " add_blocked_by " : . object( [
354+ " type " : " array " ,
355+ " items " : . object( [ " type " : " integer " ] ) ,
356+ " description " : " Task IDs that block this task "
357+ ] ) ,
358+ " add_blocks " : . object( [
359+ " type " : " array " ,
360+ " items " : . object( [ " type " : " integer " ] ) ,
361+ " description " : " Task IDs that this task blocks "
362+ ] )
363+ ] ) ,
364+ " required " : . array( [ " task_id " ] )
365+ ] )
366+ ) ,
367+ ToolDefinition (
368+ name: " task_list " ,
369+ description: " List all tasks with status markers and dependency info. " ,
370+ inputSchema: . object( [
371+ " type " : " object " ,
372+ " properties " : . object( [ : ] ) ,
373+ " required " : . array( [ ] )
374+ ] )
375+ ) ,
376+ ToolDefinition (
377+ name: " task_get " ,
378+ description: " Get detailed info about a specific task. " ,
379+ inputSchema: . object( [
380+ " type " : " object " ,
381+ " properties " : . object( [
382+ " task_id " : . object( [
383+ " type " : " integer " ,
384+ " description " : " The task ID to retrieve "
385+ ] )
386+ ] ) ,
387+ " required " : . array( [ " task_id " ] )
388+ ] )
314389 )
315390 ]
316391
@@ -323,7 +398,11 @@ extension Agent {
323398 " todo " : executeTodo,
324399 " agent " : executeAgent,
325400 " load_skill " : executeLoadSkill,
326- " compact " : executeCompact
401+ " compact " : executeCompact,
402+ " task_create " : executeTaskCreate,
403+ " task_update " : executeTaskUpdate,
404+ " task_list " : executeTaskList,
405+ " task_get " : executeTaskGet
327406 ]
328407
329408 guard let handler = handlers [ name] else {
@@ -508,6 +587,60 @@ extension Agent {
508587
509588 private func executeCompact( _ input: JSONValue ) async -> Result < String , ToolError > { . success( " Compressing... " ) }
510589
590+ private func executeTaskCreate( _ input: JSONValue ) async -> Result < String , ToolError > {
591+ guard let subject = input [ " subject " ] ? . stringValue else {
592+ return . failure( . missingParameter( " subject " ) )
593+ }
594+
595+ let description = input [ " description " ] ? . stringValue ?? " "
596+
597+ do {
598+ let result = try taskManager. create ( subject: subject, description: description)
599+ return . success( result)
600+ } catch {
601+ return . failure( . executionFailed( " \( error) " ) )
602+ }
603+ }
604+
605+ private func executeTaskUpdate( _ input: JSONValue ) async -> Result < String , ToolError > {
606+ guard let taskId = input [ " task_id " ] ? . intValue else {
607+ return . failure( . missingParameter( " task_id " ) )
608+ }
609+
610+ let status = input [ " status " ] ? . stringValue
611+ let addBlockedBy = input [ " add_blocked_by " ] ? . arrayValue? . compactMap ( \. intValue) ?? [ ]
612+ let addBlocks = input [ " add_blocks " ] ? . arrayValue? . compactMap ( \. intValue) ?? [ ]
613+
614+ do {
615+ let result = try taskManager. update (
616+ taskId: taskId,
617+ status: status,
618+ addBlockedBy: addBlockedBy,
619+ addBlocks: addBlocks
620+ )
621+ return . success( result)
622+ } catch {
623+ return . failure( . executionFailed( " \( error) " ) )
624+ }
625+ }
626+
627+ private func executeTaskList( _ input: JSONValue ) async -> Result < String , ToolError > {
628+ . success( taskManager. listAll ( ) )
629+ }
630+
631+ private func executeTaskGet( _ input: JSONValue ) async -> Result < String , ToolError > {
632+ guard let taskId = input [ " task_id " ] ? . intValue else {
633+ return . failure( . missingParameter( " task_id " ) )
634+ }
635+
636+ do {
637+ let result = try taskManager. get ( taskId: taskId)
638+ return . success( result)
639+ } catch {
640+ return . failure( . executionFailed( " \( error) " ) )
641+ }
642+ }
643+
511644 // MARK: Helpers
512645
513646 struct ToolProcessingResult {
@@ -611,7 +744,7 @@ extension Agent {
611744
612745 static let subagent = LoopConfig (
613746 tools: Agent . toolDefinitions. filter {
614- !Set( [ " agent " , " todo " , " compact " ] ) . contains ( $0. name)
747+ !Set( [ " agent " , " todo " , " compact " , " task_create " , " task_update " ] ) . contains ( $0. name)
615748 } ,
616749 maxIterations: 30 ,
617750 enableNag: false ,
0 commit comments