@locusai/sdk 0.4.6 → 0.4.10

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.
Files changed (58) hide show
  1. package/dist/agent/worker.js +1271 -239
  2. package/dist/index-node.js +1601 -20
  3. package/dist/index.js +429 -121
  4. package/dist/orchestrator.d.ts.map +1 -1
  5. package/package.json +7 -19
  6. package/dist/agent/artifact-syncer.js +0 -77
  7. package/dist/agent/codebase-indexer-service.js +0 -55
  8. package/dist/agent/index.js +0 -5
  9. package/dist/agent/sprint-planner.js +0 -68
  10. package/dist/agent/task-executor.js +0 -60
  11. package/dist/ai/anthropic-client.js +0 -70
  12. package/dist/ai/claude-runner.js +0 -71
  13. package/dist/ai/index.js +0 -2
  14. package/dist/core/config.js +0 -15
  15. package/dist/core/index.js +0 -3
  16. package/dist/core/indexer.js +0 -113
  17. package/dist/core/prompt-builder.js +0 -83
  18. package/dist/events.js +0 -15
  19. package/dist/modules/auth.js +0 -23
  20. package/dist/modules/base.js +0 -8
  21. package/dist/modules/ci.js +0 -7
  22. package/dist/modules/docs.js +0 -38
  23. package/dist/modules/invitations.js +0 -22
  24. package/dist/modules/organizations.js +0 -39
  25. package/dist/modules/sprints.js +0 -34
  26. package/dist/modules/tasks.js +0 -56
  27. package/dist/modules/workspaces.js +0 -49
  28. package/dist/orchestrator.js +0 -356
  29. package/dist/utils/colors.js +0 -54
  30. package/dist/utils/retry.js +0 -37
  31. package/src/agent/artifact-syncer.ts +0 -111
  32. package/src/agent/codebase-indexer-service.ts +0 -71
  33. package/src/agent/index.ts +0 -5
  34. package/src/agent/sprint-planner.ts +0 -86
  35. package/src/agent/task-executor.ts +0 -85
  36. package/src/agent/worker.ts +0 -322
  37. package/src/ai/anthropic-client.ts +0 -93
  38. package/src/ai/claude-runner.ts +0 -86
  39. package/src/ai/index.ts +0 -2
  40. package/src/core/config.ts +0 -21
  41. package/src/core/index.ts +0 -3
  42. package/src/core/indexer.ts +0 -131
  43. package/src/core/prompt-builder.ts +0 -91
  44. package/src/events.ts +0 -35
  45. package/src/index-node.ts +0 -23
  46. package/src/index.ts +0 -159
  47. package/src/modules/auth.ts +0 -48
  48. package/src/modules/base.ts +0 -9
  49. package/src/modules/ci.ts +0 -12
  50. package/src/modules/docs.ts +0 -84
  51. package/src/modules/invitations.ts +0 -45
  52. package/src/modules/organizations.ts +0 -90
  53. package/src/modules/sprints.ts +0 -69
  54. package/src/modules/tasks.ts +0 -110
  55. package/src/modules/workspaces.ts +0 -94
  56. package/src/orchestrator.ts +0 -473
  57. package/src/utils/colors.ts +0 -63
  58. package/src/utils/retry.ts +0 -56
@@ -1,91 +0,0 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import { AssigneeRole, Task } from "@locusai/shared";
3
- import { getLocusPath } from "./config.js";
4
-
5
- export class PromptBuilder {
6
- constructor(private projectPath: string) {}
7
-
8
- async build(task: Task): Promise<string> {
9
- let prompt = `# Task: ${task.title}\n\n`;
10
-
11
- const roleText = this.roleToText(task.assigneeRole);
12
- if (roleText) {
13
- prompt += `## Role\nYou are acting as a ${roleText}.\n\n`;
14
- }
15
-
16
- prompt += `## Description\n${task.description || "No description provided."}\n\n`;
17
-
18
- // 1. Add CLAUDE.md context
19
- const contextPath = getLocusPath(this.projectPath, "contextFile");
20
- if (existsSync(contextPath)) {
21
- try {
22
- const context = readFileSync(contextPath, "utf-8");
23
- prompt += `## Project Context (from CLAUDE.md)\n${context}\n\n`;
24
- } catch (err) {
25
- console.warn(`Warning: Could not read context file: ${err}`);
26
- }
27
- }
28
-
29
- // 2. Add Codebase Index context
30
- const indexPath = getLocusPath(this.projectPath, "indexFile");
31
- if (existsSync(indexPath)) {
32
- prompt += `## Codebase Overview\nThere is an index file in the .locus/codebase-index.json and if you need you can check it.\n\n`;
33
- }
34
-
35
- // 3. Add Documents
36
- if (task.docs && task.docs.length > 0) {
37
- prompt += `## Attached Documents\n`;
38
- for (const doc of task.docs) {
39
- prompt += `### ${doc.title}\n${doc.content || "(No content)"}\n\n`;
40
- }
41
- }
42
-
43
- // 4. Add Checklist
44
- if (task.acceptanceChecklist && task.acceptanceChecklist.length > 0) {
45
- prompt += `## Acceptance Criteria\n`;
46
- for (const item of task.acceptanceChecklist) {
47
- prompt += `- ${item.done ? "[x]" : "[ ]"} ${item.text}\n`;
48
- }
49
- prompt += "\n";
50
- }
51
-
52
- // 5. Add Comments & Feedback
53
- if (task.comments && task.comments.length > 0) {
54
- const comments = task.comments.slice(0, 5);
55
- prompt += `## Task History & Feedback\n`;
56
- prompt += `Review the following comments for context or rejection feedback:\n\n`;
57
- for (const comment of comments) {
58
- const date = new Date(comment.createdAt).toLocaleString();
59
- prompt += `### ${comment.author} (${date})\n${comment.text}\n\n`;
60
- }
61
- }
62
-
63
- prompt += `## Instructions
64
- 1. Complete this task.
65
- 2. **Artifact Management**: If you create any high-level documentation (PRDs, technical drafts, architecture docs), you MUST save them in \`.locus/artifacts/\`. Do NOT create them in the root directory.
66
- 3. **Paths**: Use relative paths from the project root at all times. Do NOT use absolute local paths (e.g., /Users/...).
67
- 4. When finished successfully, output: <promise>COMPLETE</promise>\n`;
68
- return prompt;
69
- }
70
-
71
- roleToText(role: Task["assigneeRole"]): string | null {
72
- if (!role) {
73
- return null;
74
- }
75
-
76
- switch (role) {
77
- case AssigneeRole.BACKEND:
78
- return "Backend Engineer";
79
- case AssigneeRole.FRONTEND:
80
- return "Frontend Engineer";
81
- case AssigneeRole.PM:
82
- return "Product Manager";
83
- case AssigneeRole.QA:
84
- return "QA Engineer";
85
- case AssigneeRole.DESIGN:
86
- return "Product Designer";
87
- default:
88
- return "engineer";
89
- }
90
- }
91
- }
package/src/events.ts DELETED
@@ -1,35 +0,0 @@
1
- import { EventEmitter } from "events";
2
-
3
- import { RetryOptions } from "./utils/retry.js";
4
-
5
- export enum LocusEvent {
6
- TOKEN_EXPIRED = "TOKEN_EXPIRED",
7
- AUTH_ERROR = "AUTH_ERROR",
8
- REQUEST_ERROR = "REQUEST_ERROR",
9
- }
10
-
11
- export interface LocusConfig {
12
- baseUrl: string;
13
- token?: string | null;
14
- timeout?: number;
15
- retryOptions?: RetryOptions;
16
- }
17
-
18
- export class LocusEmitter extends EventEmitter {
19
- on(event: LocusEvent.TOKEN_EXPIRED, listener: () => void): this;
20
- on(event: LocusEvent.AUTH_ERROR, listener: (error: Error) => void): this;
21
- on(event: LocusEvent.REQUEST_ERROR, listener: (error: Error) => void): this;
22
- on(
23
- event: LocusEvent | string,
24
- listener: ((...args: unknown[]) => void) | (() => void)
25
- ): this {
26
- return super.on(event, listener);
27
- }
28
-
29
- emit(event: LocusEvent.TOKEN_EXPIRED): boolean;
30
- emit(event: LocusEvent.AUTH_ERROR, error: Error): boolean;
31
- emit(event: LocusEvent.REQUEST_ERROR, error: Error): boolean;
32
- emit(event: LocusEvent | string, ...args: unknown[]): boolean {
33
- return super.emit(event, ...args);
34
- }
35
- }
package/src/index-node.ts DELETED
@@ -1,23 +0,0 @@
1
- /**
2
- * Node.js-only exports
3
- * This is a separate entry point for Node.js/CLI only
4
- * It should NOT be imported by browser applications
5
- *
6
- * These modules use Node.js APIs (fs, child_process, etc.)
7
- * and will break in browser environments
8
- */
9
-
10
- // Node.js-only: Agent system
11
- export * from "./agent/index.js";
12
- // Node.js-only: AI clients
13
- export * from "./ai/index.js";
14
- // Node.js-only: Core utilities (uses fs)
15
- export * from "./core/index.js";
16
- // Re-export everything from main index (browser-safe)
17
- export * from "./index.js";
18
-
19
- // Node.js-only: Orchestrator
20
- export { AgentOrchestrator, type OrchestratorConfig } from "./orchestrator.js";
21
-
22
- // Utilities
23
- export { c } from "./utils/colors.js";
package/src/index.ts DELETED
@@ -1,159 +0,0 @@
1
- import axios, { AxiosInstance, InternalAxiosRequestConfig } from "axios";
2
- import { LocusConfig, LocusEmitter, LocusEvent } from "./events.js";
3
- import { AuthModule } from "./modules/auth.js";
4
- import { CiModule } from "./modules/ci.js";
5
- import { DocsModule } from "./modules/docs.js";
6
- import { InvitationsModule } from "./modules/invitations.js";
7
- import { OrganizationsModule } from "./modules/organizations.js";
8
- import { SprintsModule } from "./modules/sprints.js";
9
- import { TasksModule } from "./modules/tasks.js";
10
- import { WorkspacesModule } from "./modules/workspaces.js";
11
- import { RetryOptions } from "./utils/retry.js";
12
-
13
- // Browser-safe exports only
14
- export * from "./events.js";
15
- export * from "./modules/auth.js";
16
- export * from "./modules/ci.js";
17
- export * from "./modules/docs.js";
18
- export * from "./modules/invitations.js";
19
- export * from "./modules/organizations.js";
20
- export * from "./modules/sprints.js";
21
- export * from "./modules/tasks.js";
22
- export * from "./modules/workspaces.js";
23
-
24
- export class LocusClient {
25
- private readonly api: AxiosInstance;
26
- public readonly emitter: LocusEmitter;
27
-
28
- public readonly auth: AuthModule;
29
- public readonly tasks: TasksModule;
30
- public readonly sprints: SprintsModule;
31
- public readonly workspaces: WorkspacesModule;
32
- public readonly organizations: OrganizationsModule;
33
- public readonly invitations: InvitationsModule;
34
- public readonly docs: DocsModule;
35
- public readonly ci: CiModule;
36
-
37
- constructor(config: LocusConfig) {
38
- this.emitter = new LocusEmitter();
39
-
40
- this.api = axios.create({
41
- baseURL: config.baseUrl,
42
- timeout: config.timeout || 10000,
43
- headers: {
44
- "Content-Type": "application/json",
45
- ...(config.token ? { Authorization: `Bearer ${config.token}` } : {}),
46
- },
47
- });
48
-
49
- this.setupInterceptors();
50
-
51
- // Initialize modules
52
- this.auth = new AuthModule(this.api, this.emitter);
53
- this.tasks = new TasksModule(this.api, this.emitter);
54
- this.sprints = new SprintsModule(this.api, this.emitter);
55
- this.workspaces = new WorkspacesModule(this.api, this.emitter);
56
- this.organizations = new OrganizationsModule(this.api, this.emitter);
57
- this.invitations = new InvitationsModule(this.api, this.emitter);
58
- this.docs = new DocsModule(this.api, this.emitter);
59
- this.ci = new CiModule(this.api, this.emitter);
60
-
61
- if (config.retryOptions) {
62
- this.setupRetryInterceptor(config.retryOptions);
63
- }
64
- }
65
-
66
- private setupRetryInterceptor(retryOptions: RetryOptions) {
67
- this.api.interceptors.response.use(undefined, async (error) => {
68
- const config = error.config as InternalAxiosRequestConfig & {
69
- _retryCount?: number;
70
- };
71
-
72
- if (!config || !retryOptions) {
73
- return Promise.reject(error);
74
- }
75
-
76
- config._retryCount = config._retryCount || 0;
77
-
78
- const maxRetries = retryOptions.maxRetries ?? 3;
79
- const shouldRetry =
80
- config._retryCount < maxRetries &&
81
- (retryOptions.retryCondition
82
- ? retryOptions.retryCondition(error)
83
- : !error.response || error.response.status >= 500);
84
-
85
- if (shouldRetry) {
86
- config._retryCount++;
87
- const delay = Math.min(
88
- (retryOptions.initialDelay ?? 1000) *
89
- Math.pow(retryOptions.factor ?? 2, config._retryCount - 1),
90
- retryOptions.maxDelay ?? 5000
91
- );
92
-
93
- await new Promise((resolve) => setTimeout(resolve, delay));
94
- return this.api(config);
95
- }
96
-
97
- return Promise.reject(error);
98
- });
99
- }
100
-
101
- private setupInterceptors() {
102
- this.api.interceptors.response.use(
103
- (response) => {
104
- if (
105
- response.data &&
106
- typeof response.data === "object" &&
107
- "data" in response.data
108
- ) {
109
- response.data = response.data.data;
110
- }
111
- return response;
112
- },
113
- (error) => {
114
- const status = error.response?.status;
115
-
116
- // Extract error message from API response format: { error: { message: "..." } }
117
- let message: string;
118
-
119
- // Try to get message from API error response
120
- if (
121
- error.response?.data?.error?.message &&
122
- typeof error.response.data.error.message === "string"
123
- ) {
124
- message = error.response.data.error.message;
125
- } else if (
126
- error.response?.data?.message &&
127
- typeof error.response.data.message === "string"
128
- ) {
129
- message = error.response.data.message;
130
- } else if (error.message && typeof error.message === "string") {
131
- message = error.message;
132
- } else {
133
- message = "An error occurred";
134
- }
135
-
136
- // Create a new error with a meaningful message
137
- const enhancedError = new Error(message);
138
- enhancedError.name = `HTTP${status || "Error"}`;
139
-
140
- if (status === 401) {
141
- this.emitter.emit(LocusEvent.TOKEN_EXPIRED);
142
- this.emitter.emit(LocusEvent.AUTH_ERROR, enhancedError);
143
- } else {
144
- this.emitter.emit(LocusEvent.REQUEST_ERROR, enhancedError);
145
- }
146
-
147
- return Promise.reject(enhancedError);
148
- }
149
- );
150
- }
151
-
152
- public setToken(token: string | null) {
153
- if (token) {
154
- this.api.defaults.headers.common.Authorization = `Bearer ${token}`;
155
- } else {
156
- delete this.api.defaults.headers.common.Authorization;
157
- }
158
- }
159
- }
@@ -1,48 +0,0 @@
1
- import {
2
- CompleteRegistration,
3
- LoginResponse,
4
- User,
5
- VerifyOtp,
6
- } from "@locusai/shared";
7
- import { BaseModule } from "./base.js";
8
-
9
- export class AuthModule extends BaseModule {
10
- async getMe(): Promise<User> {
11
- const { data } = await this.api.get<User>("/auth/me");
12
- return data;
13
- }
14
-
15
- async requestRegisterOtp(email: string): Promise<{ success: boolean }> {
16
- const { data } = await this.api.post<{ success: boolean }>(
17
- "/auth/register-otp",
18
- { email }
19
- );
20
- return data;
21
- }
22
-
23
- async requestLoginOtp(email: string): Promise<{ success: boolean }> {
24
- const { data } = await this.api.post<{ success: boolean }>(
25
- "/auth/login-otp",
26
- { email }
27
- );
28
- return data;
29
- }
30
-
31
- async verifyLogin(body: VerifyOtp): Promise<LoginResponse> {
32
- const { data } = await this.api.post<LoginResponse>(
33
- "/auth/verify-login",
34
- body
35
- );
36
- return data;
37
- }
38
-
39
- async completeRegistration(
40
- body: CompleteRegistration
41
- ): Promise<LoginResponse> {
42
- const { data } = await this.api.post<LoginResponse>(
43
- "/auth/complete-registration",
44
- body
45
- );
46
- return data;
47
- }
48
- }
@@ -1,9 +0,0 @@
1
- import { AxiosInstance } from "axios";
2
- import { LocusEmitter } from "../events.js";
3
-
4
- export abstract class BaseModule {
5
- constructor(
6
- protected readonly api: AxiosInstance,
7
- protected readonly emitter: LocusEmitter
8
- ) {}
9
- }
package/src/modules/ci.ts DELETED
@@ -1,12 +0,0 @@
1
- import { ReportCiResult } from "@locusai/shared";
2
- import { BaseModule } from "./base.js";
3
-
4
- export class CiModule extends BaseModule {
5
- async report(body: ReportCiResult): Promise<{ success: boolean }> {
6
- const { data } = await this.api.post<{ success: boolean }>(
7
- "/ci/report",
8
- body
9
- );
10
- return data;
11
- }
12
- }
@@ -1,84 +0,0 @@
1
- import {
2
- CreateDoc,
3
- CreateDocGroup,
4
- Doc,
5
- DocGroup,
6
- DocGroupResponse,
7
- DocGroupsResponse,
8
- DocResponse,
9
- DocsResponse,
10
- UpdateDoc,
11
- UpdateDocGroup,
12
- } from "@locusai/shared";
13
- import { BaseModule } from "./base.js";
14
-
15
- export class DocsModule extends BaseModule {
16
- async create(workspaceId: string, body: CreateDoc): Promise<Doc> {
17
- const { data } = await this.api.post<DocResponse>(
18
- `/workspaces/${workspaceId}/docs`,
19
- body
20
- );
21
- return data.doc;
22
- }
23
-
24
- async list(workspaceId: string): Promise<Doc[]> {
25
- const { data } = await this.api.get<DocsResponse>(
26
- `/workspaces/${workspaceId}/docs`
27
- );
28
- return data.docs;
29
- }
30
-
31
- async getById(id: string, workspaceId: string): Promise<Doc> {
32
- const { data } = await this.api.get<DocResponse>(
33
- `/workspaces/${workspaceId}/docs/${id}`
34
- );
35
- return data.doc;
36
- }
37
-
38
- async update(id: string, workspaceId: string, body: UpdateDoc): Promise<Doc> {
39
- const { data } = await this.api.put<DocResponse>(
40
- `/workspaces/${workspaceId}/docs/${id}`,
41
- body
42
- );
43
- return data.doc;
44
- }
45
-
46
- async delete(id: string, workspaceId: string): Promise<void> {
47
- await this.api.delete(`/workspaces/${workspaceId}/docs/${id}`);
48
- }
49
-
50
- // Group Management
51
- async listGroups(workspaceId: string): Promise<DocGroup[]> {
52
- const { data } = await this.api.get<DocGroupsResponse>(
53
- `/workspaces/${workspaceId}/doc-groups`
54
- );
55
- return data.groups;
56
- }
57
-
58
- async createGroup(
59
- workspaceId: string,
60
- body: CreateDocGroup
61
- ): Promise<DocGroup> {
62
- const { data } = await this.api.post<DocGroupResponse>(
63
- `/workspaces/${workspaceId}/doc-groups`,
64
- body
65
- );
66
- return data.group;
67
- }
68
-
69
- async updateGroup(
70
- id: string,
71
- workspaceId: string,
72
- body: UpdateDocGroup
73
- ): Promise<DocGroup> {
74
- const { data } = await this.api.patch<DocGroupResponse>(
75
- `/workspaces/${workspaceId}/doc-groups/${id}`,
76
- body
77
- );
78
- return data.group;
79
- }
80
-
81
- async deleteGroup(id: string, workspaceId: string): Promise<void> {
82
- await this.api.delete(`/workspaces/${workspaceId}/doc-groups/${id}`);
83
- }
84
- }
@@ -1,45 +0,0 @@
1
- import {
2
- AcceptInvitation,
3
- AcceptInvitationResponse,
4
- CreateInvitation,
5
- Invitation,
6
- InvitationResponse,
7
- InvitationsResponse,
8
- } from "@locusai/shared";
9
- import { BaseModule } from "./base.js";
10
-
11
- export class InvitationsModule extends BaseModule {
12
- async create(orgId: string, body: CreateInvitation): Promise<Invitation> {
13
- const { data } = await this.api.post<InvitationResponse>(
14
- `/org/${orgId}/invitations`,
15
- body
16
- );
17
- return data.invitation;
18
- }
19
-
20
- async list(orgId: string): Promise<Invitation[]> {
21
- const { data } = await this.api.get<InvitationsResponse>(
22
- `/org/${orgId}/invitations`
23
- );
24
- return data.invitations;
25
- }
26
-
27
- async verify(token: string): Promise<InvitationResponse> {
28
- const { data } = await this.api.get<InvitationResponse>(
29
- `/invitations/verify/${token}`
30
- );
31
- return data;
32
- }
33
-
34
- async accept(body: AcceptInvitation): Promise<AcceptInvitationResponse> {
35
- const { data } = await this.api.post<AcceptInvitationResponse>(
36
- "/invitations/accept",
37
- body
38
- );
39
- return data;
40
- }
41
-
42
- async revoke(orgId: string, id: string): Promise<void> {
43
- await this.api.delete(`/org/${orgId}/invitations/${id}`);
44
- }
45
- }
@@ -1,90 +0,0 @@
1
- import {
2
- AddMember,
3
- MembershipResponse,
4
- MembershipWithUser,
5
- MembersResponse,
6
- Organization,
7
- OrganizationResponse,
8
- OrganizationsResponse,
9
- } from "@locusai/shared";
10
- import { BaseModule } from "./base.js";
11
-
12
- export interface ApiKey {
13
- id: string;
14
- organizationId: string;
15
- name: string;
16
- key: string;
17
- active: boolean;
18
- lastUsedAt: string | null;
19
- createdAt: string;
20
- updatedAt: string;
21
- }
22
-
23
- interface ApiKeysResponse {
24
- apiKeys: ApiKey[];
25
- }
26
-
27
- interface ApiKeyResponse {
28
- apiKey: ApiKey;
29
- }
30
-
31
- export class OrganizationsModule extends BaseModule {
32
- async list(): Promise<Organization[]> {
33
- const { data } =
34
- await this.api.get<OrganizationsResponse>("/organizations");
35
- return data.organizations;
36
- }
37
-
38
- async getById(id: string): Promise<Organization> {
39
- const { data } = await this.api.get<OrganizationResponse>(
40
- `/organizations/${id}`
41
- );
42
- return data.organization;
43
- }
44
-
45
- async listMembers(id: string): Promise<MembershipWithUser[]> {
46
- const { data } = await this.api.get<MembersResponse>(
47
- `/organizations/${id}/members`
48
- );
49
- return data.members;
50
- }
51
-
52
- async addMember(id: string, body: AddMember): Promise<MembershipWithUser> {
53
- const { data } = await this.api.post<MembershipResponse>(
54
- `/organizations/${id}/members`,
55
- body
56
- );
57
- return data.membership;
58
- }
59
-
60
- async removeMember(orgId: string, userId: string): Promise<void> {
61
- await this.api.delete(`/organizations/${orgId}/members/${userId}`);
62
- }
63
-
64
- async delete(orgId: string): Promise<void> {
65
- await this.api.delete(`/organizations/${orgId}`);
66
- }
67
-
68
- // ============================================================================
69
- // API Key Management
70
- // ============================================================================
71
-
72
- async listApiKeys(orgId: string): Promise<ApiKey[]> {
73
- const { data } = await this.api.get<ApiKeysResponse>(
74
- `/organizations/${orgId}/api-keys`
75
- );
76
- return data.apiKeys;
77
- }
78
-
79
- async createApiKey(orgId: string, name: string): Promise<ApiKey> {
80
- const { data } = await this.api.post<ApiKeyResponse>(
81
- `/organizations/${orgId}/api-keys`,
82
- { name }
83
- );
84
- return data.apiKey;
85
- }
86
-
87
- async deleteApiKey(orgId: string, keyId: string): Promise<void> {
88
- await this.api.delete(`/organizations/${orgId}/api-keys/${keyId}`);
89
- }
90
- }
@@ -1,69 +0,0 @@
1
- import {
2
- CreateSprint,
3
- Sprint,
4
- SprintResponse,
5
- SprintsResponse,
6
- UpdateSprint,
7
- } from "@locusai/shared";
8
- import { BaseModule } from "./base.js";
9
-
10
- export class SprintsModule extends BaseModule {
11
- async list(workspaceId: string): Promise<Sprint[]> {
12
- const { data } = await this.api.get<SprintsResponse>(
13
- `/workspaces/${workspaceId}/sprints`
14
- );
15
- return data.sprints;
16
- }
17
-
18
- async getActive(workspaceId: string): Promise<Sprint> {
19
- const { data } = await this.api.get<SprintResponse>(
20
- `/workspaces/${workspaceId}/sprints/active`
21
- );
22
- return data.sprint;
23
- }
24
-
25
- async getById(id: string, workspaceId: string): Promise<Sprint> {
26
- const { data } = await this.api.get<SprintResponse>(
27
- `/workspaces/${workspaceId}/sprints/${id}`
28
- );
29
- return data.sprint;
30
- }
31
-
32
- async create(workspaceId: string, body: CreateSprint): Promise<Sprint> {
33
- const { data } = await this.api.post<SprintResponse>(
34
- `/workspaces/${workspaceId}/sprints`,
35
- body
36
- );
37
- return data.sprint;
38
- }
39
-
40
- async update(
41
- id: string,
42
- workspaceId: string,
43
- body: UpdateSprint
44
- ): Promise<Sprint> {
45
- const { data } = await this.api.patch<SprintResponse>(
46
- `/workspaces/${workspaceId}/sprints/${id}`,
47
- body
48
- );
49
- return data.sprint;
50
- }
51
-
52
- async delete(id: string, workspaceId: string): Promise<void> {
53
- await this.api.delete(`/workspaces/${workspaceId}/sprints/${id}`);
54
- }
55
-
56
- async start(id: string, workspaceId: string): Promise<Sprint> {
57
- const { data } = await this.api.post<SprintResponse>(
58
- `/workspaces/${workspaceId}/sprints/${id}/start`
59
- );
60
- return data.sprint;
61
- }
62
-
63
- async complete(id: string, workspaceId: string): Promise<Sprint> {
64
- const { data } = await this.api.post<SprintResponse>(
65
- `/workspaces/${workspaceId}/sprints/${id}/complete`
66
- );
67
- return data.sprint;
68
- }
69
- }