@@ -50,6 +50,10 @@ const (
50
50
ToolNameWorkspaceEditFile = "coder_workspace_edit_file"
51
51
ToolNameWorkspaceEditFiles = "coder_workspace_edit_files"
52
52
ToolNameWorkspacePortForward = "coder_workspace_port_forward"
53
+ ToolNameCreateTask = "coder_create_task"
54
+ ToolNameDeleteTask = "coder_delete_task"
55
+ ToolNameListTasks = "coder_list_tasks"
56
+ ToolNameGetTaskStatus = "coder_get_task_status"
53
57
)
54
58
55
59
func NewDeps (client * codersdk.Client ,opts ... func (* Deps )) (Deps ,error ) {
@@ -223,6 +227,10 @@ var All = []GenericTool{
223
227
WorkspaceEditFile .Generic (),
224
228
WorkspaceEditFiles .Generic (),
225
229
WorkspacePortForward .Generic (),
230
+ CreateTask .Generic (),
231
+ DeleteTask .Generic (),
232
+ ListTasks .Generic (),
233
+ GetTaskStatus .Generic (),
226
234
}
227
235
228
236
type ReportTaskArgs struct {
@@ -344,7 +352,7 @@ is provisioned correctly and the agent can connect to the control plane.
344
352
Properties :map [string ]any {
345
353
"user" :map [string ]any {
346
354
"type" :"string" ,
347
- "description" :"Username or ID of the user to createthe workspace for. Use the `me` keyword to create a workspace for the authenticated user." ,
355
+ "description" :userDescription ( " create a workspace" ) ,
348
356
},
349
357
"template_version_id" :map [string ]any {
350
358
"type" :"string" ,
@@ -1393,8 +1401,6 @@ type WorkspaceLSResponse struct {
1393
1401
Contents []WorkspaceLSFile `json:"contents"`
1394
1402
}
1395
1403
1396
- const workspaceDescription = "The workspace name in the format [owner/]workspace[.agent]. If an owner is not specified, the authenticated user is used."
1397
-
1398
1404
var WorkspaceLS = Tool [WorkspaceLSArgs ,WorkspaceLSResponse ]{
1399
1405
Tool : aisdk.Tool {
1400
1406
Name :ToolNameWorkspaceLS ,
@@ -1750,6 +1756,232 @@ var WorkspacePortForward = Tool[WorkspacePortForwardArgs, WorkspacePortForwardRe
1750
1756
},
1751
1757
}
1752
1758
1759
+ type CreateTaskArgs struct {
1760
+ Prompt string `json:"prompt"`
1761
+ TemplateVersionID string `json:"template_version_id"`
1762
+ TemplateVersionPresetID string `json:"template_version_preset_id"`
1763
+ User string `json:"user"`
1764
+ }
1765
+
1766
+ var CreateTask = Tool [CreateTaskArgs , codersdk.Task ]{
1767
+ Tool : aisdk.Tool {
1768
+ Name :ToolNameCreateTask ,
1769
+ Description :`Create a task.` ,
1770
+ Schema : aisdk.Schema {
1771
+ Properties :map [string ]any {
1772
+ "prompt" :map [string ]any {
1773
+ "type" :"string" ,
1774
+ "description" :"Prompt for the task." ,
1775
+ },
1776
+ "template_version_id" :map [string ]any {
1777
+ "type" :"string" ,
1778
+ "description" :"ID of the template version to create the task from." ,
1779
+ },
1780
+ "template_preset_version_id" :map [string ]any {
1781
+ "type" :"string" ,
1782
+ "description" :"Optional ID of the template version preset to create the task from." ,
1783
+ },
1784
+ "user" :map [string ]any {
1785
+ "type" :"string" ,
1786
+ "description" :userDescription ("create a task" ),
1787
+ },
1788
+ },
1789
+ Required : []string {"prompt" ,"template_version_id" },
1790
+ },
1791
+ },
1792
+ UserClientOptional :true ,
1793
+ Handler :func (ctx context.Context ,deps Deps ,args CreateTaskArgs ) (codersdk.Task ,error ) {
1794
+ if args .Prompt == "" {
1795
+ return codersdk.Task {},xerrors .New ("a prompt is required" )
1796
+ }
1797
+
1798
+ tvID ,err := uuid .Parse (args .TemplateVersionID )
1799
+ if err != nil {
1800
+ return codersdk.Task {},xerrors .New ("template_version_id must be a valid UUID" )
1801
+ }
1802
+
1803
+ var tvPresetID uuid.UUID
1804
+ if args .TemplateVersionPresetID != "" {
1805
+ tvPresetID ,err = uuid .Parse (args .TemplateVersionPresetID )
1806
+ if err != nil {
1807
+ return codersdk.Task {},xerrors .New ("template_version_preset_id must be a valid UUID" )
1808
+ }
1809
+ }
1810
+
1811
+ if args .User == "" {
1812
+ args .User = codersdk .Me
1813
+ }
1814
+
1815
+ expClient := codersdk .NewExperimentalClient (deps .coderClient )
1816
+ task ,err := expClient .CreateTask (ctx ,args .User , codersdk.CreateTaskRequest {
1817
+ Prompt :args .Prompt ,
1818
+ TemplateVersionID :tvID ,
1819
+ TemplateVersionPresetID :tvPresetID ,
1820
+ })
1821
+ if err != nil {
1822
+ return codersdk.Task {},xerrors .Errorf ("create task: %w" ,err )
1823
+ }
1824
+
1825
+ return task ,nil
1826
+ },
1827
+ }
1828
+
1829
+ type DeleteTaskArgs struct {
1830
+ TaskID string `json:"task_id"`
1831
+ }
1832
+
1833
+ var DeleteTask = Tool [DeleteTaskArgs , codersdk.Response ]{
1834
+ Tool : aisdk.Tool {
1835
+ Name :ToolNameDeleteTask ,
1836
+ Description :`Delete a task.` ,
1837
+ Schema : aisdk.Schema {
1838
+ Properties :map [string ]any {
1839
+ "task_id" :map [string ]any {
1840
+ "type" :"string" ,
1841
+ "description" :taskIDDescription ("delete" ),
1842
+ },
1843
+ },
1844
+ Required : []string {"task_id" },
1845
+ },
1846
+ },
1847
+ UserClientOptional :true ,
1848
+ Handler :func (ctx context.Context ,deps Deps ,args DeleteTaskArgs ) (codersdk.Response ,error ) {
1849
+ if args .TaskID == "" {
1850
+ return codersdk.Response {},xerrors .New ("task_id is required" )
1851
+ }
1852
+
1853
+ expClient := codersdk .NewExperimentalClient (deps .coderClient )
1854
+
1855
+ var owner string
1856
+ id ,err := uuid .Parse (args .TaskID )
1857
+ if err == nil {
1858
+ task ,err := expClient .TaskByID (ctx ,id )
1859
+ if err != nil {
1860
+ return codersdk.Response {},xerrors .Errorf ("get task %q: %w" ,args .TaskID ,err )
1861
+ }
1862
+ owner = task .OwnerName
1863
+ }else {
1864
+ workspaceName := NormalizeWorkspaceInput (args .TaskID )
1865
+ ws ,err := namedWorkspace (ctx ,deps .coderClient ,workspaceName )
1866
+ if err != nil {
1867
+ return codersdk.Response {},xerrors .Errorf ("get task workspace %q: %w" ,args .TaskID ,err )
1868
+ }
1869
+ owner = ws .OwnerName
1870
+ id = ws .ID
1871
+ }
1872
+
1873
+ err = expClient .DeleteTask (ctx ,owner ,id )
1874
+ if err != nil {
1875
+ return codersdk.Response {},xerrors .Errorf ("delete task: %w" ,err )
1876
+ }
1877
+
1878
+ return codersdk.Response {
1879
+ Message :"Task deleted successfully" ,
1880
+ },nil
1881
+ },
1882
+ }
1883
+
1884
+ type ListTasksArgs struct {
1885
+ Status string `json:"status"`
1886
+ User string `json:"user"`
1887
+ }
1888
+
1889
+ type ListTasksResponse struct {
1890
+ Tasks []codersdk.Task `json:"tasks"`
1891
+ }
1892
+
1893
+ var ListTasks = Tool [ListTasksArgs ,ListTasksResponse ]{
1894
+ Tool : aisdk.Tool {
1895
+ Name :ToolNameListTasks ,
1896
+ Description :`List tasks.` ,
1897
+ Schema : aisdk.Schema {
1898
+ Properties :map [string ]any {
1899
+ "status" :map [string ]any {
1900
+ "type" :"string" ,
1901
+ "description" :"Optional filter by task status." ,
1902
+ },
1903
+ "user" :map [string ]any {
1904
+ "type" :"string" ,
1905
+ "description" :userDescription ("list tasks" ),
1906
+ },
1907
+ },
1908
+ Required : []string {},
1909
+ },
1910
+ },
1911
+ UserClientOptional :true ,
1912
+ Handler :func (ctx context.Context ,deps Deps ,args ListTasksArgs ) (ListTasksResponse ,error ) {
1913
+ if args .User == "" {
1914
+ args .User = codersdk .Me
1915
+ }
1916
+
1917
+ expClient := codersdk .NewExperimentalClient (deps .coderClient )
1918
+ tasks ,err := expClient .Tasks (ctx ,& codersdk.TasksFilter {
1919
+ Owner :args .User ,
1920
+ Status :args .Status ,
1921
+ })
1922
+ if err != nil {
1923
+ return ListTasksResponse {},xerrors .Errorf ("list tasks: %w" ,err )
1924
+ }
1925
+
1926
+ return ListTasksResponse {
1927
+ Tasks :tasks ,
1928
+ },nil
1929
+ },
1930
+ }
1931
+
1932
+ type GetTaskStatusArgs struct {
1933
+ TaskID string `json:"task_id"`
1934
+ }
1935
+
1936
+ type GetTaskStatusResponse struct {
1937
+ Status codersdk.WorkspaceStatus `json:"status"`
1938
+ State * codersdk.TaskStateEntry `json:"state"`
1939
+ }
1940
+
1941
+ var GetTaskStatus = Tool [GetTaskStatusArgs ,GetTaskStatusResponse ]{
1942
+ Tool : aisdk.Tool {
1943
+ Name :ToolNameGetTaskStatus ,
1944
+ Description :`Get the status of a task.` ,
1945
+ Schema : aisdk.Schema {
1946
+ Properties :map [string ]any {
1947
+ "task_id" :map [string ]any {
1948
+ "type" :"string" ,
1949
+ "description" :taskIDDescription ("get" ),
1950
+ },
1951
+ },
1952
+ Required : []string {"task_id" },
1953
+ },
1954
+ },
1955
+ UserClientOptional :true ,
1956
+ Handler :func (ctx context.Context ,deps Deps ,args GetTaskStatusArgs ) (GetTaskStatusResponse ,error ) {
1957
+ if args .TaskID == "" {
1958
+ return GetTaskStatusResponse {},xerrors .New ("task_id is required" )
1959
+ }
1960
+
1961
+ expClient := codersdk .NewExperimentalClient (deps .coderClient )
1962
+
1963
+ id ,err := uuid .Parse (args .TaskID )
1964
+ if err != nil {
1965
+ workspaceName := NormalizeWorkspaceInput (args .TaskID )
1966
+ ws ,err := namedWorkspace (ctx ,deps .coderClient ,workspaceName )
1967
+ if err != nil {
1968
+ return GetTaskStatusResponse {},xerrors .Errorf ("get task workspace %q: %w" ,args .TaskID ,err )
1969
+ }
1970
+ id = ws .ID
1971
+ }
1972
+
1973
+ task ,err := expClient .TaskByID (ctx ,id )
1974
+ if err != nil {
1975
+ return GetTaskStatusResponse {},xerrors .Errorf ("get task %q: %w" ,args .TaskID ,err )
1976
+ }
1977
+
1978
+ return GetTaskStatusResponse {
1979
+ Status :task .Status ,
1980
+ State :task .CurrentState ,
1981
+ },nil
1982
+ },
1983
+ }
1984
+
1753
1985
// NormalizeWorkspaceInput converts workspace name input to standard format.
1754
1986
// Handles the following input formats:
1755
1987
// - workspace → workspace
@@ -1810,3 +2042,13 @@ func newAgentConn(ctx context.Context, client *codersdk.Client, workspace string
1810
2042
}
1811
2043
return conn ,nil
1812
2044
}
2045
+
2046
+ const workspaceDescription = "The workspace name in the format [owner/]workspace[.agent]. If an owner is not specified, the authenticated user is used."
2047
+
2048
+ func taskIDDescription (action string )string {
2049
+ return fmt .Sprintf ("ID or workspace identifier in the format [owner/]workspace[.agent] for the task to %s. If an owner is not specified, the authenticated user is used." ,action )
2050
+ }
2051
+
2052
+ func userDescription (action string )string {
2053
+ return fmt .Sprintf ("Username or ID of the user for which to %s. Omit or use the `me` keyword to %s for the authenticated user." ,action ,action )
2054
+ }