@2digits/tlo-mcp 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # @2digits/tlo-mcp
2
+
3
+ MCP (Model Context Protocol) server for TeamLeader Orbit (TLO) - project management and time tracking.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @2digits/tlo-mcp
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### As MCP Server
14
+
15
+ ```bash
16
+ TLO_COOKIE="your-session-cookie" npx @2digits/tlo-mcp
17
+ ```
18
+
19
+ ### Configuration
20
+
21
+ Set the `TLO_COOKIE` environment variable to your TeamLeader Orbit session cookie.
22
+
23
+ ## Data Model
24
+
25
+ ```text
26
+ FOLDER (workspace, e.g., "2DIGITS | Projects")
27
+ └── PROJECT (e.g., "I amsterdam | doorontwikkeling")
28
+ ├── TASK (work items with budget/workload)
29
+ │ └── ACTIVITY (time entries)
30
+ └── BOARD (kanban)
31
+ └── BOARDLIST (column)
32
+ └── TODO (card)
33
+ ```
34
+
35
+ ### Key IDs
36
+
37
+ - `folderId` - Workspace containing projects
38
+ - `projectId` - Project within a folder
39
+ - `taskId` - Work item within project
40
+ - `todoId` - Kanban card
41
+ - `contactId` - User identifier
42
+
43
+ ## Available Tools
44
+
45
+ ### Projects
46
+
47
+ | Tool | Description |
48
+ | --------------------- | --------------------------------------------------- |
49
+ | `get_projects` | List all projects with client, owner, dates, budget |
50
+ | `get_project_details` | Get single project with billing rates |
51
+ | `get_tasks` | Get tasks within a project |
52
+ | `get_tasks_for_user` | Get tasks assigned to a user |
53
+ | `set_task_state` | Change task state (DRAFT/OPEN/COMPLETED/CLOSED) |
54
+
55
+ ### Time Tracking
56
+
57
+ | Tool | Description |
58
+ | --------------------- | ------------------------------- |
59
+ | `get_week_activities` | Get all time entries for a week |
60
+ | `create_activity` | Log time against project/task |
61
+ | `update_activity` | Modify existing time entry |
62
+ | `delete_activity` | Remove time entry |
63
+
64
+ ### Kanban
65
+
66
+ | Tool | Description |
67
+ | ----------------- | -------------------------------------- |
68
+ | `get_todo_detail` | Get kanban card with columns and links |
69
+ | `move_todo` | Move card between columns |
70
+
71
+ ### Messages
72
+
73
+ | Tool | Description |
74
+ | -------------- | ---------------------------------- |
75
+ | `get_messages` | Get comments on project/board/todo |
76
+ | `post_message` | Add comment to project/board/todo |
77
+
78
+ ## Common Workflows
79
+
80
+ ### View someone's week
81
+
82
+ ```text
83
+ get_week_activities(date: "2025-01-20", contactId: "1699127")
84
+ ```
85
+
86
+ ### Log time
87
+
88
+ ```text
89
+ 1. get_projects() → find folderId
90
+ 2. get_tasks(projectId) → optionally find taskId
91
+ 3. create_activity(folderId, startDate, durationMinutes, contactId)
92
+ ```
93
+
94
+ ### Move kanban card
95
+
96
+ ```text
97
+ 1. get_todo_detail(todoId) → get boardId and BOARDLISTS
98
+ 2. move_todo(id, boardId, boardListId, sortIndex: 0)
99
+ ```
100
+
101
+ ## License
102
+
103
+ MIT
@@ -0,0 +1 @@
1
+ import*as e from"effect/Context";import*as t from"@effect/platform/HttpBody";import*as n from"@effect/platform/UrlParams";import*as r from"effect/Effect";import*as i from"effect/Layer";import*as a from"effect/Option";import*as o from"effect/Redacted";import*as s from"effect/Schema";import*as c from"@effect/platform/HttpClient";import*as l from"@effect/platform/HttpClientRequest";import*as u from"effect/Config";import*as d from"@effect/platform/FetchHttpClient";var f=class extends e.Tag(`@2digits/tlo-mcp/services/TloConfig`)(){},p=class extends s.TaggedError()(`TloApiError`,{message:s.String,code:s.optional(s.String),endpoint:s.optional(s.String)}){},m=class extends s.TaggedError()(`TloAuthError`,{message:s.String}){},h=class extends s.TaggedError()(`TloNetworkError`,{message:s.String,cause:s.optional(s.Unknown),endpoint:s.optional(s.String)}){},g=class extends s.TaggedError()(`TloParseError`,{message:s.String,cause:s.optional(s.Unknown)}){};const _=s.Union(p,m,h,g);var v=class extends e.Tag(`@2digits/tlo-mcp/services/TloHttpClient`)(){};function y(e){return[...e.entries()].map(([e,t])=>`${e}=${t}`).join(`; `)}const b=i.effect(v,r.gen(function*(){let e=yield*f,t=(yield*c.HttpClient).pipe(c.mapRequest(l.prependUrl(e.baseUrl)),c.mapRequest(t=>t.pipe(l.setHeader(`Cookie`,y(e.cookies)))),c.filterStatusOk);return v.of({client:t})}));var x=class extends e.Tag(`@2digits/tlo-mcp/services/TeamLeaderClient`)(){};function ee(e){return t=>new h({message:t._tag===`ResponseError`?`HTTP ${t.response.status}`:`Request failed: ${t.reason}`,cause:t,endpoint:e})}function te(e){return new g({message:`Failed to parse response`,cause:e})}function ne(e){return typeof e==`object`&&!!e&&`err`in e&&typeof e.err==`number`&&e.err!==0}const re=/\{MSG:'([^']*)',\s*err:(\d+)\}/;function S(e){let t=re.exec(e);return t?a.some({MSG:t[1]??`Unknown error`,err:Number(t[2])}):a.none()}const C=i.effect(x,r.gen(function*(){let e=yield*f,{client:i}=yield*v;return x.of({post:r.fn(`TeamLeaderClient.post`)(function*(c,l,u){let d={...l,t:o.value(e.sessionToken)},f=n.fromInput(d);return yield*i.post(c,{body:t.urlParams(f)}).pipe(r.flatMap(e=>e.text),r.flatMap(e=>{let t=S(e);if(a.isSome(t)&&t.value.err!==0)return r.fail(new p({message:t.value.MSG,endpoint:c}));let n;try{n=JSON.parse(e)}catch{return r.fail(new g({message:`Invalid JSON response`,cause:e}))}return ne(n)?r.fail(new p({message:n.MSG,endpoint:c})):s.decodeUnknown(u)(n).pipe(r.mapError(te))}),r.scoped,r.mapError(e=>e instanceof p||e instanceof g?e:ee(c)(e)))})})})),w=s.Struct({ID:s.Number,FOLDERID:s.optional(s.Union(s.String,s.Number)),PROJECT_ID:s.optional(s.Union(s.String,s.Number)),TASKID:s.optional(s.NullOr(s.Union(s.String,s.Number))),TODOID:s.optional(s.NullOr(s.Union(s.String,s.Number))),TICKETID:s.optional(s.NullOr(s.Union(s.String,s.Number))),CONTACTID:s.optional(s.Union(s.String,s.Number)),DESCRIPTION:s.NullOr(s.String),DT:s.String,START_DT:s.optional(s.String),END_DT:s.optional(s.String),DURATION:s.Number,TYPE:s.optional(s.Number),PROJECT_NAME:s.optional(s.NullOr(s.String)),TASK_NAME:s.optional(s.NullOr(s.String)),CLIENT_NAME:s.optional(s.NullOr(s.String)),FOLDER_NAME:s.optional(s.NullOr(s.String)),ENTITY_NAME:s.optional(s.NullOr(s.String)),PROJECTOWNER_NAME:s.optional(s.NullOr(s.String)),CLIENT_COLOR:s.optional(s.NullOr(s.String)),PROJECT_COLOR:s.optional(s.NullOr(s.String)),PROJECT_STATE:s.optional(s.NullOr(s.String)),TASK_STATE:s.optional(s.NullOr(s.String)),TIMESHEET_STATE:s.optional(s.NullOr(s.String)),BILLING_MODE:s.optional(s.NullOr(s.String)),NON_BILLABLE:s.optional(s.NullOr(s.Number)),RATE:s.optional(s.NullOr(s.Number)),VALUE:s.optional(s.NullOr(s.Number)),PROJECT_START_DT:s.optional(s.NullOr(s.String)),PROJECT_END_DT:s.optional(s.NullOr(s.String)),TASK_START_DT:s.optional(s.NullOr(s.String)),TASK_END_DT:s.optional(s.NullOr(s.String)),READONLY:s.optional(s.NullOr(s.Number)),TASK_WORKLOAD:s.optional(s.NullOr(s.Number))});var T=class extends s.Class(`Activity`)({id:s.Number,projectId:s.optional(s.String),folderId:s.optional(s.String),taskId:s.optional(s.NullOr(s.String)),todoId:s.optional(s.NullOr(s.String)),ticketId:s.optional(s.NullOr(s.String)),userId:s.optional(s.String),description:s.NullOr(s.String),startDate:s.String,endDate:s.optional(s.String),durationMinutes:s.Number,projectName:s.optional(s.NullOr(s.String)),taskName:s.optional(s.NullOr(s.String)),clientName:s.optional(s.NullOr(s.String)),folderName:s.optional(s.NullOr(s.String)),entityName:s.optional(s.NullOr(s.String)),projectOwnerName:s.optional(s.NullOr(s.String)),projectState:s.optional(s.NullOr(s.String)),taskState:s.optional(s.NullOr(s.String)),timesheetState:s.optional(s.NullOr(s.String)),billingMode:s.optional(s.NullOr(s.String)),nonBillable:s.optional(s.NullOr(s.Number)),rate:s.optional(s.NullOr(s.Number)),value:s.optional(s.NullOr(s.Number)),projectStartDate:s.optional(s.NullOr(s.String)),projectEndDate:s.optional(s.NullOr(s.String)),taskStartDate:s.optional(s.NullOr(s.String)),taskEndDate:s.optional(s.NullOr(s.String)),readOnly:s.optional(s.NullOr(s.Boolean)),taskWorkload:s.optional(s.NullOr(s.Number)),projectColor:s.optional(s.String),clientColor:s.optional(s.String)}){};function E(e){return new T({id:e.ID,projectId:e.PROJECT_ID===void 0?e.FOLDERID===void 0?void 0:String(e.FOLDERID):String(e.PROJECT_ID),folderId:e.FOLDERID===void 0?void 0:String(e.FOLDERID),taskId:e.TASKID!==void 0&&e.TASKID!==null?String(e.TASKID):null,todoId:e.TODOID!==void 0&&e.TODOID!==null?String(e.TODOID):null,ticketId:e.TICKETID!==void 0&&e.TICKETID!==null?String(e.TICKETID):null,userId:e.CONTACTID===void 0?void 0:String(e.CONTACTID),description:e.DESCRIPTION,startDate:e.DT,endDate:e.END_DT,durationMinutes:e.DURATION,projectName:e.PROJECT_NAME,taskName:e.TASK_NAME,clientName:e.CLIENT_NAME,folderName:e.FOLDER_NAME,entityName:e.ENTITY_NAME,projectOwnerName:e.PROJECTOWNER_NAME,projectState:e.PROJECT_STATE,taskState:e.TASK_STATE,timesheetState:e.TIMESHEET_STATE,billingMode:e.BILLING_MODE,nonBillable:e.NON_BILLABLE,rate:e.RATE,value:e.VALUE,projectStartDate:e.PROJECT_START_DT,projectEndDate:e.PROJECT_END_DT,taskStartDate:e.TASK_START_DT,taskEndDate:e.TASK_END_DT,readOnly:e.READONLY===void 0||e.READONLY===null?void 0:e.READONLY!==0,taskWorkload:e.TASK_WORKLOAD,projectColor:e.PROJECT_COLOR??void 0,clientColor:e.CLIENT_COLOR??void 0})}const D=s.Struct({ACTIVITIES:s.Array(w)}),O=s.Struct({ID:s.Number,DURATION:s.optional(s.Number),DT:s.optional(s.String),TYPE:s.optional(s.Number),DESCRIPTION:s.optional(s.NullOr(s.String)),CLIENT_COLOR:s.optional(s.String),FOLDERID:s.optional(s.Union(s.String,s.Number))});function k(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}T${String(e.getHours()).padStart(2,`0`)}:${String(e.getMinutes()).padStart(2,`0`)}:${String(e.getSeconds()).padStart(2,`0`)}`}var A=class extends e.Tag(`@2digits/tlo-mcp/services/TimeService`)(){};const j=i.effect(A,r.gen(function*(){let e=yield*x;return A.of({getWeek:r.fn(`TimeService.getWeek`)(function*(t,n,i=`Europe/Amsterdam`){return yield*e.post(`/ajax/pln/GetWeek`,{DT:k(t),CONTACTID:n,tmz:i},D).pipe(r.map(e=>e.ACTIVITIES.map(e=>E(e))))}),createActivity:r.fn(`TimeService.createActivity`)(function*(t){return yield*e.post(`/ajax/pln/SetActivity`,{ID:0,ACTION:`CREATE`,DT:k(t.startDate),DURATION:t.durationMinutes,FOLDERID:t.folderId,TASKID:t.taskId,TODOID:t.todoId,CONTACTID:t.contactId,CLIENT_COLOR:t.clientColor,DESCRIPTION:t.description},O).pipe(r.map(e=>e.ID))}),updateActivity:r.fn(`TimeService.updateActivity`)(function*(t){return yield*e.post(`/ajax/pln/SetActivity`,{ID:t.id,ACTION:`MOVE`,DT:t.startDate?k(t.startDate):void 0,DURATION:t.durationMinutes,DESCRIPTION:t.description},O).pipe(r.asVoid)}),deleteActivity:r.fn(`TimeService.deleteActivity`)(function*(t){return yield*e.post(`/ajax/pln/SetActivity`,{ID:t.id,ACTION:`DELETE`},O).pipe(r.asVoid)})})})),M=s.Struct({ID:s.Number,PROJECT_NAME:s.optional(s.String),NAME:s.optional(s.String),STATE:s.optional(s.String),OWNER_NAME:s.optional(s.String),START_DT:s.optional(s.String),END_DT:s.optional(s.String),BILLING_BUDGET:s.optional(s.Number),BILLING_MODE:s.optional(s.String),BILLING_REMAINING:s.optional(s.Number),CLIENT_NAME:s.optional(s.String),CLIENT_ID:s.optional(s.Number),FOLDERID:s.optional(s.Number),FOLDER_NAME:s.optional(s.String),EXTID:s.optional(s.String),CALC_TOTAL:s.optional(s.Number),CALC_DONE:s.optional(s.Number),CALC_PLANNED:s.optional(s.Number)}),ie=s.Struct({Records:s.Array(M),RecordCount:s.optional(s.Number)}),ae=s.Union(M,s.Struct({Record:M}));var N=class extends s.Class(`Project`)({id:s.Number,name:s.String,state:s.optional(s.String),ownerName:s.optional(s.String),startDate:s.optional(s.String),endDate:s.optional(s.String),billingBudget:s.optional(s.Number),billingMode:s.optional(s.String),billingRemaining:s.optional(s.Number),clientName:s.optional(s.String),clientId:s.optional(s.Number),folderId:s.optional(s.Number),folderName:s.optional(s.String),extId:s.optional(s.String),calcTotal:s.optional(s.Number),calcDone:s.optional(s.Number),calcPlanned:s.optional(s.Number)}){};function P(e){return N.make({id:e.ID,name:e.PROJECT_NAME??e.NAME??``,state:e.STATE,ownerName:e.OWNER_NAME,startDate:e.START_DT,endDate:e.END_DT,billingBudget:e.BILLING_BUDGET,billingMode:e.BILLING_MODE,billingRemaining:e.BILLING_REMAINING,clientName:e.CLIENT_NAME,clientId:e.CLIENT_ID,folderId:e.FOLDERID,folderName:e.FOLDER_NAME,extId:e.EXTID,calcTotal:e.CALC_TOTAL,calcDone:e.CALC_DONE,calcPlanned:e.CALC_PLANNED})}const F=s.Struct({ID:s.Number,OWNERID:s.optional(s.Number),OWNER_NAME:s.optional(s.String),AVATAR:s.optional(s.String),CREATED_DT:s.optional(s.String),CONTENT:s.optional(s.String),SUBCONTENT:s.optional(s.String),OBJECTTYPE:s.optional(s.String),OBJECTID:s.optional(s.Number),OBJECTNAME:s.optional(s.String),MSGTYPE:s.optional(s.String),LIKECNT:s.optional(s.Number),REPLYCNT:s.optional(s.Number),OUTQUEUEID:s.optional(s.String),INTERNAL:s.optional(s.Number)}),I=s.Array(F);var L=class extends s.Class(`Message`)({id:s.Number,ownerId:s.optional(s.Number),ownerName:s.optional(s.String),avatar:s.optional(s.String),createdAt:s.optional(s.String),content:s.optional(s.String),subcontent:s.optional(s.String),objectType:s.optional(s.String),objectId:s.optional(s.Number),objectName:s.optional(s.String),messageType:s.optional(s.String),likeCount:s.optional(s.Number),replyCount:s.optional(s.Number),outQueueId:s.optional(s.String),internal:s.optional(s.Boolean)}){};function R(e){return new L({id:e.ID,ownerId:e.OWNERID,ownerName:e.OWNER_NAME,avatar:e.AVATAR,createdAt:e.CREATED_DT,content:e.CONTENT,subcontent:e.SUBCONTENT,objectType:e.OBJECTTYPE,objectId:e.OBJECTID,objectName:e.OBJECTNAME,messageType:e.MSGTYPE,likeCount:e.LIKECNT,replyCount:e.REPLYCNT,outQueueId:e.OUTQUEUEID,internal:e.INTERNAL===void 0?void 0:e.INTERNAL!==0})}const z=s.Struct({ID:s.Number,PROJECTID:s.optional(s.Number),NAME:s.optional(s.String),STATE:s.optional(s.String),OWNER_NAME:s.optional(s.String),START_DT:s.optional(s.String),END_DT:s.optional(s.String),BUDGET:s.optional(s.Number)}),B=s.Struct({Records:s.Array(z),RecordCount:s.optional(s.Number)});var V=class extends s.Class(`Task`)({id:s.Number,projectId:s.optional(s.Number),name:s.optional(s.String),state:s.optional(s.String),ownerName:s.optional(s.String),startDate:s.optional(s.String),endDate:s.optional(s.String),budget:s.optional(s.Number)}){};function H(e){return new V({id:e.ID,projectId:e.PROJECTID,name:e.NAME,state:e.STATE,ownerName:e.OWNER_NAME,startDate:e.START_DT,endDate:e.END_DT,budget:e.BUDGET})}const U=s.Struct({ID:s.Number,WORKLOAD:s.optional(s.Number),TOTAL:s.optional(s.Number),REMAINING:s.optional(s.Number),AVAIL:s.optional(s.Number),CLIENTID:s.optional(s.Number),PROJECTID:s.optional(s.Number),PROJECT_START_DT:s.optional(s.String),PROJECT_END_DT:s.optional(s.String),START_DT:s.optional(s.String),END_DT:s.optional(s.String),STATE:s.optional(s.String)}),W=s.Struct({Records:s.Array(U)});var G=class extends s.Class(`TaskForUser`)({id:s.Number,workload:s.optional(s.Number),total:s.optional(s.Number),remaining:s.optional(s.Number),avail:s.optional(s.Number),clientId:s.optional(s.Number),projectId:s.optional(s.Number),projectStartDate:s.optional(s.String),projectEndDate:s.optional(s.String),startDate:s.optional(s.String),endDate:s.optional(s.String),state:s.optional(s.String)}){};function K(e){return new G({id:e.ID,workload:e.WORKLOAD,total:e.TOTAL,remaining:e.REMAINING,avail:e.AVAIL,clientId:e.CLIENTID,projectId:e.PROJECTID,projectStartDate:e.PROJECT_START_DT,projectEndDate:e.PROJECT_END_DT,startDate:e.START_DT,endDate:e.END_DT,state:e.STATE})}const q=s.Record({key:s.String,value:s.Unknown});var J=class extends e.Tag(`@2digits/tlo-mcp/services/BoardService`)(){};function oe(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`}function Y(e){return e.Records}const X=i.effect(J,r.gen(function*(){let e=yield*x;return J.of({getProjects:r.fn(`BoardService.getProjects`)(function*(t={}){let n=t.states??[`DRAFT`,`OPEN`,`CLOSED`];return yield*e.post(`/ajax/pln/GetProjects`,{STATE:n.join(`|`),COLUMNS:`ID|PROJECT_NAME|NAME|STATE|OWNER_NAME|START_DT|END_DT|BILLING_BUDGET|BILLING_MODE|BILLING_REMAINING|CLIENT_NAME|CLIENT_ID|FOLDERID|FOLDER_NAME|EXTID|CALC_TOTAL|CALC_DONE|CALC_PLANNED`,limit:t.limit??100,page:t.page??1},ie).pipe(r.map(e=>e.Records.map(e=>P(e))))}),getProjectDetails:r.fn(`BoardService.getProjectDetails`)(function*(t){return yield*e.post(`/ajax/pln/GetProjectDetails`,{ID:t.projectId},ae).pipe(r.map(e=>`Record`in e?e.Record:e),r.map(e=>P(e)))}),getMessages:r.fn(`BoardService.getMessages`)(function*(t){return yield*e.post(`/ajax/board/ProcessMessage`,{OBJECTTYPE:t.objectType,OBJECTID:t.objectId,ONLYCOMMENTS:t.onlyComments===!1?0:1,HIDEINTERNAL:t.hideInternal===!1?0:1,PAGETYPE:`SEQID`,MINID:0,limit:t.limit??100},I).pipe(r.map(e=>e.map(e=>R(e))))}),getTasks:r.fn(`BoardService.getTasks`)(function*(t){let n=t.states??[`DRAFT`,`OPEN`,`CLOSED`];return yield*e.post(`/ajax/pln/GetTasks`,{PROJECTID:t.projectId,STATE:n.join(`|`),COLUMNS:`ID|PROJECTID|NAME|STATE|OWNER_NAME|START_DT|END_DT|BUDGET`,limit:t.limit??100,page:t.page??1},B).pipe(r.map(e=>e.Records.map(e=>H(e))))}),getTasksForUser:r.fn(`BoardService.getTasksForUser`)(function*(t){return yield*e.post(`/ajax/pln/GetTasksForUser`,{CONTACTID:t.contactId,START_DT:oe(t.startDate),PERIOD:t.period},W).pipe(r.map(e=>Y(e)),r.map(e=>e.map(e=>K(e))))}),getTodoDetail:r.fn(`BoardService.getTodoDetail`)(function*(t){return yield*e.post(`/ajax/board/GetTodoDetail`,{ID:t.id},q)}),moveTodo:r.fn(`BoardService.moveTodo`)(function*(t){return yield*e.post(`/ajax/board/MoveTodo`,{ID:t.id,BOARDID:t.boardId,BOARDLISTID:t.boardListId,SORTINDEX:t.sortIndex},s.Unknown).pipe(r.asVoid)}),postMessage:r.fn(`BoardService.postMessage`)(function*(t){return yield*e.post(`/ajax/board/ProcessMessage`,{ACTION:`ADD`,OBJECTTYPE:t.objectType,OBJECTID:t.objectId,CONTENT:t.content},s.Unknown).pipe(r.asVoid)}),setTaskState:r.fn(`BoardService.setTaskState`)(function*(t){return yield*e.post(`/ajax/pln/SetTaskState`,{PROJECTID:t.projectId,ID:t.taskId,STATE:t.state},s.Unknown).pipe(r.asVoid)})})}));function se(e){if(a.isNone(e))return new Map;let t=e.value.split(`;`).map(e=>e.trim().split(`=`)).filter(e=>e.length===2);return new Map(t)}const Z=r.gen(function*(){let e=yield*u.redacted(`TLO_SESSION_TOKEN`);return{baseUrl:yield*u.string(`TLO_BASE_URL`).pipe(u.withDefault(`https://socialbrothers.orbit.teamleader.eu`)),sessionToken:e,cookies:se(yield*u.option(u.string(`TLO_COOKIES`)))}}),ce=i.effect(f,Z),Q=i.mergeAll(j,X),$=C.pipe(i.provide(b.pipe(i.provide(d.layer)))),le=Q.pipe(i.provide($));export{_ as C,f as E,m as S,g as T,T as _,ce as a,C as b,L as c,G as d,q as f,j as g,A as h,Z as i,N as l,P as m,le as n,J as o,R as p,Q as r,X as s,$ as t,V as u,E as v,h as w,p as x,x as y};
package/dist/bin.d.mts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/dist/bin.mjs ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{C as e,_ as t,a as n,c as r,d as i,f as a,h as o,l as s,n as c,o as l,u}from"./TloLive-19PJ2qwv.mjs";import*as d from"effect/Effect";import*as f from"effect/Layer";import*as p from"effect/Option";import*as m from"effect/Schema";import*as h from"@effect/platform/Command";import*as g from"@effect/platform/CommandExecutor";import*as _ from"@effect/platform/FileSystem";import*as v from"effect/Deferred";import{constUndefined as ee,constVoid as te,dual as ne,identity as re,pipe as y}from"effect/Function";import*as ie from"effect/Inspectable";import*as b from"effect/Sink";import*as x from"effect/Stream";import*as S from"node:child_process";import*as C from"@effect/platform/Error";import{BadArgument as ae,SystemError as oe}from"@effect/platform/Error";import*as w from"effect/Channel";import*as se from"effect/Cause";import*as ce from"effect/Chunk";import*as T from"effect/Exit";import*as le from"effect/Fiber";import*as ue from"effect/MutableRef";import*as de from"effect/Runtime";import{Readable as fe}from"node:stream";import{effectify as E}from"@effect/platform/Effectify";import*as pe from"node:crypto";import*as D from"node:fs";import*as me from"node:os";import*as O from"node:path";import{Path as k,TypeId as A}from"@effect/platform/Path";import*as j from"node:url";import*as M from"@effect/platform/Terminal";import*as he from"effect/Mailbox";import*as N from"effect/RcRef";import*as P from"node:readline";import*as F from"@effect/platform/Worker";import{WorkerError as I}from"@effect/platform/WorkerError";import*as ge from"effect/Scope";import{makeRunMain as _e}from"@effect/platform/Runtime";import*as L from"@effect/cli/Command";import*as R from"@effect/ai/McpServer";import*as z from"effect/Logger";import*as ve from"@effect/ai/Toolkit";import*as B from"@effect/ai/Tool";const V=(e,t)=>(n,[r])=>{let i=`Unknown`;switch(n.code){case`ENOENT`:i=`NotFound`;break;case`EACCES`:i=`PermissionDenied`;break;case`EEXIST`:i=`AlreadyExists`;break;case`EISDIR`:i=`BadResource`;break;case`ENOTDIR`:i=`BadResource`;break;case`EBUSY`:i=`Busy`;break;case`ELOOP`:i=`BadResource`;break}return new oe({reason:i,module:e,method:t,pathOrDescriptor:r,syscall:n.syscall,description:n.message,cause:n})},H=(e,t,n)=>x.fromChannel(ye(e,t,n)),ye=(e,t,n)=>w.suspend(()=>Se(e(),t,ue.make(void 0),n)),be=(e,t,{encoding:n,endOnDone:r=!0}={},i=d.void)=>{let a=xe(e,n),o=r?d.async(t=>{`closed`in e&&e.closed?t(d.void):(e.once(`finish`,()=>t(d.void)),e.end())}):d.void;return{awaitRead:()=>d.void,emit:a,error:e=>d.zipRight(o,t(e)),done:e=>d.zipRight(o,i)}},xe=(e,t)=>n=>n.length===0?d.void:d.async(r=>{let i=n[Symbol.iterator](),a=i.next();function o(){let n=a;a=i.next();let s=e.write(n.value,t);a.done?r(d.void):s?o():e.once(`drain`,o)}o()}),Se=(e,t,n,r)=>{if(!e.readable)return w.void;let i=d.unsafeMakeLatch(!1);function a(){i.unsafeOpen()}function o(e){n.current=T.fail(t(e)),i.unsafeOpen()}function s(){n.current=T.void,i.unsafeOpen()}e.on(`readable`,a),e.on(`error`,o),e.on(`end`,s);let c=r?.chunkSize?Number(r.chunkSize):void 0,l=w.suspend(function t(){let r=e.read(c);if(r===null)return n.current?w.fromEffect(n.current):(i.unsafeClose(),w.flatMap(i.await,t));let a=[r];for(;;){if(r=e.read(c),r===null)return w.flatMap(w.write(ce.unsafeFromArray(a)),t);a.push(r)}});return w.ensuring(l,d.sync(()=>{e.off(`readable`,a),e.off(`error`,o),e.off(`end`,s),r?.closeOnDone!==!1&&`closed`in e&&!e.closed&&e.destroy()}))},Ce=(e,t,n)=>b.fromChannel(we(e,t,n)),we=(e,t,n)=>w.flatMap(d.zip(d.sync(()=>e()),v.make()),([e,r])=>w.embedInput(Te(e,r,t),be(e,e=>v.failCause(r,e),n,v.complete(r,d.void)))),Te=(e,t,n)=>d.suspend(()=>{function r(e){v.unsafeDone(t,d.fail(n(e)))}return e.on(`error`,r),d.ensuring(v.await(t),d.sync(()=>{e.removeListener(`error`,r)}))}),Ee=e=>typeof e==`string`?e:`pipe`,De=e=>typeof e==`string`?e:`pipe`,U=e=>e instanceof globalThis.Error?e:new globalThis.Error(String(e)),W=(e,t,n)=>{let r=h.flatten(n).reduce((e,t)=>{let n=`${t.command} ${t.args.join(` `)}`;return e.length===0?n:`${e} | ${n}`},``);return V(`Command`,e)(t,[r])},Oe={[g.ProcessTypeId]:g.ProcessTypeId,...ie.BaseProto,toJSON(){return{_id:`@effect/platform/CommandExecutor/Process`,pid:this.pid}}},G=e=>t=>{switch(t._tag){case`StandardCommand`:{let n=d.flatMap(v.make(),e=>d.async(n=>{let r=S.spawn(t.command,t.args,{stdio:[Ee(t.stdin),De(t.stdout),De(t.stderr)],cwd:p.getOrElse(t.cwd,ee),shell:t.shell,env:{...process.env,...Object.fromEntries(t.env)},detached:process.platform!==`win32`});return r.on(`error`,e=>{n(d.fail(W(`spawn`,e,t)))}),r.on(`exit`,(...t)=>{v.unsafeDone(e,d.succeed(t))}),r.on(`spawn`,()=>{n(d.succeed([r,e]))}),d.sync(()=>{r.kill(`SIGTERM`)})})),r=process.platform===`win32`?(e,n)=>d.async(n=>{S.exec(`taskkill /pid ${e.pid} /T /F`,e=>{n(e?d.fail(W(`kill`,U(e),t)):d.void)})}):(e,n)=>d.try({try:()=>process.kill(-e.pid,n),catch:e=>W(`kill`,U(e),t)}),i=(e,n)=>d.suspend(()=>e.kill(n)?d.void:d.fail(W(`kill`,new globalThis.Error(`Failed to kill process`),t)));return y(p.match(t.cwd,{onNone:()=>d.void,onSome:t=>e.access(t)}),d.zipRight(d.acquireRelease(n,([e,t])=>d.flatMap(v.isDone(t),n=>n?d.flatMap(v.await(t),([t])=>t!==0&&t!==null?r(e,`SIGTERM`).pipe(d.ignore):d.void):r(e,`SIGTERM`).pipe(d.orElse(()=>i(e,`SIGTERM`)),d.zipRight(v.await(t)),d.ignore)))),d.map(([e,n])=>{let a=b.drain;e.stdin!==null&&(a=Ce(()=>e.stdin,e=>W(`toWritable`,U(e),t)));let o=d.flatMap(v.await(n),([e,n])=>e===null?d.fail(W(`exitCode`,new globalThis.Error(`Process interrupted due to receipt of signal: ${n}`),t)):d.succeed(g.ExitCode(e))),s=d.negate(v.isDone(n)),c=(t=`SIGTERM`)=>r(e,t).pipe(d.orElse(()=>i(e,t)),d.zipRight(d.asVoid(v.await(n)))),l=g.ProcessId(e.pid),u=H(()=>e.stderr,e=>W(`fromReadable(stderr)`,U(e),t)),f=H(()=>e.stdout,e=>W(`fromReadable(stdout)`,U(e),t));return typeof t.stdout!=`string`&&(f=x.transduce(f,t.stdout)),Object.assign(Object.create(Oe),{pid:l,exitCode:o,isRunning:s,kill:c,stdin:a,stderr:u,stdout:f})}),typeof t.stdin==`string`?re:d.tap(e=>d.forkDaemon(x.run(t.stdin,e.stdin))))}case`PipedCommand`:{let n=h.flatten(t);if(n.length===1)return y(n[0],G(e));let r=n[0],i=n.slice(1),a=i.slice(0,i.length-1),o=i[i.length-1],s=a.reduce((t,n)=>y(h.stdin(n,t),G(e),d.map(e=>e.stdout),x.unwrapScoped),y(G(e)(r),d.map(e=>e.stdout),x.unwrapScoped));return y(h.stdin(o,s),G(e))}}},ke=f.effect(g.CommandExecutor,y(_.FileSystem,d.map(e=>g.makeExecutor(G(e))))),K=e=>t=>new C.BadArgument({module:`FileSystem`,method:e,cause:t}),Ae=(()=>{let e=E(D.access,V(`FileSystem`,`access`),K(`access`));return(t,n)=>{let r=D.constants.F_OK;return n?.readable&&(r|=D.constants.R_OK),n?.writable&&(r|=D.constants.W_OK),e(t,r)}})(),je=(()=>{let e=E(D.cp,V(`FileSystem`,`copy`),K(`copy`));return(t,n,r)=>e(t,n,{force:r?.overwrite??!1,preserveTimestamps:r?.preserveTimestamps??!1,recursive:!0})})(),Me=(()=>{let e=E(D.copyFile,V(`FileSystem`,`copyFile`),K(`copyFile`));return(t,n)=>e(t,n)})(),Ne=(()=>{let e=E(D.chmod,V(`FileSystem`,`chmod`),K(`chmod`));return(t,n)=>e(t,n)})(),Pe=(()=>{let e=E(D.chown,V(`FileSystem`,`chown`),K(`chown`));return(t,n,r)=>e(t,n,r)})(),Fe=(()=>{let e=E(D.link,V(`FileSystem`,`link`),K(`link`));return(t,n)=>e(t,n)})(),Ie=(()=>{let e=E(D.mkdir,V(`FileSystem`,`makeDirectory`),K(`makeDirectory`));return(t,n)=>e(t,{recursive:n?.recursive??!1,mode:n?.mode})})(),q=e=>{let t=E(D.mkdtemp,V(`FileSystem`,e),K(e));return e=>d.suspend(()=>{let n=e?.prefix??``,r=typeof e?.directory==`string`?O.join(e.directory,`.`):me.tmpdir();return t(n?O.join(r,n):r+`/`)})},Le=q(`makeTempDirectory`),J=e=>{let t=E(D.rm,V(`FileSystem`,e),K(e));return(e,n)=>t(e,{recursive:n?.recursive??!1,force:n?.force??!1})},Re=J(`remove`),ze=(()=>{let e=q(`makeTempDirectoryScoped`),t=J(`makeTempDirectoryScoped`);return n=>d.acquireRelease(e(n),e=>d.orDie(t(e,{recursive:!0})))})(),Be=e=>{let t=E(D.open,V(`FileSystem`,e),K(e)),n=E(D.close,V(`FileSystem`,e),K(e));return(e,r)=>y(d.acquireRelease(t(e,r?.flag??`r`,r?.mode),e=>d.orDie(n(e))),d.map(e=>He(_.FileDescriptor(e),r?.flag?.startsWith(`a`)??!1)))},Ve=Be(`open`),He=(()=>{let e=e=>E(D.read,V(`FileSystem`,e),K(e)),t=e(`read`),n=e(`readAlloc`),r=E(D.fstat,V(`FileSystem`,`stat`),K(`stat`)),i=E(D.ftruncate,V(`FileSystem`,`truncate`),K(`truncate`)),a=E(D.fsync,V(`FileSystem`,`sync`),K(`sync`)),o=e=>E(D.write,V(`FileSystem`,e),K(e)),s=o(`write`),c=o(`writeAll`);class l{fd;append;[_.FileTypeId];semaphore=d.unsafeMakeSemaphore(1);position=0n;constructor(e,t){this.fd=e,this.append=t,this[_.FileTypeId]=_.FileTypeId}get stat(){return d.map(r(this.fd),Ze)}get sync(){return a(this.fd)}seek(e,t){let n=_.Size(e);return this.semaphore.withPermits(1)(d.sync(()=>(t===`start`?this.position=n:t===`current`&&(this.position+=n),this.position)))}read(e){return this.semaphore.withPermits(1)(d.map(d.suspend(()=>t(this.fd,{buffer:e,position:this.position})),e=>{let t=_.Size(e);return this.position+=t,t}))}readAlloc(e){let t=Number(e);return this.semaphore.withPermits(1)(d.flatMap(d.sync(()=>Buffer.allocUnsafeSlow(t)),e=>d.map(n(this.fd,{buffer:e,position:this.position}),n=>{if(n===0)return p.none();if(this.position+=BigInt(n),n===t)return p.some(e);let r=Buffer.allocUnsafeSlow(n);return e.copy(r,0,0,n),p.some(r)})))}truncate(e){return this.semaphore.withPermits(1)(d.map(i(this.fd,e?Number(e):void 0),()=>{if(!this.append){let t=BigInt(e??0);this.position>t&&(this.position=t)}}))}write(e){return this.semaphore.withPermits(1)(d.map(d.suspend(()=>s(this.fd,e,void 0,void 0,this.append?void 0:Number(this.position))),e=>{let t=_.Size(e);return this.append||(this.position+=t),t}))}writeAllChunk(e){return d.flatMap(d.suspend(()=>c(this.fd,e,void 0,void 0,this.append?void 0:Number(this.position))),t=>t===0?d.fail(new C.SystemError({module:`FileSystem`,method:`writeAll`,reason:`WriteZero`,pathOrDescriptor:this.fd,description:`write returned 0 bytes written`})):(this.append||(this.position+=BigInt(t)),t<e.length?this.writeAllChunk(e.subarray(t)):d.void))}writeAll(e){return this.semaphore.withPermits(1)(this.writeAllChunk(e))}}return(e,t)=>new l(e,t)})(),Ue=e=>{let t=q(e),n=Be(e),r=e=>d.sync(()=>pe.randomBytes(e).toString(`hex`));return e=>y(d.zip(t(e),r(6)),d.map(([t,n])=>O.join(t,n+(e?.suffix??``))),d.tap(e=>d.scoped(n(e,{flag:`w+`}))))},We=Ue(`makeTempFile`),Ge=(()=>{let e=Ue(`makeTempFileScoped`),t=J(`makeTempFileScoped`);return n=>d.acquireRelease(e(n),e=>d.orDie(t(O.dirname(e),{recursive:!0})))})(),Ke=(e,t)=>d.tryPromise({try:()=>D.promises.readdir(e,t),catch:t=>V(`FileSystem`,`readDirectory`)(t,[e])}),qe=e=>d.async((t,n)=>{try{D.readFile(e,{signal:n},(n,r)=>{t(n?d.fail(V(`FileSystem`,`readFile`)(n,[e])):d.succeed(r))})}catch(e){t(d.fail(K(`readFile`)(e)))}}),Je=(()=>{let e=E(D.readlink,V(`FileSystem`,`readLink`),K(`readLink`));return t=>e(t)})(),Ye=(()=>{let e=E(D.realpath,V(`FileSystem`,`realPath`),K(`realPath`));return t=>e(t)})(),Xe=(()=>{let e=E(D.rename,V(`FileSystem`,`rename`),K(`rename`));return(t,n)=>e(t,n)})(),Ze=e=>({type:e.isFile()?`File`:e.isDirectory()?`Directory`:e.isSymbolicLink()?`SymbolicLink`:e.isBlockDevice()?`BlockDevice`:e.isCharacterDevice()?`CharacterDevice`:e.isFIFO()?`FIFO`:e.isSocket()?`Socket`:`Unknown`,mtime:p.fromNullable(e.mtime),atime:p.fromNullable(e.atime),birthtime:p.fromNullable(e.birthtime),dev:e.dev,rdev:p.fromNullable(e.rdev),ino:p.fromNullable(e.ino),mode:e.mode,nlink:p.fromNullable(e.nlink),uid:p.fromNullable(e.uid),gid:p.fromNullable(e.gid),size:_.Size(e.size),blksize:p.map(p.fromNullable(e.blksize),_.Size),blocks:p.fromNullable(e.blocks)}),Y=(()=>{let e=E(D.stat,V(`FileSystem`,`stat`),K(`stat`));return t=>d.map(e(t),Ze)})(),Qe=(()=>{let e=E(D.symlink,V(`FileSystem`,`symlink`),K(`symlink`));return(t,n)=>e(t,n)})(),$e=(()=>{let e=E(D.truncate,V(`FileSystem`,`truncate`),K(`truncate`));return(t,n)=>e(t,n===void 0?void 0:Number(n))})(),et=(()=>{let e=E(D.utimes,V(`FileSystem`,`utime`),K(`utime`));return(t,n,r)=>e(t,n,r)})(),tt=(e,t)=>x.asyncScoped(n=>d.acquireRelease(d.sync(()=>{let r=D.watch(e,{recursive:t?.recursive},(e,t)=>{if(t)switch(e){case`rename`:n.fromEffect(d.matchEffect(Y(t),{onSuccess:e=>d.succeed(_.WatchEventCreate({path:t})),onFailure:e=>e._tag===`SystemError`&&e.reason===`NotFound`?d.succeed(_.WatchEventRemove({path:t})):d.fail(e)}));return;case`change`:n.single(_.WatchEventUpdate({path:t}));return}});return r.on(`error`,t=>{n.fail(new C.SystemError({module:`FileSystem`,reason:`Unknown`,method:`watch`,pathOrDescriptor:e,cause:t}))}),r.on(`close`,()=>{n.end()}),r}),e=>d.sync(()=>e.close()))),nt=(e,t,n)=>Y(t).pipe(d.map(r=>e.pipe(p.flatMap(e=>e.register(t,r,n)),p.getOrElse(()=>tt(t,n)))),x.unwrap),rt=(e,t,n)=>d.async((r,i)=>{try{D.writeFile(e,t,{signal:i,flag:n?.flag,mode:n?.mode},t=>{r(t?d.fail(V(`FileSystem`,`writeFile`)(t,[e])):d.void)})}catch(e){r(d.fail(K(`writeFile`)(e)))}}),it=d.map(d.serviceOption(_.WatchBackend),e=>_.make({access:Ae,chmod:Ne,chown:Pe,copy:je,copyFile:Me,link:Fe,makeDirectory:Ie,makeTempDirectory:Le,makeTempDirectoryScoped:ze,makeTempFile:We,makeTempFileScoped:Ge,open:Ve,readDirectory:Ke,readFile:qe,readLink:Je,realPath:Ye,remove:Re,rename:Xe,stat:Y,symlink:Qe,truncate:$e,utimes:et,watch(t,n){return nt(e,t,n)},writeFile:rt})),at=f.effect(_.FileSystem,it),ot=e=>d.try({try:()=>j.fileURLToPath(e),catch:t=>new ae({module:`Path`,method:`fromFileUrl`,description:`Invalid file URL: ${e}`,cause:t})}),st=e=>d.try({try:()=>j.pathToFileURL(e),catch:t=>new ae({module:`Path`,method:`toFileUrl`,description:`Invalid path: ${e}`,cause:t})});({...O.posix}),{...O.win32};const ct=f.succeed(k,k.of({[A]:A,...O,fromFileUrl:ot,toFileUrl:st})),lt=e=>e.key.ctrl&&(e.key.name===`c`||e.key.name===`d`),ut=d.fnUntraced(function*(e=lt){let t=process.stdin,n=process.stdout,r=yield*N.make({acquire:d.acquireRelease(d.sync(()=>{let e=P.createInterface({input:t,escapeCodeTimeout:50});return P.emitKeypressEvents(t,e),t.isTTY&&t.setRawMode(!0),e}),e=>d.sync(()=>{t.isTTY&&t.setRawMode(!1),e.close()}))}),i=d.sync(()=>n.columns??0),a=d.gen(function*(){yield*N.get(r);let n=yield*he.make(),i=(t,r)=>{let i={input:p.fromNullable(t),key:{name:r.name??``,ctrl:!!r.ctrl,meta:!!r.meta,shift:!!r.shift}};n.unsafeOffer(i),e(i)&&n.unsafeDone(T.void)};return yield*d.addFinalizer(()=>d.sync(()=>t.off(`keypress`,i))),t.on(`keypress`,i),n}),o=N.get(r).pipe(d.flatMap(e=>d.async(t=>{let n=e=>t(d.succeed(e));return e.once(`line`,n),d.sync(()=>e.off(`line`,n))})),d.scoped);return M.Terminal.of({columns:i,readInput:a,readLine:o,display:e=>d.uninterruptible(d.async(t=>{n.write(e,e=>t(e?d.fail(new C.BadArgument({module:`Terminal`,method:`display`,description:`Failed to write prompt to stdout`,cause:e})):d.void))}))})}),dt=f.scoped(M.Terminal,ut(lt)),ft=F.makePlatform()({setup({scope:e,worker:t}){return d.flatMap(v.make(),n=>{let r=`postMessage`in t?{postMessage(e,n){t.postMessage(e,n)},kill:()=>t.terminate(),worker:t}:{postMessage(e,n){t.send(e)},kill:()=>t.kill(`SIGKILL`),worker:t};return t.on(`exit`,()=>{v.unsafeDone(n,T.void)}),d.as(ge.addFinalizer(e,d.suspend(()=>(r.postMessage([1]),v.await(n))).pipe(d.interruptible,d.timeout(5e3),d.catchAllCause(()=>d.sync(()=>r.kill())))),r)})},listen({deferred:e,emit:t,port:n}){return n.worker.on(`message`,e=>{t(e)}),n.worker.on(`messageerror`,t=>{v.unsafeDone(e,new I({reason:`decode`,cause:t}))}),n.worker.on(`error`,t=>{v.unsafeDone(e,new I({reason:`unknown`,cause:t}))}),n.worker.on(`exit`,t=>{v.unsafeDone(e,new I({reason:`unknown`,cause:Error(`exited with code ${t}`)}))}),d.void}}),pt=f.succeed(F.PlatformWorker,ft),mt=f.provide(F.layerManager,pt),ht=y(f.mergeAll(ct,ke,dt,mt),f.provideMerge(at)),gt=_e(({fiber:e,teardown:t})=>{let n=setInterval(te,2**31-1),r=!1;e.addObserver(e=>{r||(process.removeListener(`SIGINT`,i),process.removeListener(`SIGTERM`,i)),clearInterval(n),t(e,e=>{(r||e!==0)&&process.exit(e)})});function i(){r=!0,process.removeListener(`SIGINT`,i),process.removeListener(`SIGTERM`,i),e.unsafeInterruptAsFork(e.id())}process.on(`SIGINT`,i),process.on(`SIGTERM`,i)}),_t=Ce(()=>process.stdout,e=>new oe({module:`Stream`,method:`stdout`,reason:`Unknown`,cause:e})),vt=H(()=>process.stdin,e=>e,{closeOnDone:!1}).pipe(x.orDie);x.orDie,x.orDie;const X=m.Literal(`DRAFT`,`OPEN`,`COMPLETED`,`CLOSED`),yt=m.Literal(`TODO`,`BOARD`,`PROJECT`),Z=m.String.annotations({description:`ISO 8601 date string (e.g., 2025-01-20T10:00:00Z)`}),bt=B.make(`get_projects`,{description:`List all projects. Returns projectId, folderId, client, owner, dates, and budget info. Use to discover projects before drilling into tasks or logging time. Data hierarchy: FOLDER → PROJECT → TASK → ACTIVITY.`,parameters:{states:m.optional(m.Array(X)).annotations({description:`Filter by project states: DRAFT, OPEN, COMPLETED, CLOSED. Defaults to DRAFT, OPEN, CLOSED`}),limit:m.optional(m.Number).annotations({description:`Maximum number of projects to return. Defaults to 100`}),page:m.optional(m.Number).annotations({description:`Page number for pagination. Defaults to 1`})},success:m.Struct({projects:m.Array(s)}),failure:e,failureMode:`return`,dependencies:[l]}),xt=B.make(`get_project_details`,{description:`Get single project with full details including billing rates and folder info. Requires projectId from get_projects.`,parameters:{projectId:m.Number.annotations({description:`Project ID from get_projects response`})},success:m.Struct({project:s}),failure:e,failureMode:`return`,dependencies:[l]}),St=B.make(`get_messages`,{description:`Get comments/messages on a project, board, or todo. Use to read discussion history or context about work items.`,parameters:{objectType:yt.annotations({description:`Type of object: PROJECT (for project comments), BOARD (board-level), TODO (kanban card)`}),objectId:m.Number.annotations({description:`ID of the project, board, or todo`}),onlyComments:m.optional(m.Boolean).annotations({description:`Only return user comments (exclude system messages). Defaults to true`}),hideInternal:m.optional(m.Boolean).annotations({description:`Hide internal/private messages. Defaults to true`}),limit:m.optional(m.Number).annotations({description:`Maximum number of messages to return. Defaults to 100`})},success:m.Struct({messages:m.Array(r)}),failure:e,failureMode:`return`,dependencies:[l]}),Ct=B.make(`set_task_state`,{description:`Change task state. Typical flow: DRAFT → OPEN → COMPLETED → CLOSED. Requires both projectId and taskId from get_tasks.`,parameters:{projectId:m.Number.annotations({description:`Project ID containing the task (from get_projects)`}),taskId:m.Number.annotations({description:`Task ID to update (from get_tasks)`}),state:X.annotations({description:`New state: DRAFT, OPEN, COMPLETED, or CLOSED`})},success:m.Void,failure:e,failureMode:`return`,dependencies:[l]}),wt=B.make(`get_tasks`,{description:`Get tasks within a project. Tasks have budget (workload), remaining hours, and state. Use taskId when logging time to attribute work to specific deliverables.`,parameters:{projectId:m.Number.annotations({description:`Project ID from get_projects`}),states:m.optional(m.Array(X)).annotations({description:`Filter by task states: DRAFT, OPEN, COMPLETED, CLOSED. Defaults to DRAFT, OPEN, CLOSED`}),limit:m.optional(m.Number).annotations({description:`Maximum number of tasks to return. Defaults to 100`}),page:m.optional(m.Number).annotations({description:`Page number for pagination. Defaults to 1`})},success:m.Struct({tasks:m.Array(u)}),failure:e,failureMode:`return`,dependencies:[l]}),Tt=B.make(`get_tasks_for_user`,{description:`Get tasks assigned to a user for a date range. Returns tasks with REMAINING budget hours. Useful for finding what work is available to log time against.`,parameters:{contactId:m.String.annotations({description:`User/contact ID to get tasks for`}),startDate:Z.annotations({description:`Start date for the query (e.g., 2025-01-20T00:00:00Z)`}),period:m.Number.annotations({description:`Number of days to include in the query`})},success:m.Struct({tasks:m.Array(i)}),failure:e,failureMode:`return`,dependencies:[l]}),Et=B.make(`get_todo_detail`,{description:`Get kanban card details. Response includes: BOARDLISTS (all columns with IDs for move_todo), LINKS (connected tasks), ACTIVITIES (time logged against this todo).`,parameters:{id:m.Number.annotations({description:`Todo/card ID to retrieve`})},success:m.Struct({todo:a}),failure:e,failureMode:`return`,dependencies:[l]}),Dt=B.make(`move_todo`,{description:`Move kanban card between columns. Get boardId and boardListId from get_todo_detail response (BOARDLISTS array contains column IDs).`,parameters:{id:m.Number.annotations({description:`Todo/card ID to move`}),boardId:m.Number.annotations({description:`Board ID (from get_todo_detail)`}),boardListId:m.Number.annotations({description:`Target column ID (from BOARDLISTS in get_todo_detail)`}),sortIndex:m.Number.annotations({description:`Position within column (0 = top)`})},success:m.Void,failure:e,failureMode:`return`,dependencies:[l]}),Ot=B.make(`post_message`,{description:`Add a comment to a project, board, or todo. Use to leave notes or updates on work items.`,parameters:{objectType:yt.annotations({description:`Type of object: PROJECT, BOARD, or TODO`}),objectId:m.Number.annotations({description:`ID of the project, board, or todo to comment on`}),content:m.String.annotations({description:`Comment text to post`})},success:m.Void,failure:e,failureMode:`return`,dependencies:[l]}),kt=B.make(`get_week_activities`,{description:`Get all time entries for the week containing the given date. Returns project/task names, duration, and IDs. Use to review or summarize work. Response includes folderId which can be used for create_activity.`,parameters:{date:Z.annotations({description:`Any date within target week (e.g., 2025-01-20). Week is Mon-Sun.`}),contactId:m.String.annotations({description:`User/contact ID to get activities for`}),timezone:m.optional(m.String).annotations({description:`Timezone for week boundaries. Defaults to Europe/Amsterdam`})},success:m.Struct({activities:m.Array(t)}),failure:e,failureMode:`return`,dependencies:[o]}),At=B.make(`create_activity`,{description:`Log time against a project/task. Get folderId from get_projects or get_week_activities. Duration examples: 60=1h, 90=1.5h, 120=2h. Optionally link to a taskId for specific work attribution or todoId for kanban card.`,parameters:{folderId:m.String.annotations({description:`Folder/project ID to log time against (from get_projects or get_week_activities)`}),startDate:Z.annotations({description:`Date and time of the activity (e.g., 2025-01-20T09:00:00Z). Time is for display.`}),durationMinutes:m.Number.annotations({description:`Duration in minutes. Examples: 30, 60 (1h), 90 (1.5h), 120 (2h)`}),contactId:m.String.annotations({description:`User/contact ID who performed the work`}),taskId:m.optional(m.String).annotations({description:`Task ID to attribute time to (from get_tasks). Links time to specific deliverable.`}),todoId:m.optional(m.String).annotations({description:`Todo/kanban card ID to link this time entry to`}),description:m.optional(m.String).annotations({description:`Description of work performed`}),clientColor:m.optional(m.String).annotations({description:`Hex color code for display (e.g., #eeeeee)`})},success:m.Struct({id:m.Number.annotations({description:`ID of the created activity`})}),failure:e,failureMode:`return`,dependencies:[o]}),jt=B.make(`update_activity`,{description:`Modify an existing time entry. Get activity ID from get_week_activities. Only specify fields you want to change.`,parameters:{id:m.Number.annotations({description:`Activity ID to update (from get_week_activities)`}),startDate:m.optional(Z).annotations({description:`New date/time for the activity`}),durationMinutes:m.optional(m.Number).annotations({description:`New duration in minutes`}),description:m.optional(m.String).annotations({description:`New description`})},success:m.Void,failure:e,failureMode:`return`,dependencies:[o]}),Mt=B.make(`delete_activity`,{description:`Remove a time entry. Get activity ID from get_week_activities. This action cannot be undone.`,parameters:{id:m.Number.annotations({description:`Activity ID to delete (from get_week_activities)`})},success:m.Void,failure:e,failureMode:`return`,dependencies:[o]}),Nt=ve.make(bt,xt,St,wt,Tt,Et,Dt,Ot,Ct,kt,At,jt,Mt),Pt=[`DRAFT`,`OPEN`,`CLOSED`],Ft=Nt.toLayer({get_projects:d.fn(`TloToolkitHandlers.get_projects`)(function*(e){return{projects:yield*(yield*l).getProjects({...e,states:e.states??[...Pt],limit:e.limit??100,page:e.page??1})}}),get_project_details:d.fn(`TloToolkitHandlers.get_project_details`)(function*(e){return{project:yield*(yield*l).getProjectDetails(e)}}),get_messages:d.fn(`TloToolkitHandlers.get_messages`)(function*(e){return{messages:yield*(yield*l).getMessages({...e,onlyComments:e.onlyComments??!0,hideInternal:e.hideInternal??!0,limit:e.limit??100})}}),set_task_state:d.fn(`TloToolkitHandlers.set_task_state`)(function*(e){yield*(yield*l).setTaskState(e)}),get_tasks:d.fn(`TloToolkitHandlers.get_tasks`)(function*(e){return{tasks:yield*(yield*l).getTasks({...e,states:e.states??[...Pt],limit:e.limit??100,page:e.page??1})}}),get_tasks_for_user:d.fn(`TloToolkitHandlers.get_tasks_for_user`)(function*({startDate:e,...t}){return{tasks:yield*(yield*l).getTasksForUser({...t,startDate:new Date(e)})}}),get_todo_detail:d.fn(`TloToolkitHandlers.get_todo_detail`)(function*(e){return{todo:yield*(yield*l).getTodoDetail(e)}}),move_todo:d.fn(`TloToolkitHandlers.move_todo`)(function*(e){yield*(yield*l).moveTodo(e)}),post_message:d.fn(`TloToolkitHandlers.post_message`)(function*(e){yield*(yield*l).postMessage(e)}),get_week_activities:d.fn(`TloToolkitHandlers.get_week_activities`)(function*(e){let t=yield*o,n=new Date(e.date),r=e.timezone??`Europe/Amsterdam`;return{activities:yield*t.getWeek(n,e.contactId,r)}}),create_activity:d.fn(`TloToolkitHandlers.create_activity`)(function*({startDate:e,...t}){return{id:yield*(yield*o).createActivity({...t,startDate:new Date(e)})}}),update_activity:d.fn(`TloToolkitHandlers.update_activity`)(function*({startDate:e,...t}){yield*(yield*o).updateActivity({...t,startDate:e?new Date(e):void 0})}),delete_activity:d.fn(`TloToolkitHandlers.delete_activity`)(function*(e){yield*(yield*o).deleteActivity(e)})});function It(e){return R.toolkit(Nt).pipe(f.provide(Ft),f.provide(R.layerStdio({...e,stdin:vt,stdout:_t})),f.provide(z.add(z.prettyLogger({stderr:!0}))))}const Q=`tlo-mcp`,$=`0.0.0`,Lt=L.make(Q,{},d.fn(function*(){return yield*It({name:Q,version:$}).pipe(f.provide(c),f.provide(n),f.launch)}));L.run(Lt,{name:Q,version:$})(process.argv).pipe(d.provide(ht),gt);export{};
@@ -0,0 +1,738 @@
1
+ import * as Context from "effect/Context";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Layer from "effect/Layer";
4
+ import * as Redacted from "effect/Redacted";
5
+ import * as Schema from "effect/Schema";
6
+ import * as HttpClient from "@effect/platform/HttpClient";
7
+ import * as Brand from "effect/Brand";
8
+ import * as effect_ConfigError0 from "effect/ConfigError";
9
+
10
+ //#region src/services/TloConfig.d.ts
11
+ interface TloConfigShape {
12
+ readonly baseUrl: string;
13
+ readonly sessionToken: Redacted.Redacted;
14
+ readonly cookies: ReadonlyMap<string, string>;
15
+ }
16
+ declare const TloConfig_base: Context.TagClass<TloConfig, "@2digits/tlo-mcp/services/TloConfig", TloConfigShape>;
17
+ declare class TloConfig extends TloConfig_base {}
18
+ //#endregion
19
+ //#region src/schemas/errors.d.ts
20
+ declare const TloApiError_base: Schema.TaggedErrorClass<TloApiError, "TloApiError", {
21
+ readonly _tag: Schema.tag<"TloApiError">;
22
+ } & {
23
+ message: typeof Schema.String;
24
+ code: Schema.optional<typeof Schema.String>;
25
+ endpoint: Schema.optional<typeof Schema.String>;
26
+ }>;
27
+ /**
28
+ * Error returned when the TLO API indicates failure.
29
+ * This occurs when success: false in the response envelope.
30
+ */
31
+ declare class TloApiError extends TloApiError_base {}
32
+ declare const TloAuthError_base: Schema.TaggedErrorClass<TloAuthError, "TloAuthError", {
33
+ readonly _tag: Schema.tag<"TloAuthError">;
34
+ } & {
35
+ message: typeof Schema.String;
36
+ }>;
37
+ /**
38
+ * Error for authentication failures.
39
+ * Session token expired or invalid credentials.
40
+ */
41
+ declare class TloAuthError extends TloAuthError_base {}
42
+ declare const TloNetworkError_base: Schema.TaggedErrorClass<TloNetworkError, "TloNetworkError", {
43
+ readonly _tag: Schema.tag<"TloNetworkError">;
44
+ } & {
45
+ message: typeof Schema.String;
46
+ cause: Schema.optional<typeof Schema.Unknown>;
47
+ endpoint: Schema.optional<typeof Schema.String>;
48
+ }>;
49
+ /**
50
+ * Error for network/transport failures.
51
+ * Connection refused, timeout, etc.
52
+ */
53
+ declare class TloNetworkError extends TloNetworkError_base {}
54
+ declare const TloParseError_base: Schema.TaggedErrorClass<TloParseError, "TloParseError", {
55
+ readonly _tag: Schema.tag<"TloParseError">;
56
+ } & {
57
+ message: typeof Schema.String;
58
+ cause: Schema.optional<typeof Schema.Unknown>;
59
+ }>;
60
+ /**
61
+ * Error when response parsing fails.
62
+ * Unexpected response format from TLO.
63
+ */
64
+ declare class TloParseError extends TloParseError_base {}
65
+ type TloError = TloApiError | TloAuthError | TloNetworkError | TloParseError;
66
+ //#endregion
67
+ //#region src/services/TloHttpClient.d.ts
68
+ interface TloHttpClientShape {
69
+ readonly client: HttpClient.HttpClient;
70
+ }
71
+ declare const TloHttpClient_base: Context.TagClass<TloHttpClient, "@2digits/tlo-mcp/services/TloHttpClient", TloHttpClientShape>;
72
+ declare class TloHttpClient extends TloHttpClient_base {}
73
+ //#endregion
74
+ //#region src/services/TeamLeaderClient.d.ts
75
+ interface TeamLeaderClientShape {
76
+ readonly post: <TResponse, TInput, TEnv>(path: string, body: Record<string, string | number | boolean | undefined>, schema: Schema.Schema<TResponse, TInput, TEnv>) => Effect.Effect<TResponse, TloError, TEnv>;
77
+ }
78
+ declare const TeamLeaderClient_base: Context.TagClass<TeamLeaderClient, "@2digits/tlo-mcp/services/TeamLeaderClient", TeamLeaderClientShape>;
79
+ declare class TeamLeaderClient extends TeamLeaderClient_base {}
80
+ declare const TeamLeaderClientLive: Layer.Layer<TeamLeaderClient, never, TloConfig | TloHttpClient>;
81
+ //#endregion
82
+ //#region src/schemas/time.d.ts
83
+ /** Raw activity from TLO API response. Field names match the API exactly. */
84
+ declare const ActivityRaw: Schema.Struct<{
85
+ ID: typeof Schema.Number;
86
+ FOLDERID: Schema.optional<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>;
87
+ PROJECT_ID: Schema.optional<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>;
88
+ TASKID: Schema.optional<Schema.NullOr<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>>;
89
+ TODOID: Schema.optional<Schema.NullOr<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>>;
90
+ TICKETID: Schema.optional<Schema.NullOr<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>>;
91
+ CONTACTID: Schema.optional<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>;
92
+ DESCRIPTION: Schema.NullOr<typeof Schema.String>;
93
+ DT: typeof Schema.String;
94
+ START_DT: Schema.optional<typeof Schema.String>;
95
+ END_DT: Schema.optional<typeof Schema.String>;
96
+ DURATION: typeof Schema.Number;
97
+ TYPE: Schema.optional<typeof Schema.Number>;
98
+ PROJECT_NAME: Schema.optional<Schema.NullOr<typeof Schema.String>>;
99
+ TASK_NAME: Schema.optional<Schema.NullOr<typeof Schema.String>>;
100
+ CLIENT_NAME: Schema.optional<Schema.NullOr<typeof Schema.String>>;
101
+ FOLDER_NAME: Schema.optional<Schema.NullOr<typeof Schema.String>>;
102
+ ENTITY_NAME: Schema.optional<Schema.NullOr<typeof Schema.String>>;
103
+ PROJECTOWNER_NAME: Schema.optional<Schema.NullOr<typeof Schema.String>>;
104
+ CLIENT_COLOR: Schema.optional<Schema.NullOr<typeof Schema.String>>;
105
+ PROJECT_COLOR: Schema.optional<Schema.NullOr<typeof Schema.String>>;
106
+ PROJECT_STATE: Schema.optional<Schema.NullOr<typeof Schema.String>>;
107
+ TASK_STATE: Schema.optional<Schema.NullOr<typeof Schema.String>>;
108
+ TIMESHEET_STATE: Schema.optional<Schema.NullOr<typeof Schema.String>>;
109
+ BILLING_MODE: Schema.optional<Schema.NullOr<typeof Schema.String>>;
110
+ NON_BILLABLE: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
111
+ RATE: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
112
+ VALUE: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
113
+ PROJECT_START_DT: Schema.optional<Schema.NullOr<typeof Schema.String>>;
114
+ PROJECT_END_DT: Schema.optional<Schema.NullOr<typeof Schema.String>>;
115
+ TASK_START_DT: Schema.optional<Schema.NullOr<typeof Schema.String>>;
116
+ TASK_END_DT: Schema.optional<Schema.NullOr<typeof Schema.String>>;
117
+ READONLY: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
118
+ TASK_WORKLOAD: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
119
+ }>;
120
+ type ActivityRaw = typeof ActivityRaw.Type;
121
+ declare const Activity_base: Schema.Class<Activity, {
122
+ id: typeof Schema.Number;
123
+ projectId: Schema.optional<typeof Schema.String>;
124
+ folderId: Schema.optional<typeof Schema.String>;
125
+ taskId: Schema.optional<Schema.NullOr<typeof Schema.String>>;
126
+ todoId: Schema.optional<Schema.NullOr<typeof Schema.String>>;
127
+ ticketId: Schema.optional<Schema.NullOr<typeof Schema.String>>;
128
+ userId: Schema.optional<typeof Schema.String>;
129
+ description: Schema.NullOr<typeof Schema.String>;
130
+ startDate: typeof Schema.String;
131
+ endDate: Schema.optional<typeof Schema.String>;
132
+ durationMinutes: typeof Schema.Number;
133
+ projectName: Schema.optional<Schema.NullOr<typeof Schema.String>>;
134
+ taskName: Schema.optional<Schema.NullOr<typeof Schema.String>>;
135
+ clientName: Schema.optional<Schema.NullOr<typeof Schema.String>>;
136
+ folderName: Schema.optional<Schema.NullOr<typeof Schema.String>>;
137
+ entityName: Schema.optional<Schema.NullOr<typeof Schema.String>>;
138
+ projectOwnerName: Schema.optional<Schema.NullOr<typeof Schema.String>>;
139
+ projectState: Schema.optional<Schema.NullOr<typeof Schema.String>>;
140
+ taskState: Schema.optional<Schema.NullOr<typeof Schema.String>>;
141
+ timesheetState: Schema.optional<Schema.NullOr<typeof Schema.String>>;
142
+ billingMode: Schema.optional<Schema.NullOr<typeof Schema.String>>;
143
+ nonBillable: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
144
+ rate: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
145
+ value: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
146
+ projectStartDate: Schema.optional<Schema.NullOr<typeof Schema.String>>;
147
+ projectEndDate: Schema.optional<Schema.NullOr<typeof Schema.String>>;
148
+ taskStartDate: Schema.optional<Schema.NullOr<typeof Schema.String>>;
149
+ taskEndDate: Schema.optional<Schema.NullOr<typeof Schema.String>>;
150
+ readOnly: Schema.optional<Schema.NullOr<typeof Schema.Boolean>>;
151
+ taskWorkload: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
152
+ projectColor: Schema.optional<typeof Schema.String>;
153
+ clientColor: Schema.optional<typeof Schema.String>;
154
+ }, Schema.Struct.Encoded<{
155
+ id: typeof Schema.Number;
156
+ projectId: Schema.optional<typeof Schema.String>;
157
+ folderId: Schema.optional<typeof Schema.String>;
158
+ taskId: Schema.optional<Schema.NullOr<typeof Schema.String>>;
159
+ todoId: Schema.optional<Schema.NullOr<typeof Schema.String>>;
160
+ ticketId: Schema.optional<Schema.NullOr<typeof Schema.String>>;
161
+ userId: Schema.optional<typeof Schema.String>;
162
+ description: Schema.NullOr<typeof Schema.String>;
163
+ startDate: typeof Schema.String;
164
+ endDate: Schema.optional<typeof Schema.String>;
165
+ durationMinutes: typeof Schema.Number;
166
+ projectName: Schema.optional<Schema.NullOr<typeof Schema.String>>;
167
+ taskName: Schema.optional<Schema.NullOr<typeof Schema.String>>;
168
+ clientName: Schema.optional<Schema.NullOr<typeof Schema.String>>;
169
+ folderName: Schema.optional<Schema.NullOr<typeof Schema.String>>;
170
+ entityName: Schema.optional<Schema.NullOr<typeof Schema.String>>;
171
+ projectOwnerName: Schema.optional<Schema.NullOr<typeof Schema.String>>;
172
+ projectState: Schema.optional<Schema.NullOr<typeof Schema.String>>;
173
+ taskState: Schema.optional<Schema.NullOr<typeof Schema.String>>;
174
+ timesheetState: Schema.optional<Schema.NullOr<typeof Schema.String>>;
175
+ billingMode: Schema.optional<Schema.NullOr<typeof Schema.String>>;
176
+ nonBillable: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
177
+ rate: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
178
+ value: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
179
+ projectStartDate: Schema.optional<Schema.NullOr<typeof Schema.String>>;
180
+ projectEndDate: Schema.optional<Schema.NullOr<typeof Schema.String>>;
181
+ taskStartDate: Schema.optional<Schema.NullOr<typeof Schema.String>>;
182
+ taskEndDate: Schema.optional<Schema.NullOr<typeof Schema.String>>;
183
+ readOnly: Schema.optional<Schema.NullOr<typeof Schema.Boolean>>;
184
+ taskWorkload: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
185
+ projectColor: Schema.optional<typeof Schema.String>;
186
+ clientColor: Schema.optional<typeof Schema.String>;
187
+ }>, never, {
188
+ readonly description: string | null;
189
+ } & {
190
+ readonly id: number;
191
+ } & {
192
+ readonly startDate: string;
193
+ } & {
194
+ readonly durationMinutes: number;
195
+ } & {
196
+ readonly projectId?: string | undefined;
197
+ } & {
198
+ readonly folderId?: string | undefined;
199
+ } & {
200
+ readonly taskId?: string | null | undefined;
201
+ } & {
202
+ readonly todoId?: string | null | undefined;
203
+ } & {
204
+ readonly ticketId?: string | null | undefined;
205
+ } & {
206
+ readonly userId?: string | undefined;
207
+ } & {
208
+ readonly endDate?: string | undefined;
209
+ } & {
210
+ readonly projectName?: string | null | undefined;
211
+ } & {
212
+ readonly taskName?: string | null | undefined;
213
+ } & {
214
+ readonly clientName?: string | null | undefined;
215
+ } & {
216
+ readonly folderName?: string | null | undefined;
217
+ } & {
218
+ readonly entityName?: string | null | undefined;
219
+ } & {
220
+ readonly projectOwnerName?: string | null | undefined;
221
+ } & {
222
+ readonly projectState?: string | null | undefined;
223
+ } & {
224
+ readonly taskState?: string | null | undefined;
225
+ } & {
226
+ readonly timesheetState?: string | null | undefined;
227
+ } & {
228
+ readonly billingMode?: string | null | undefined;
229
+ } & {
230
+ readonly nonBillable?: number | null | undefined;
231
+ } & {
232
+ readonly rate?: number | null | undefined;
233
+ } & {
234
+ readonly value?: number | null | undefined;
235
+ } & {
236
+ readonly projectStartDate?: string | null | undefined;
237
+ } & {
238
+ readonly projectEndDate?: string | null | undefined;
239
+ } & {
240
+ readonly taskStartDate?: string | null | undefined;
241
+ } & {
242
+ readonly taskEndDate?: string | null | undefined;
243
+ } & {
244
+ readonly readOnly?: boolean | null | undefined;
245
+ } & {
246
+ readonly taskWorkload?: number | null | undefined;
247
+ } & {
248
+ readonly projectColor?: string | undefined;
249
+ } & {
250
+ readonly clientColor?: string | undefined;
251
+ }, {}, {}>;
252
+ declare class Activity extends Activity_base {}
253
+ declare function activityFromRaw(raw: ActivityRaw): typeof Activity.Type;
254
+ declare const GetWeekResponse: Schema.Struct<{
255
+ ACTIVITIES: Schema.Array$<Schema.Struct<{
256
+ ID: typeof Schema.Number;
257
+ FOLDERID: Schema.optional<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>;
258
+ PROJECT_ID: Schema.optional<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>;
259
+ TASKID: Schema.optional<Schema.NullOr<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>>;
260
+ TODOID: Schema.optional<Schema.NullOr<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>>;
261
+ TICKETID: Schema.optional<Schema.NullOr<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>>;
262
+ CONTACTID: Schema.optional<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>;
263
+ DESCRIPTION: Schema.NullOr<typeof Schema.String>;
264
+ DT: typeof Schema.String;
265
+ START_DT: Schema.optional<typeof Schema.String>;
266
+ END_DT: Schema.optional<typeof Schema.String>;
267
+ DURATION: typeof Schema.Number;
268
+ TYPE: Schema.optional<typeof Schema.Number>;
269
+ PROJECT_NAME: Schema.optional<Schema.NullOr<typeof Schema.String>>;
270
+ TASK_NAME: Schema.optional<Schema.NullOr<typeof Schema.String>>;
271
+ CLIENT_NAME: Schema.optional<Schema.NullOr<typeof Schema.String>>;
272
+ FOLDER_NAME: Schema.optional<Schema.NullOr<typeof Schema.String>>;
273
+ ENTITY_NAME: Schema.optional<Schema.NullOr<typeof Schema.String>>;
274
+ PROJECTOWNER_NAME: Schema.optional<Schema.NullOr<typeof Schema.String>>;
275
+ CLIENT_COLOR: Schema.optional<Schema.NullOr<typeof Schema.String>>;
276
+ PROJECT_COLOR: Schema.optional<Schema.NullOr<typeof Schema.String>>;
277
+ PROJECT_STATE: Schema.optional<Schema.NullOr<typeof Schema.String>>;
278
+ TASK_STATE: Schema.optional<Schema.NullOr<typeof Schema.String>>;
279
+ TIMESHEET_STATE: Schema.optional<Schema.NullOr<typeof Schema.String>>;
280
+ BILLING_MODE: Schema.optional<Schema.NullOr<typeof Schema.String>>;
281
+ NON_BILLABLE: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
282
+ RATE: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
283
+ VALUE: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
284
+ PROJECT_START_DT: Schema.optional<Schema.NullOr<typeof Schema.String>>;
285
+ PROJECT_END_DT: Schema.optional<Schema.NullOr<typeof Schema.String>>;
286
+ TASK_START_DT: Schema.optional<Schema.NullOr<typeof Schema.String>>;
287
+ TASK_END_DT: Schema.optional<Schema.NullOr<typeof Schema.String>>;
288
+ READONLY: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
289
+ TASK_WORKLOAD: Schema.optional<Schema.NullOr<typeof Schema.Number>>;
290
+ }>>;
291
+ }>;
292
+ type GetWeekResponse = typeof GetWeekResponse.Type;
293
+ declare const SetActivityResponse: Schema.Struct<{
294
+ ID: typeof Schema.Number;
295
+ DURATION: Schema.optional<typeof Schema.Number>;
296
+ DT: Schema.optional<typeof Schema.String>;
297
+ TYPE: Schema.optional<typeof Schema.Number>;
298
+ DESCRIPTION: Schema.optional<Schema.NullOr<typeof Schema.String>>;
299
+ CLIENT_COLOR: Schema.optional<typeof Schema.String>;
300
+ FOLDERID: Schema.optional<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>;
301
+ }>;
302
+ type SetActivityResponse = typeof SetActivityResponse.Type;
303
+ interface CreateActivityParams {
304
+ readonly folderId: string;
305
+ readonly taskId?: string;
306
+ readonly todoId?: string;
307
+ readonly startDate: Date;
308
+ readonly durationMinutes: number;
309
+ readonly description?: string;
310
+ readonly contactId: string;
311
+ readonly clientColor?: string;
312
+ }
313
+ interface UpdateActivityParams {
314
+ readonly id: number;
315
+ readonly startDate?: Date;
316
+ readonly durationMinutes?: number;
317
+ readonly description?: string;
318
+ }
319
+ interface DeleteActivityParams {
320
+ readonly id: number;
321
+ }
322
+ //#endregion
323
+ //#region src/services/TimeService.d.ts
324
+ interface TimeServiceShape {
325
+ readonly getWeek: (date: Date, contactId: string, timezone?: string) => Effect.Effect<ReadonlyArray<typeof Activity.Type>, TloError>;
326
+ readonly createActivity: (params: CreateActivityParams) => Effect.Effect<number, TloError>;
327
+ readonly updateActivity: (params: UpdateActivityParams) => Effect.Effect<void, TloError>;
328
+ readonly deleteActivity: (params: DeleteActivityParams) => Effect.Effect<void, TloError>;
329
+ }
330
+ declare const TimeService_base: Context.TagClass<TimeService, "@2digits/tlo-mcp/services/TimeService", TimeServiceShape>;
331
+ declare class TimeService extends TimeService_base {}
332
+ declare const TimeServiceLive: Layer.Layer<TimeService, never, TeamLeaderClient>;
333
+ //#endregion
334
+ //#region src/schemas/board.d.ts
335
+ declare const ProjectRaw: Schema.Struct<{
336
+ ID: typeof Schema.Number;
337
+ PROJECT_NAME: Schema.optional<typeof Schema.String>;
338
+ NAME: Schema.optional<typeof Schema.String>;
339
+ STATE: Schema.optional<typeof Schema.String>;
340
+ OWNER_NAME: Schema.optional<typeof Schema.String>;
341
+ START_DT: Schema.optional<typeof Schema.String>;
342
+ END_DT: Schema.optional<typeof Schema.String>;
343
+ BILLING_BUDGET: Schema.optional<typeof Schema.Number>;
344
+ BILLING_MODE: Schema.optional<typeof Schema.String>;
345
+ BILLING_REMAINING: Schema.optional<typeof Schema.Number>;
346
+ CLIENT_NAME: Schema.optional<typeof Schema.String>;
347
+ CLIENT_ID: Schema.optional<typeof Schema.Number>;
348
+ FOLDERID: Schema.optional<typeof Schema.Number>;
349
+ FOLDER_NAME: Schema.optional<typeof Schema.String>;
350
+ EXTID: Schema.optional<typeof Schema.String>;
351
+ CALC_TOTAL: Schema.optional<typeof Schema.Number>;
352
+ CALC_DONE: Schema.optional<typeof Schema.Number>;
353
+ CALC_PLANNED: Schema.optional<typeof Schema.Number>;
354
+ }>;
355
+ type ProjectRaw = typeof ProjectRaw.Type;
356
+ declare const Project_base: Schema.Class<Project, {
357
+ id: typeof Schema.Number;
358
+ name: typeof Schema.String;
359
+ state: Schema.optional<typeof Schema.String>;
360
+ ownerName: Schema.optional<typeof Schema.String>;
361
+ startDate: Schema.optional<typeof Schema.String>;
362
+ endDate: Schema.optional<typeof Schema.String>;
363
+ billingBudget: Schema.optional<typeof Schema.Number>;
364
+ billingMode: Schema.optional<typeof Schema.String>;
365
+ billingRemaining: Schema.optional<typeof Schema.Number>;
366
+ clientName: Schema.optional<typeof Schema.String>;
367
+ clientId: Schema.optional<typeof Schema.Number>;
368
+ folderId: Schema.optional<typeof Schema.Number>;
369
+ folderName: Schema.optional<typeof Schema.String>;
370
+ extId: Schema.optional<typeof Schema.String>;
371
+ calcTotal: Schema.optional<typeof Schema.Number>;
372
+ calcDone: Schema.optional<typeof Schema.Number>;
373
+ calcPlanned: Schema.optional<typeof Schema.Number>;
374
+ }, Schema.Struct.Encoded<{
375
+ id: typeof Schema.Number;
376
+ name: typeof Schema.String;
377
+ state: Schema.optional<typeof Schema.String>;
378
+ ownerName: Schema.optional<typeof Schema.String>;
379
+ startDate: Schema.optional<typeof Schema.String>;
380
+ endDate: Schema.optional<typeof Schema.String>;
381
+ billingBudget: Schema.optional<typeof Schema.Number>;
382
+ billingMode: Schema.optional<typeof Schema.String>;
383
+ billingRemaining: Schema.optional<typeof Schema.Number>;
384
+ clientName: Schema.optional<typeof Schema.String>;
385
+ clientId: Schema.optional<typeof Schema.Number>;
386
+ folderId: Schema.optional<typeof Schema.Number>;
387
+ folderName: Schema.optional<typeof Schema.String>;
388
+ extId: Schema.optional<typeof Schema.String>;
389
+ calcTotal: Schema.optional<typeof Schema.Number>;
390
+ calcDone: Schema.optional<typeof Schema.Number>;
391
+ calcPlanned: Schema.optional<typeof Schema.Number>;
392
+ }>, never, {
393
+ readonly id: number;
394
+ } & {
395
+ readonly startDate?: string | undefined;
396
+ } & {
397
+ readonly folderId?: number | undefined;
398
+ } & {
399
+ readonly endDate?: string | undefined;
400
+ } & {
401
+ readonly clientName?: string | undefined;
402
+ } & {
403
+ readonly folderName?: string | undefined;
404
+ } & {
405
+ readonly billingMode?: string | undefined;
406
+ } & {
407
+ readonly name: string;
408
+ } & {
409
+ readonly state?: string | undefined;
410
+ } & {
411
+ readonly ownerName?: string | undefined;
412
+ } & {
413
+ readonly billingBudget?: number | undefined;
414
+ } & {
415
+ readonly billingRemaining?: number | undefined;
416
+ } & {
417
+ readonly clientId?: number | undefined;
418
+ } & {
419
+ readonly extId?: string | undefined;
420
+ } & {
421
+ readonly calcTotal?: number | undefined;
422
+ } & {
423
+ readonly calcDone?: number | undefined;
424
+ } & {
425
+ readonly calcPlanned?: number | undefined;
426
+ }, {}, {}>;
427
+ declare class Project extends Project_base {}
428
+ declare function projectFromRaw(raw: ProjectRaw): Project;
429
+ declare const MessageRaw: Schema.Struct<{
430
+ ID: typeof Schema.Number;
431
+ OWNERID: Schema.optional<typeof Schema.Number>;
432
+ OWNER_NAME: Schema.optional<typeof Schema.String>;
433
+ AVATAR: Schema.optional<typeof Schema.String>;
434
+ CREATED_DT: Schema.optional<typeof Schema.String>;
435
+ CONTENT: Schema.optional<typeof Schema.String>;
436
+ SUBCONTENT: Schema.optional<typeof Schema.String>;
437
+ OBJECTTYPE: Schema.optional<typeof Schema.String>;
438
+ OBJECTID: Schema.optional<typeof Schema.Number>;
439
+ OBJECTNAME: Schema.optional<typeof Schema.String>;
440
+ MSGTYPE: Schema.optional<typeof Schema.String>;
441
+ LIKECNT: Schema.optional<typeof Schema.Number>;
442
+ REPLYCNT: Schema.optional<typeof Schema.Number>;
443
+ OUTQUEUEID: Schema.optional<typeof Schema.String>;
444
+ INTERNAL: Schema.optional<typeof Schema.Number>;
445
+ }>;
446
+ type MessageRaw = typeof MessageRaw.Type;
447
+ declare const Message_base: Schema.Class<Message, {
448
+ id: typeof Schema.Number;
449
+ ownerId: Schema.optional<typeof Schema.Number>;
450
+ ownerName: Schema.optional<typeof Schema.String>;
451
+ avatar: Schema.optional<typeof Schema.String>;
452
+ createdAt: Schema.optional<typeof Schema.String>;
453
+ content: Schema.optional<typeof Schema.String>;
454
+ subcontent: Schema.optional<typeof Schema.String>;
455
+ objectType: Schema.optional<typeof Schema.String>;
456
+ objectId: Schema.optional<typeof Schema.Number>;
457
+ objectName: Schema.optional<typeof Schema.String>;
458
+ messageType: Schema.optional<typeof Schema.String>;
459
+ likeCount: Schema.optional<typeof Schema.Number>;
460
+ replyCount: Schema.optional<typeof Schema.Number>;
461
+ outQueueId: Schema.optional<typeof Schema.String>;
462
+ internal: Schema.optional<typeof Schema.Boolean>;
463
+ }, Schema.Struct.Encoded<{
464
+ id: typeof Schema.Number;
465
+ ownerId: Schema.optional<typeof Schema.Number>;
466
+ ownerName: Schema.optional<typeof Schema.String>;
467
+ avatar: Schema.optional<typeof Schema.String>;
468
+ createdAt: Schema.optional<typeof Schema.String>;
469
+ content: Schema.optional<typeof Schema.String>;
470
+ subcontent: Schema.optional<typeof Schema.String>;
471
+ objectType: Schema.optional<typeof Schema.String>;
472
+ objectId: Schema.optional<typeof Schema.Number>;
473
+ objectName: Schema.optional<typeof Schema.String>;
474
+ messageType: Schema.optional<typeof Schema.String>;
475
+ likeCount: Schema.optional<typeof Schema.Number>;
476
+ replyCount: Schema.optional<typeof Schema.Number>;
477
+ outQueueId: Schema.optional<typeof Schema.String>;
478
+ internal: Schema.optional<typeof Schema.Boolean>;
479
+ }>, never, {
480
+ readonly id: number;
481
+ } & {
482
+ readonly ownerName?: string | undefined;
483
+ } & {
484
+ readonly ownerId?: number | undefined;
485
+ } & {
486
+ readonly avatar?: string | undefined;
487
+ } & {
488
+ readonly createdAt?: string | undefined;
489
+ } & {
490
+ readonly content?: string | undefined;
491
+ } & {
492
+ readonly subcontent?: string | undefined;
493
+ } & {
494
+ readonly objectType?: string | undefined;
495
+ } & {
496
+ readonly objectId?: number | undefined;
497
+ } & {
498
+ readonly objectName?: string | undefined;
499
+ } & {
500
+ readonly messageType?: string | undefined;
501
+ } & {
502
+ readonly likeCount?: number | undefined;
503
+ } & {
504
+ readonly replyCount?: number | undefined;
505
+ } & {
506
+ readonly outQueueId?: string | undefined;
507
+ } & {
508
+ readonly internal?: boolean | undefined;
509
+ }, {}, {}>;
510
+ declare class Message extends Message_base {}
511
+ declare function messageFromRaw(raw: MessageRaw): typeof Message.Type;
512
+ type TaskState = 'OPEN' | 'COMPLETED' | 'DRAFT' | 'CLOSED';
513
+ declare const TaskRaw: Schema.Struct<{
514
+ ID: typeof Schema.Number;
515
+ PROJECTID: Schema.optional<typeof Schema.Number>;
516
+ NAME: Schema.optional<typeof Schema.String>;
517
+ STATE: Schema.optional<typeof Schema.String>;
518
+ OWNER_NAME: Schema.optional<typeof Schema.String>;
519
+ START_DT: Schema.optional<typeof Schema.String>;
520
+ END_DT: Schema.optional<typeof Schema.String>;
521
+ BUDGET: Schema.optional<typeof Schema.Number>;
522
+ }>;
523
+ type TaskRaw = typeof TaskRaw.Type;
524
+ declare const Task_base: Schema.Class<Task, {
525
+ id: typeof Schema.Number;
526
+ projectId: Schema.optional<typeof Schema.Number>;
527
+ name: Schema.optional<typeof Schema.String>;
528
+ state: Schema.optional<typeof Schema.String>;
529
+ ownerName: Schema.optional<typeof Schema.String>;
530
+ startDate: Schema.optional<typeof Schema.String>;
531
+ endDate: Schema.optional<typeof Schema.String>;
532
+ budget: Schema.optional<typeof Schema.Number>;
533
+ }, Schema.Struct.Encoded<{
534
+ id: typeof Schema.Number;
535
+ projectId: Schema.optional<typeof Schema.Number>;
536
+ name: Schema.optional<typeof Schema.String>;
537
+ state: Schema.optional<typeof Schema.String>;
538
+ ownerName: Schema.optional<typeof Schema.String>;
539
+ startDate: Schema.optional<typeof Schema.String>;
540
+ endDate: Schema.optional<typeof Schema.String>;
541
+ budget: Schema.optional<typeof Schema.Number>;
542
+ }>, never, {
543
+ readonly id: number;
544
+ } & {
545
+ readonly startDate?: string | undefined;
546
+ } & {
547
+ readonly projectId?: number | undefined;
548
+ } & {
549
+ readonly endDate?: string | undefined;
550
+ } & {
551
+ readonly name?: string | undefined;
552
+ } & {
553
+ readonly state?: string | undefined;
554
+ } & {
555
+ readonly ownerName?: string | undefined;
556
+ } & {
557
+ readonly budget?: number | undefined;
558
+ }, {}, {}>;
559
+ declare class Task extends Task_base {}
560
+ interface SetTaskStateParams {
561
+ readonly projectId: number;
562
+ readonly taskId: number;
563
+ readonly state: TaskState;
564
+ }
565
+ interface GetMessagesParams {
566
+ readonly objectType: 'TODO' | 'BOARD' | 'PROJECT';
567
+ readonly objectId: number;
568
+ readonly onlyComments?: boolean;
569
+ readonly hideInternal?: boolean;
570
+ readonly limit?: number;
571
+ }
572
+ interface GetProjectsParams {
573
+ readonly states?: ReadonlyArray<TaskState>;
574
+ readonly limit?: number;
575
+ readonly page?: number;
576
+ }
577
+ declare const TaskForUserRaw: Schema.Struct<{
578
+ ID: typeof Schema.Number;
579
+ WORKLOAD: Schema.optional<typeof Schema.Number>;
580
+ TOTAL: Schema.optional<typeof Schema.Number>;
581
+ REMAINING: Schema.optional<typeof Schema.Number>;
582
+ AVAIL: Schema.optional<typeof Schema.Number>;
583
+ CLIENTID: Schema.optional<typeof Schema.Number>;
584
+ PROJECTID: Schema.optional<typeof Schema.Number>;
585
+ PROJECT_START_DT: Schema.optional<typeof Schema.String>;
586
+ PROJECT_END_DT: Schema.optional<typeof Schema.String>;
587
+ START_DT: Schema.optional<typeof Schema.String>;
588
+ END_DT: Schema.optional<typeof Schema.String>;
589
+ STATE: Schema.optional<typeof Schema.String>;
590
+ }>;
591
+ type TaskForUserRaw = typeof TaskForUserRaw.Type;
592
+ declare const TaskForUser_base: Schema.Class<TaskForUser, {
593
+ id: typeof Schema.Number;
594
+ workload: Schema.optional<typeof Schema.Number>;
595
+ total: Schema.optional<typeof Schema.Number>;
596
+ remaining: Schema.optional<typeof Schema.Number>;
597
+ avail: Schema.optional<typeof Schema.Number>;
598
+ clientId: Schema.optional<typeof Schema.Number>;
599
+ projectId: Schema.optional<typeof Schema.Number>;
600
+ projectStartDate: Schema.optional<typeof Schema.String>;
601
+ projectEndDate: Schema.optional<typeof Schema.String>;
602
+ startDate: Schema.optional<typeof Schema.String>;
603
+ endDate: Schema.optional<typeof Schema.String>;
604
+ state: Schema.optional<typeof Schema.String>;
605
+ }, Schema.Struct.Encoded<{
606
+ id: typeof Schema.Number;
607
+ workload: Schema.optional<typeof Schema.Number>;
608
+ total: Schema.optional<typeof Schema.Number>;
609
+ remaining: Schema.optional<typeof Schema.Number>;
610
+ avail: Schema.optional<typeof Schema.Number>;
611
+ clientId: Schema.optional<typeof Schema.Number>;
612
+ projectId: Schema.optional<typeof Schema.Number>;
613
+ projectStartDate: Schema.optional<typeof Schema.String>;
614
+ projectEndDate: Schema.optional<typeof Schema.String>;
615
+ startDate: Schema.optional<typeof Schema.String>;
616
+ endDate: Schema.optional<typeof Schema.String>;
617
+ state: Schema.optional<typeof Schema.String>;
618
+ }>, never, {
619
+ readonly id: number;
620
+ } & {
621
+ readonly startDate?: string | undefined;
622
+ } & {
623
+ readonly projectId?: number | undefined;
624
+ } & {
625
+ readonly endDate?: string | undefined;
626
+ } & {
627
+ readonly projectStartDate?: string | undefined;
628
+ } & {
629
+ readonly projectEndDate?: string | undefined;
630
+ } & {
631
+ readonly state?: string | undefined;
632
+ } & {
633
+ readonly clientId?: number | undefined;
634
+ } & {
635
+ readonly workload?: number | undefined;
636
+ } & {
637
+ readonly total?: number | undefined;
638
+ } & {
639
+ readonly remaining?: number | undefined;
640
+ } & {
641
+ readonly avail?: number | undefined;
642
+ }, {}, {}>;
643
+ declare class TaskForUser extends TaskForUser_base {}
644
+ declare const TodoDetail: Schema.Record$<typeof Schema.String, typeof Schema.Unknown>;
645
+ type TodoDetail = typeof TodoDetail.Type;
646
+ interface GetTasksParams {
647
+ readonly projectId: number;
648
+ readonly states?: ReadonlyArray<TaskState>;
649
+ readonly limit?: number;
650
+ readonly page?: number;
651
+ }
652
+ interface GetProjectDetailsParams {
653
+ readonly projectId: number;
654
+ }
655
+ interface GetTasksForUserParams {
656
+ readonly contactId: string;
657
+ readonly startDate: Date;
658
+ readonly period: number;
659
+ }
660
+ interface GetTodoDetailParams {
661
+ readonly id: number;
662
+ }
663
+ interface MoveTodoParams {
664
+ readonly id: number;
665
+ readonly boardId: number;
666
+ readonly boardListId: number;
667
+ readonly sortIndex: number;
668
+ }
669
+ interface PostMessageParams {
670
+ readonly objectType: 'TODO' | 'BOARD' | 'PROJECT';
671
+ readonly objectId: number;
672
+ readonly content: string;
673
+ }
674
+ //#endregion
675
+ //#region src/services/BoardService.d.ts
676
+ interface BoardServiceShape {
677
+ readonly getProjects: (params?: GetProjectsParams) => Effect.Effect<ReadonlyArray<typeof Project.Type>, TloError>;
678
+ readonly getProjectDetails: (params: GetProjectDetailsParams) => Effect.Effect<typeof Project.Type, TloError>;
679
+ readonly getMessages: (params: GetMessagesParams) => Effect.Effect<ReadonlyArray<typeof Message.Type>, TloError>;
680
+ readonly getTasks: (params: GetTasksParams) => Effect.Effect<ReadonlyArray<typeof Task.Type>, TloError>;
681
+ readonly getTasksForUser: (params: GetTasksForUserParams) => Effect.Effect<ReadonlyArray<typeof TaskForUser.Type>, TloError>;
682
+ readonly getTodoDetail: (params: GetTodoDetailParams) => Effect.Effect<TodoDetail, TloError>;
683
+ readonly moveTodo: (params: MoveTodoParams) => Effect.Effect<void, TloError>;
684
+ readonly postMessage: (params: PostMessageParams) => Effect.Effect<void, TloError>;
685
+ readonly setTaskState: (params: SetTaskStateParams) => Effect.Effect<void, TloError>;
686
+ }
687
+ declare const BoardService_base: Context.TagClass<BoardService, "@2digits/tlo-mcp/services/BoardService", BoardServiceShape>;
688
+ declare class BoardService extends BoardService_base {}
689
+ declare const BoardServiceLive: Layer.Layer<BoardService, never, TeamLeaderClient>;
690
+ //#endregion
691
+ //#region src/layers/TloConfigLive.d.ts
692
+ declare const TloConfigFromEnv: Effect.Effect<{
693
+ baseUrl: string;
694
+ sessionToken: Redacted.Redacted<string>;
695
+ cookies: ReadonlyMap<string, string>;
696
+ }, effect_ConfigError0.ConfigError, never>;
697
+ declare const TloConfigLive: Layer.Layer<TloConfig, effect_ConfigError0.ConfigError, never>;
698
+ //#endregion
699
+ //#region src/layers/TloLive.d.ts
700
+ declare const TloServicesLive: Layer.Layer<TimeService | BoardService, never, TeamLeaderClient>;
701
+ declare const TloClientLive: Layer.Layer<TeamLeaderClient, never, TloConfig>;
702
+ declare const TloLive: Layer.Layer<TimeService | BoardService, never, TloConfig>;
703
+ //#endregion
704
+ //#region src/schemas/common.d.ts
705
+ /**
706
+ * TeamLeader Orbit uses YYYYMMDDHHMMSS format for dates.
707
+ * Example: "20251117143000" = Nov 17, 2025 14:30:00
708
+ */
709
+ declare const TloDateString: Schema.brand<Schema.filter<typeof Schema.String>, "TloDateString">;
710
+ type TloDateString = typeof TloDateString.Type;
711
+ /**
712
+ * Format Date to YYYYMMDDHHMMSS string.
713
+ */
714
+ declare function formatTloDate(d: Date): TloDateString;
715
+ /**
716
+ * Transform between TLO date strings and JavaScript Date objects.
717
+ */
718
+ declare const TloDate: Schema.transform<Schema.brand<Schema.filter<typeof Schema.String>, "TloDateString">, typeof Schema.DateFromSelf>;
719
+ type TloDate = typeof TloDate.Type;
720
+ /**
721
+ * TLO entity IDs are numeric strings.
722
+ */
723
+ type TloId = string & Brand.Brand<'TloId'>;
724
+ declare const TloId: Brand.Brand.Constructor<TloId>;
725
+ declare const TloIdSchema: Schema.BrandSchema<string & Brand.Brand<"TloId">, string, never>;
726
+ /**
727
+ * Standard TLO API response envelope schema.
728
+ * Note: Most endpoints return data directly without this wrapper.
729
+ * Kept for potential use with endpoints that do use the envelope pattern.
730
+ */
731
+ declare function TloResponse<$A, $I, $R>(dataSchema: Schema.Schema<$A, $I, $R>): Schema.Struct<{
732
+ success: typeof Schema.Boolean;
733
+ ID: Schema.optional<typeof Schema.Number>;
734
+ OBJ: Schema.Schema<$A, $I, $R>;
735
+ err: Schema.optional<typeof Schema.String>;
736
+ }>;
737
+ //#endregion
738
+ export { Activity, type ActivityRaw, BoardService, BoardServiceLive, type BoardServiceShape, type CreateActivityParams, type DeleteActivityParams, type GetMessagesParams, type GetProjectDetailsParams, type GetProjectsParams, type GetTasksForUserParams, type GetTodoDetailParams, type GetWeekResponse, Message, type MessageRaw, type MoveTodoParams, type PostMessageParams, Project, type ProjectRaw, type SetActivityResponse, type SetTaskStateParams, Task, TaskForUser, type TaskForUserRaw, type TaskRaw, type TaskState, TeamLeaderClient, TeamLeaderClientLive, type TeamLeaderClientShape, TimeService, TimeServiceLive, type TimeServiceShape, TloApiError, TloAuthError, TloClientLive, TloConfig, TloConfigFromEnv, TloConfigLive, type TloConfigShape, TloDate, TloDateString, type TloError, TloId, TloIdSchema, TloLive, TloNetworkError, TloParseError, TloResponse, TloServicesLive, TodoDetail, type UpdateActivityParams, activityFromRaw, formatTloDate, messageFromRaw, projectFromRaw };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ import{E as e,S as t,T as n,_ as r,a as i,b as a,c as o,d as s,f as c,g as l,h as u,i as d,l as f,m as p,n as m,o as h,p as g,r as _,s as v,t as y,u as b,v as x,w as S,x as C,y as w}from"./TloLive-19PJ2qwv.mjs";import*as T from"effect/Schema";import*as E from"effect/Brand";const D=T.String.pipe(T.pattern(/^\d{14}$/),T.brand(`TloDateString`));function O(e){let t=Number.parseInt(e.slice(0,4),10),n=Number.parseInt(e.slice(4,6),10)-1,r=Number.parseInt(e.slice(6,8),10),i=Number.parseInt(e.slice(8,10),10),a=Number.parseInt(e.slice(10,12),10),o=Number.parseInt(e.slice(12,14),10);return new Date(t,n,r,i,a,o)}function k(e){return`${e.getFullYear().toString().padStart(4,`0`)}${(e.getMonth()+1).toString().padStart(2,`0`)}${e.getDate().toString().padStart(2,`0`)}${e.getHours().toString().padStart(2,`0`)}${e.getMinutes().toString().padStart(2,`0`)}${e.getSeconds().toString().padStart(2,`0`)}`}const A=T.transform(D,T.DateFromSelf,{strict:!0,decode:O,encode:k}),j=E.nominal(),M=T.String.pipe(T.fromBrand(j));function N(e){return T.Struct({success:T.Boolean,ID:T.optional(T.Number),OBJ:e,err:T.optional(T.String)})}export{r as Activity,h as BoardService,v as BoardServiceLive,o as Message,f as Project,b as Task,s as TaskForUser,w as TeamLeaderClient,a as TeamLeaderClientLive,u as TimeService,l as TimeServiceLive,C as TloApiError,t as TloAuthError,y as TloClientLive,e as TloConfig,d as TloConfigFromEnv,i as TloConfigLive,A as TloDate,D as TloDateString,j as TloId,M as TloIdSchema,m as TloLive,S as TloNetworkError,n as TloParseError,N as TloResponse,_ as TloServicesLive,c as TodoDetail,x as activityFromRaw,k as formatTloDate,g as messageFromRaw,p as projectFromRaw};
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@2digits/tlo-mcp",
3
+ "version": "0.0.0",
4
+ "public": true,
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/2digits-agency/configs.git",
8
+ "directory": "packages/tlo-mcp"
9
+ },
10
+ "type": "module",
11
+ "types": "./dist/index.d.mts",
12
+ "bin": {
13
+ "tlo-mcp": "./dist/bin.mjs"
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "exports": {
19
+ ".": "./dist/index.mjs",
20
+ "./bin": "./dist/bin.mjs",
21
+ "./package.json": "./package.json"
22
+ },
23
+ "sideEffects": false,
24
+ "scripts": {
25
+ "prepare": "effect-language-service patch",
26
+ "build": "tsdown --minify --config-loader unconfig",
27
+ "dev": "tsdown --watch --config-loader unconfig",
28
+ "test": "vitest run",
29
+ "test:watch": "vitest",
30
+ "types": "tsc --noEmit"
31
+ },
32
+ "license": "MIT",
33
+ "dependencies": {
34
+ "@effect/ai": "catalog:",
35
+ "@effect/cli": "catalog:",
36
+ "@effect/experimental": "catalog:",
37
+ "@effect/platform": "catalog:",
38
+ "@effect/rpc": "catalog:",
39
+ "effect": "catalog:"
40
+ },
41
+ "devDependencies": {
42
+ "@2digits/tsconfig": "workspace:*",
43
+ "@arethetypeswrong/core": "catalog:",
44
+ "@effect/language-service": "catalog:",
45
+ "@effect/platform-node": "catalog:",
46
+ "@effect/vitest": "catalog:",
47
+ "publint": "catalog:",
48
+ "tsdown": "catalog:",
49
+ "typescript": "catalog:",
50
+ "vitest": "catalog:"
51
+ }
52
+ }