@locusai/sdk 0.4.5 → 0.4.9
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/dist/index-node.js +1590 -20
- package/dist/index.js +429 -121
- package/dist/orchestrator.d.ts.map +1 -1
- package/package.json +12 -23
- package/dist/agent/artifact-syncer.js +0 -77
- package/dist/agent/codebase-indexer-service.js +0 -55
- package/dist/agent/index.js +0 -5
- package/dist/agent/sprint-planner.js +0 -68
- package/dist/agent/task-executor.js +0 -60
- package/dist/agent/worker.js +0 -252
- package/dist/ai/anthropic-client.js +0 -70
- package/dist/ai/claude-runner.js +0 -71
- package/dist/ai/index.js +0 -2
- package/dist/core/config.js +0 -15
- package/dist/core/index.js +0 -3
- package/dist/core/indexer.js +0 -113
- package/dist/core/prompt-builder.js +0 -83
- package/dist/events.js +0 -15
- package/dist/modules/auth.js +0 -23
- package/dist/modules/base.js +0 -8
- package/dist/modules/ci.js +0 -7
- package/dist/modules/docs.js +0 -38
- package/dist/modules/invitations.js +0 -22
- package/dist/modules/organizations.js +0 -39
- package/dist/modules/sprints.js +0 -34
- package/dist/modules/tasks.js +0 -56
- package/dist/modules/workspaces.js +0 -49
- package/dist/orchestrator.js +0 -356
- package/dist/utils/colors.js +0 -54
- package/dist/utils/retry.js +0 -37
- package/src/agent/artifact-syncer.ts +0 -111
- package/src/agent/codebase-indexer-service.ts +0 -71
- package/src/agent/index.ts +0 -5
- package/src/agent/sprint-planner.ts +0 -86
- package/src/agent/task-executor.ts +0 -85
- package/src/agent/worker.ts +0 -322
- package/src/ai/anthropic-client.ts +0 -93
- package/src/ai/claude-runner.ts +0 -86
- package/src/ai/index.ts +0 -2
- package/src/core/config.ts +0 -21
- package/src/core/index.ts +0 -3
- package/src/core/indexer.ts +0 -131
- package/src/core/prompt-builder.ts +0 -91
- package/src/events.ts +0 -35
- package/src/index-node.ts +0 -23
- package/src/index.ts +0 -159
- package/src/modules/auth.ts +0 -48
- package/src/modules/base.ts +0 -9
- package/src/modules/ci.ts +0 -12
- package/src/modules/docs.ts +0 -84
- package/src/modules/invitations.ts +0 -45
- package/src/modules/organizations.ts +0 -90
- package/src/modules/sprints.ts +0 -69
- package/src/modules/tasks.ts +0 -110
- package/src/modules/workspaces.ts +0 -94
- package/src/orchestrator.ts +0 -473
- package/src/utils/colors.ts +0 -63
- package/src/utils/retry.ts +0 -56
package/dist/core/index.js
DELETED
package/dist/core/indexer.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
import { globby } from "globby";
|
|
4
|
-
export class CodebaseIndexer {
|
|
5
|
-
projectPath;
|
|
6
|
-
indexPath;
|
|
7
|
-
constructor(projectPath) {
|
|
8
|
-
this.projectPath = projectPath;
|
|
9
|
-
this.indexPath = join(projectPath, ".locus", "codebase-index.json");
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Generates a codebase index by providing the entire file tree to an AI summarizer.
|
|
13
|
-
* This is much more efficient than per-file indexing for large projects.
|
|
14
|
-
*/
|
|
15
|
-
async index(onProgress, treeSummarizer) {
|
|
16
|
-
if (!treeSummarizer) {
|
|
17
|
-
throw new Error("A treeSummarizer is required for this indexing method.");
|
|
18
|
-
}
|
|
19
|
-
if (onProgress)
|
|
20
|
-
onProgress("Generating file tree...");
|
|
21
|
-
// 1. Get a comprehensive but clean file tree
|
|
22
|
-
const gitmodulesPath = join(this.projectPath, ".gitmodules");
|
|
23
|
-
const submoduleIgnores = [];
|
|
24
|
-
if (existsSync(gitmodulesPath)) {
|
|
25
|
-
try {
|
|
26
|
-
const content = readFileSync(gitmodulesPath, "utf-8");
|
|
27
|
-
const lines = content.split("\n");
|
|
28
|
-
for (const line of lines) {
|
|
29
|
-
const match = line.match(/^\s*path\s*=\s*(.*)$/);
|
|
30
|
-
const path = match?.[1]?.trim();
|
|
31
|
-
if (path) {
|
|
32
|
-
submoduleIgnores.push(`${path}/**`);
|
|
33
|
-
submoduleIgnores.push(`**/${path}/**`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
// Fallback if .gitmodules exists but can't be read or parsed
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
const files = await globby(["**/*"], {
|
|
42
|
-
cwd: this.projectPath,
|
|
43
|
-
gitignore: true,
|
|
44
|
-
ignore: [
|
|
45
|
-
...submoduleIgnores,
|
|
46
|
-
"**/node_modules/**",
|
|
47
|
-
"**/dist/**",
|
|
48
|
-
"**/build/**",
|
|
49
|
-
"**/target/**", // Rust build artifacts
|
|
50
|
-
"**/bin/**",
|
|
51
|
-
"**/obj/**",
|
|
52
|
-
"**/.next/**",
|
|
53
|
-
"**/.svelte-kit/**",
|
|
54
|
-
"**/.nuxt/**",
|
|
55
|
-
"**/.cache/**",
|
|
56
|
-
"**/out/**",
|
|
57
|
-
"**/__tests__/**",
|
|
58
|
-
"**/coverage/**",
|
|
59
|
-
"**/*.test.*",
|
|
60
|
-
"**/*.spec.*",
|
|
61
|
-
"**/*.d.ts",
|
|
62
|
-
"**/tsconfig.tsbuildinfo",
|
|
63
|
-
"**/.locus/*.json", // Ignore index and other system JSONs
|
|
64
|
-
"**/.locus/*.md", // Ignore system MDs
|
|
65
|
-
"**/.locus/!(artifacts)/**", // Ignore everything in .locus EXCEPT artifacts
|
|
66
|
-
"**/.git/**",
|
|
67
|
-
"**/.svn/**",
|
|
68
|
-
"**/.hg/**",
|
|
69
|
-
"**/.vscode/**",
|
|
70
|
-
"**/.idea/**",
|
|
71
|
-
"**/.DS_Store",
|
|
72
|
-
"**/bun.lock",
|
|
73
|
-
"**/package-lock.json",
|
|
74
|
-
"**/yarn.lock",
|
|
75
|
-
"**/pnpm-lock.yaml",
|
|
76
|
-
"**/Cargo.lock",
|
|
77
|
-
"**/go.sum",
|
|
78
|
-
"**/poetry.lock",
|
|
79
|
-
// Binary/Large Assets
|
|
80
|
-
"**/*.{png,jpg,jpeg,gif,svg,ico,mp4,webm,wav,mp3,woff,woff2,eot,ttf,otf,pdf,zip,tar.gz,rar}",
|
|
81
|
-
],
|
|
82
|
-
});
|
|
83
|
-
// Format the tree for the AI
|
|
84
|
-
const treeString = files.join("\n");
|
|
85
|
-
if (onProgress)
|
|
86
|
-
onProgress("AI is analyzing codebase structure...");
|
|
87
|
-
// 2. Ask AI to generate the index based on the tree
|
|
88
|
-
const index = await treeSummarizer(treeString);
|
|
89
|
-
// 3. Post-process: Ensure symbols are extracted for core files if not provided by AI
|
|
90
|
-
// (AI is good at structure, but might miss specific exports unless it reads the files)
|
|
91
|
-
// For now, we trust the AI's structural summary and can supplement symbols later if needed.
|
|
92
|
-
index.lastIndexed = new Date().toISOString();
|
|
93
|
-
return index;
|
|
94
|
-
}
|
|
95
|
-
loadIndex() {
|
|
96
|
-
if (existsSync(this.indexPath)) {
|
|
97
|
-
try {
|
|
98
|
-
return JSON.parse(readFileSync(this.indexPath, "utf-8"));
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
saveIndex(index) {
|
|
107
|
-
const dir = dirname(this.indexPath);
|
|
108
|
-
if (!existsSync(dir)) {
|
|
109
|
-
mkdirSync(dir, { recursive: true });
|
|
110
|
-
}
|
|
111
|
-
writeFileSync(this.indexPath, JSON.stringify(index, null, 2));
|
|
112
|
-
}
|
|
113
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import { AssigneeRole } from "@locusai/shared";
|
|
3
|
-
import { getLocusPath } from "./config.js";
|
|
4
|
-
export class PromptBuilder {
|
|
5
|
-
projectPath;
|
|
6
|
-
constructor(projectPath) {
|
|
7
|
-
this.projectPath = projectPath;
|
|
8
|
-
}
|
|
9
|
-
async build(task) {
|
|
10
|
-
let prompt = `# Task: ${task.title}\n\n`;
|
|
11
|
-
const roleText = this.roleToText(task.assigneeRole);
|
|
12
|
-
if (roleText) {
|
|
13
|
-
prompt += `## Role\nYou are acting as a ${roleText}.\n\n`;
|
|
14
|
-
}
|
|
15
|
-
prompt += `## Description\n${task.description || "No description provided."}\n\n`;
|
|
16
|
-
// 1. Add CLAUDE.md context
|
|
17
|
-
const contextPath = getLocusPath(this.projectPath, "contextFile");
|
|
18
|
-
if (existsSync(contextPath)) {
|
|
19
|
-
try {
|
|
20
|
-
const context = readFileSync(contextPath, "utf-8");
|
|
21
|
-
prompt += `## Project Context (from CLAUDE.md)\n${context}\n\n`;
|
|
22
|
-
}
|
|
23
|
-
catch (err) {
|
|
24
|
-
console.warn(`Warning: Could not read context file: ${err}`);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
// 2. Add Codebase Index context
|
|
28
|
-
const indexPath = getLocusPath(this.projectPath, "indexFile");
|
|
29
|
-
if (existsSync(indexPath)) {
|
|
30
|
-
prompt += `## Codebase Overview\nThere is an index file in the .locus/codebase-index.json and if you need you can check it.\n\n`;
|
|
31
|
-
}
|
|
32
|
-
// 3. Add Documents
|
|
33
|
-
if (task.docs && task.docs.length > 0) {
|
|
34
|
-
prompt += `## Attached Documents\n`;
|
|
35
|
-
for (const doc of task.docs) {
|
|
36
|
-
prompt += `### ${doc.title}\n${doc.content || "(No content)"}\n\n`;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
// 4. Add Checklist
|
|
40
|
-
if (task.acceptanceChecklist && task.acceptanceChecklist.length > 0) {
|
|
41
|
-
prompt += `## Acceptance Criteria\n`;
|
|
42
|
-
for (const item of task.acceptanceChecklist) {
|
|
43
|
-
prompt += `- ${item.done ? "[x]" : "[ ]"} ${item.text}\n`;
|
|
44
|
-
}
|
|
45
|
-
prompt += "\n";
|
|
46
|
-
}
|
|
47
|
-
// 5. Add Comments & Feedback
|
|
48
|
-
if (task.comments && task.comments.length > 0) {
|
|
49
|
-
const comments = task.comments.slice(0, 5);
|
|
50
|
-
prompt += `## Task History & Feedback\n`;
|
|
51
|
-
prompt += `Review the following comments for context or rejection feedback:\n\n`;
|
|
52
|
-
for (const comment of comments) {
|
|
53
|
-
const date = new Date(comment.createdAt).toLocaleString();
|
|
54
|
-
prompt += `### ${comment.author} (${date})\n${comment.text}\n\n`;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
prompt += `## Instructions
|
|
58
|
-
1. Complete this task.
|
|
59
|
-
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.
|
|
60
|
-
3. **Paths**: Use relative paths from the project root at all times. Do NOT use absolute local paths (e.g., /Users/...).
|
|
61
|
-
4. When finished successfully, output: <promise>COMPLETE</promise>\n`;
|
|
62
|
-
return prompt;
|
|
63
|
-
}
|
|
64
|
-
roleToText(role) {
|
|
65
|
-
if (!role) {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
switch (role) {
|
|
69
|
-
case AssigneeRole.BACKEND:
|
|
70
|
-
return "Backend Engineer";
|
|
71
|
-
case AssigneeRole.FRONTEND:
|
|
72
|
-
return "Frontend Engineer";
|
|
73
|
-
case AssigneeRole.PM:
|
|
74
|
-
return "Product Manager";
|
|
75
|
-
case AssigneeRole.QA:
|
|
76
|
-
return "QA Engineer";
|
|
77
|
-
case AssigneeRole.DESIGN:
|
|
78
|
-
return "Product Designer";
|
|
79
|
-
default:
|
|
80
|
-
return "engineer";
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
package/dist/events.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from "events";
|
|
2
|
-
export var LocusEvent;
|
|
3
|
-
(function (LocusEvent) {
|
|
4
|
-
LocusEvent["TOKEN_EXPIRED"] = "TOKEN_EXPIRED";
|
|
5
|
-
LocusEvent["AUTH_ERROR"] = "AUTH_ERROR";
|
|
6
|
-
LocusEvent["REQUEST_ERROR"] = "REQUEST_ERROR";
|
|
7
|
-
})(LocusEvent || (LocusEvent = {}));
|
|
8
|
-
export class LocusEmitter extends EventEmitter {
|
|
9
|
-
on(event, listener) {
|
|
10
|
-
return super.on(event, listener);
|
|
11
|
-
}
|
|
12
|
-
emit(event, ...args) {
|
|
13
|
-
return super.emit(event, ...args);
|
|
14
|
-
}
|
|
15
|
-
}
|
package/dist/modules/auth.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { BaseModule } from "./base.js";
|
|
2
|
-
export class AuthModule extends BaseModule {
|
|
3
|
-
async getMe() {
|
|
4
|
-
const { data } = await this.api.get("/auth/me");
|
|
5
|
-
return data;
|
|
6
|
-
}
|
|
7
|
-
async requestRegisterOtp(email) {
|
|
8
|
-
const { data } = await this.api.post("/auth/register-otp", { email });
|
|
9
|
-
return data;
|
|
10
|
-
}
|
|
11
|
-
async requestLoginOtp(email) {
|
|
12
|
-
const { data } = await this.api.post("/auth/login-otp", { email });
|
|
13
|
-
return data;
|
|
14
|
-
}
|
|
15
|
-
async verifyLogin(body) {
|
|
16
|
-
const { data } = await this.api.post("/auth/verify-login", body);
|
|
17
|
-
return data;
|
|
18
|
-
}
|
|
19
|
-
async completeRegistration(body) {
|
|
20
|
-
const { data } = await this.api.post("/auth/complete-registration", body);
|
|
21
|
-
return data;
|
|
22
|
-
}
|
|
23
|
-
}
|
package/dist/modules/base.js
DELETED
package/dist/modules/ci.js
DELETED
package/dist/modules/docs.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { BaseModule } from "./base.js";
|
|
2
|
-
export class DocsModule extends BaseModule {
|
|
3
|
-
async create(workspaceId, body) {
|
|
4
|
-
const { data } = await this.api.post(`/workspaces/${workspaceId}/docs`, body);
|
|
5
|
-
return data.doc;
|
|
6
|
-
}
|
|
7
|
-
async list(workspaceId) {
|
|
8
|
-
const { data } = await this.api.get(`/workspaces/${workspaceId}/docs`);
|
|
9
|
-
return data.docs;
|
|
10
|
-
}
|
|
11
|
-
async getById(id, workspaceId) {
|
|
12
|
-
const { data } = await this.api.get(`/workspaces/${workspaceId}/docs/${id}`);
|
|
13
|
-
return data.doc;
|
|
14
|
-
}
|
|
15
|
-
async update(id, workspaceId, body) {
|
|
16
|
-
const { data } = await this.api.put(`/workspaces/${workspaceId}/docs/${id}`, body);
|
|
17
|
-
return data.doc;
|
|
18
|
-
}
|
|
19
|
-
async delete(id, workspaceId) {
|
|
20
|
-
await this.api.delete(`/workspaces/${workspaceId}/docs/${id}`);
|
|
21
|
-
}
|
|
22
|
-
// Group Management
|
|
23
|
-
async listGroups(workspaceId) {
|
|
24
|
-
const { data } = await this.api.get(`/workspaces/${workspaceId}/doc-groups`);
|
|
25
|
-
return data.groups;
|
|
26
|
-
}
|
|
27
|
-
async createGroup(workspaceId, body) {
|
|
28
|
-
const { data } = await this.api.post(`/workspaces/${workspaceId}/doc-groups`, body);
|
|
29
|
-
return data.group;
|
|
30
|
-
}
|
|
31
|
-
async updateGroup(id, workspaceId, body) {
|
|
32
|
-
const { data } = await this.api.patch(`/workspaces/${workspaceId}/doc-groups/${id}`, body);
|
|
33
|
-
return data.group;
|
|
34
|
-
}
|
|
35
|
-
async deleteGroup(id, workspaceId) {
|
|
36
|
-
await this.api.delete(`/workspaces/${workspaceId}/doc-groups/${id}`);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { BaseModule } from "./base.js";
|
|
2
|
-
export class InvitationsModule extends BaseModule {
|
|
3
|
-
async create(orgId, body) {
|
|
4
|
-
const { data } = await this.api.post(`/org/${orgId}/invitations`, body);
|
|
5
|
-
return data.invitation;
|
|
6
|
-
}
|
|
7
|
-
async list(orgId) {
|
|
8
|
-
const { data } = await this.api.get(`/org/${orgId}/invitations`);
|
|
9
|
-
return data.invitations;
|
|
10
|
-
}
|
|
11
|
-
async verify(token) {
|
|
12
|
-
const { data } = await this.api.get(`/invitations/verify/${token}`);
|
|
13
|
-
return data;
|
|
14
|
-
}
|
|
15
|
-
async accept(body) {
|
|
16
|
-
const { data } = await this.api.post("/invitations/accept", body);
|
|
17
|
-
return data;
|
|
18
|
-
}
|
|
19
|
-
async revoke(orgId, id) {
|
|
20
|
-
await this.api.delete(`/org/${orgId}/invitations/${id}`);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { BaseModule } from "./base.js";
|
|
2
|
-
export class OrganizationsModule extends BaseModule {
|
|
3
|
-
async list() {
|
|
4
|
-
const { data } = await this.api.get("/organizations");
|
|
5
|
-
return data.organizations;
|
|
6
|
-
}
|
|
7
|
-
async getById(id) {
|
|
8
|
-
const { data } = await this.api.get(`/organizations/${id}`);
|
|
9
|
-
return data.organization;
|
|
10
|
-
}
|
|
11
|
-
async listMembers(id) {
|
|
12
|
-
const { data } = await this.api.get(`/organizations/${id}/members`);
|
|
13
|
-
return data.members;
|
|
14
|
-
}
|
|
15
|
-
async addMember(id, body) {
|
|
16
|
-
const { data } = await this.api.post(`/organizations/${id}/members`, body);
|
|
17
|
-
return data.membership;
|
|
18
|
-
}
|
|
19
|
-
async removeMember(orgId, userId) {
|
|
20
|
-
await this.api.delete(`/organizations/${orgId}/members/${userId}`);
|
|
21
|
-
}
|
|
22
|
-
async delete(orgId) {
|
|
23
|
-
await this.api.delete(`/organizations/${orgId}`);
|
|
24
|
-
}
|
|
25
|
-
// ============================================================================
|
|
26
|
-
// API Key Management
|
|
27
|
-
// ============================================================================
|
|
28
|
-
async listApiKeys(orgId) {
|
|
29
|
-
const { data } = await this.api.get(`/organizations/${orgId}/api-keys`);
|
|
30
|
-
return data.apiKeys;
|
|
31
|
-
}
|
|
32
|
-
async createApiKey(orgId, name) {
|
|
33
|
-
const { data } = await this.api.post(`/organizations/${orgId}/api-keys`, { name });
|
|
34
|
-
return data.apiKey;
|
|
35
|
-
}
|
|
36
|
-
async deleteApiKey(orgId, keyId) {
|
|
37
|
-
await this.api.delete(`/organizations/${orgId}/api-keys/${keyId}`);
|
|
38
|
-
}
|
|
39
|
-
}
|
package/dist/modules/sprints.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { BaseModule } from "./base.js";
|
|
2
|
-
export class SprintsModule extends BaseModule {
|
|
3
|
-
async list(workspaceId) {
|
|
4
|
-
const { data } = await this.api.get(`/workspaces/${workspaceId}/sprints`);
|
|
5
|
-
return data.sprints;
|
|
6
|
-
}
|
|
7
|
-
async getActive(workspaceId) {
|
|
8
|
-
const { data } = await this.api.get(`/workspaces/${workspaceId}/sprints/active`);
|
|
9
|
-
return data.sprint;
|
|
10
|
-
}
|
|
11
|
-
async getById(id, workspaceId) {
|
|
12
|
-
const { data } = await this.api.get(`/workspaces/${workspaceId}/sprints/${id}`);
|
|
13
|
-
return data.sprint;
|
|
14
|
-
}
|
|
15
|
-
async create(workspaceId, body) {
|
|
16
|
-
const { data } = await this.api.post(`/workspaces/${workspaceId}/sprints`, body);
|
|
17
|
-
return data.sprint;
|
|
18
|
-
}
|
|
19
|
-
async update(id, workspaceId, body) {
|
|
20
|
-
const { data } = await this.api.patch(`/workspaces/${workspaceId}/sprints/${id}`, body);
|
|
21
|
-
return data.sprint;
|
|
22
|
-
}
|
|
23
|
-
async delete(id, workspaceId) {
|
|
24
|
-
await this.api.delete(`/workspaces/${workspaceId}/sprints/${id}`);
|
|
25
|
-
}
|
|
26
|
-
async start(id, workspaceId) {
|
|
27
|
-
const { data } = await this.api.post(`/workspaces/${workspaceId}/sprints/${id}/start`);
|
|
28
|
-
return data.sprint;
|
|
29
|
-
}
|
|
30
|
-
async complete(id, workspaceId) {
|
|
31
|
-
const { data } = await this.api.post(`/workspaces/${workspaceId}/sprints/${id}/complete`);
|
|
32
|
-
return data.sprint;
|
|
33
|
-
}
|
|
34
|
-
}
|
package/dist/modules/tasks.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { TaskStatus, } from "@locusai/shared";
|
|
2
|
-
import { BaseModule } from "./base.js";
|
|
3
|
-
export class TasksModule extends BaseModule {
|
|
4
|
-
/**
|
|
5
|
-
* List all tasks in a workspace, optionally filtered
|
|
6
|
-
*/
|
|
7
|
-
async list(workspaceId, options) {
|
|
8
|
-
const { data } = await this.api.get(`/workspaces/${workspaceId}/tasks`);
|
|
9
|
-
let tasks = data.tasks;
|
|
10
|
-
// Client-side filtering (API doesn't support query params yet)
|
|
11
|
-
if (options?.sprintId) {
|
|
12
|
-
tasks = tasks.filter((t) => t.sprintId === options.sprintId);
|
|
13
|
-
}
|
|
14
|
-
if (options?.status) {
|
|
15
|
-
const statuses = Array.isArray(options.status)
|
|
16
|
-
? options.status
|
|
17
|
-
: [options.status];
|
|
18
|
-
tasks = tasks.filter((t) => statuses.includes(t.status));
|
|
19
|
-
}
|
|
20
|
-
return tasks;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Get available tasks for an agent to work on.
|
|
24
|
-
* Returns tasks in BACKLOG or IN_PROGRESS (unassigned) status.
|
|
25
|
-
*/
|
|
26
|
-
async getAvailable(workspaceId, sprintId) {
|
|
27
|
-
const tasks = await this.list(workspaceId, {
|
|
28
|
-
sprintId,
|
|
29
|
-
});
|
|
30
|
-
return tasks.filter((t) => t.status === TaskStatus.BACKLOG ||
|
|
31
|
-
(t.status === TaskStatus.IN_PROGRESS && !t.assignedTo));
|
|
32
|
-
}
|
|
33
|
-
async getById(id, workspaceId) {
|
|
34
|
-
const { data } = await this.api.get(`/workspaces/${workspaceId}/tasks/${id}`);
|
|
35
|
-
return data.task;
|
|
36
|
-
}
|
|
37
|
-
async create(workspaceId, body) {
|
|
38
|
-
const { data } = await this.api.post(`/workspaces/${workspaceId}/tasks`, body);
|
|
39
|
-
return data.task;
|
|
40
|
-
}
|
|
41
|
-
async update(id, workspaceId, body) {
|
|
42
|
-
const { data } = await this.api.patch(`/workspaces/${workspaceId}/tasks/${id}`, body);
|
|
43
|
-
return data.task;
|
|
44
|
-
}
|
|
45
|
-
async delete(id, workspaceId) {
|
|
46
|
-
await this.api.delete(`/workspaces/${workspaceId}/tasks/${id}`);
|
|
47
|
-
}
|
|
48
|
-
async getBacklog(workspaceId) {
|
|
49
|
-
const { data } = await this.api.get(`/workspaces/${workspaceId}/tasks/backlog`);
|
|
50
|
-
return data.tasks;
|
|
51
|
-
}
|
|
52
|
-
async addComment(id, workspaceId, body) {
|
|
53
|
-
const { data } = await this.api.post(`/workspaces/${workspaceId}/tasks/${id}/comment`, body);
|
|
54
|
-
return data.comment;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { BaseModule } from "./base.js";
|
|
2
|
-
export class WorkspacesModule extends BaseModule {
|
|
3
|
-
async listAll() {
|
|
4
|
-
const { data } = await this.api.get("/workspaces");
|
|
5
|
-
return data.workspaces;
|
|
6
|
-
}
|
|
7
|
-
async listByOrg(orgId) {
|
|
8
|
-
const { data } = await this.api.get(`/workspaces/org/${orgId}`);
|
|
9
|
-
return data.workspaces;
|
|
10
|
-
}
|
|
11
|
-
async create(body) {
|
|
12
|
-
const { orgId, ...bodyWithoutOrgId } = body;
|
|
13
|
-
const { data } = await this.api.post(`/workspaces/org/${orgId}`, bodyWithoutOrgId);
|
|
14
|
-
return data.workspace;
|
|
15
|
-
}
|
|
16
|
-
async createWithAutoOrg(body) {
|
|
17
|
-
const { data } = await this.api.post("/workspaces", body);
|
|
18
|
-
return data.workspace;
|
|
19
|
-
}
|
|
20
|
-
async getById(id) {
|
|
21
|
-
const { data } = await this.api.get(`/workspaces/${id}`);
|
|
22
|
-
return data.workspace;
|
|
23
|
-
}
|
|
24
|
-
async update(id, body) {
|
|
25
|
-
const { data } = await this.api.put(`/workspaces/${id}`, body);
|
|
26
|
-
return data.workspace;
|
|
27
|
-
}
|
|
28
|
-
async delete(id) {
|
|
29
|
-
await this.api.delete(`/workspaces/${id}`);
|
|
30
|
-
}
|
|
31
|
-
async getStats(id) {
|
|
32
|
-
const { data } = await this.api.get(`/workspaces/${id}/stats`);
|
|
33
|
-
return data;
|
|
34
|
-
}
|
|
35
|
-
async getActivity(id, limit) {
|
|
36
|
-
const { data } = await this.api.get(`/workspaces/${id}/activity`, {
|
|
37
|
-
params: { limit },
|
|
38
|
-
});
|
|
39
|
-
return data.activity;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Dispatch a task from the workspace backlog to an agent.
|
|
43
|
-
* Atomically moves a task from BACKLOG to IN_PROGRESS and assigns it.
|
|
44
|
-
*/
|
|
45
|
-
async dispatch(id, workerId, sprintId) {
|
|
46
|
-
const { data } = await this.api.post(`/workspaces/${id}/dispatch`, { workerId, sprintId });
|
|
47
|
-
return data.task;
|
|
48
|
-
}
|
|
49
|
-
}
|