@qelos/aidev 0.3.0 → 0.3.1
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/.env.aidev.example +62 -62
- package/CONTRIBUTING.md +78 -78
- package/LICENSE +21 -21
- package/README.md +467 -467
- package/dist/__tests__/local-provider.test.js +31 -31
- package/dist/__tests__/platform.test.js +5 -5
- package/dist/__tests__/run.test.js +21 -8
- package/dist/__tests__/run.test.js.map +1 -1
- package/dist/cli.js +0 -0
- package/dist/commands/help.js +61 -61
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +126 -101
- package/dist/commands/run.js.map +1 -1
- package/dist/github.js +23 -23
- package/dist/providers/linear.js +70 -70
- package/dist/providers/monday.js +39 -39
- package/package.json +50 -50
- package/scripts/run-tests.cjs +18 -18
package/dist/providers/linear.js
CHANGED
|
@@ -35,16 +35,16 @@ class LinearProvider {
|
|
|
35
35
|
return raw.data;
|
|
36
36
|
}
|
|
37
37
|
async fetchWorkflowStateIds() {
|
|
38
|
-
const query = `
|
|
39
|
-
query WorkflowStates($filter: WorkflowStateFilter) {
|
|
40
|
-
workflowStates(filter: $filter) {
|
|
41
|
-
nodes {
|
|
42
|
-
id
|
|
43
|
-
name
|
|
44
|
-
type
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
38
|
+
const query = `
|
|
39
|
+
query WorkflowStates($filter: WorkflowStateFilter) {
|
|
40
|
+
workflowStates(filter: $filter) {
|
|
41
|
+
nodes {
|
|
42
|
+
id
|
|
43
|
+
name
|
|
44
|
+
type
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
48
|
`;
|
|
49
49
|
const data = await this.graphql(query, { filter: { team: { id: { eq: this.teamId } } } });
|
|
50
50
|
const byName = new Map();
|
|
@@ -55,21 +55,21 @@ class LinearProvider {
|
|
|
55
55
|
}
|
|
56
56
|
async fetchTasks() {
|
|
57
57
|
logger_1.logger.debug(`Fetching Linear issues for team ${this.teamId} with label "${this.label}"`);
|
|
58
|
-
const query = `
|
|
59
|
-
query Issues($filter: IssueFilter) {
|
|
60
|
-
issues(filter: $filter, first: 100) {
|
|
61
|
-
nodes {
|
|
62
|
-
id
|
|
63
|
-
identifier
|
|
64
|
-
title
|
|
65
|
-
description
|
|
66
|
-
url
|
|
67
|
-
state { id name type }
|
|
68
|
-
priority
|
|
69
|
-
labels { nodes { name } }
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
58
|
+
const query = `
|
|
59
|
+
query Issues($filter: IssueFilter) {
|
|
60
|
+
issues(filter: $filter, first: 100) {
|
|
61
|
+
nodes {
|
|
62
|
+
id
|
|
63
|
+
identifier
|
|
64
|
+
title
|
|
65
|
+
description
|
|
66
|
+
url
|
|
67
|
+
state { id name type }
|
|
68
|
+
priority
|
|
69
|
+
labels { nodes { name } }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
73
|
`;
|
|
74
74
|
const filter = {
|
|
75
75
|
team: { id: { eq: this.teamId } },
|
|
@@ -95,13 +95,13 @@ class LinearProvider {
|
|
|
95
95
|
async postComment(taskId, text) {
|
|
96
96
|
logger_1.logger.debug(`Posting comment to Linear issue ${taskId}`);
|
|
97
97
|
const issueId = await this.resolveIssueId(taskId);
|
|
98
|
-
const mutation = `
|
|
99
|
-
mutation CreateComment($input: CommentCreateInput!) {
|
|
100
|
-
commentCreate(input: $input) {
|
|
101
|
-
success
|
|
102
|
-
comment { id }
|
|
103
|
-
}
|
|
104
|
-
}
|
|
98
|
+
const mutation = `
|
|
99
|
+
mutation CreateComment($input: CommentCreateInput!) {
|
|
100
|
+
commentCreate(input: $input) {
|
|
101
|
+
success
|
|
102
|
+
comment { id }
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
105
|
`;
|
|
106
106
|
await this.graphql(mutation, {
|
|
107
107
|
input: { issueId, body: text },
|
|
@@ -110,19 +110,19 @@ class LinearProvider {
|
|
|
110
110
|
async getComments(taskId) {
|
|
111
111
|
logger_1.logger.debug(`Fetching comments for Linear issue ${taskId}`);
|
|
112
112
|
const issueId = await this.resolveIssueId(taskId);
|
|
113
|
-
const query = `
|
|
114
|
-
query IssueComments($id: String!) {
|
|
115
|
-
issue(id: $id) {
|
|
116
|
-
comments {
|
|
117
|
-
nodes {
|
|
118
|
-
id
|
|
119
|
-
body
|
|
120
|
-
user { name id }
|
|
121
|
-
createdAt
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
113
|
+
const query = `
|
|
114
|
+
query IssueComments($id: String!) {
|
|
115
|
+
issue(id: $id) {
|
|
116
|
+
comments {
|
|
117
|
+
nodes {
|
|
118
|
+
id
|
|
119
|
+
body
|
|
120
|
+
user { name id }
|
|
121
|
+
createdAt
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
126
|
`;
|
|
127
127
|
const data = await this.graphql(query, { id: issueId });
|
|
128
128
|
const nodes = data.issue?.comments?.nodes ?? [];
|
|
@@ -137,12 +137,12 @@ class LinearProvider {
|
|
|
137
137
|
}
|
|
138
138
|
async resolveIssueId(identifier) {
|
|
139
139
|
if (/^[A-Z]+-\d+$/i.test(identifier)) {
|
|
140
|
-
const query = `
|
|
141
|
-
query IssueByIdentifier($filter: IssueFilter) {
|
|
142
|
-
issues(filter: $filter, first: 1) {
|
|
143
|
-
nodes { id }
|
|
144
|
-
}
|
|
145
|
-
}
|
|
140
|
+
const query = `
|
|
141
|
+
query IssueByIdentifier($filter: IssueFilter) {
|
|
142
|
+
issues(filter: $filter, first: 1) {
|
|
143
|
+
nodes { id }
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
146
|
`;
|
|
147
147
|
const data = await this.graphql(query, {
|
|
148
148
|
filter: { identifier: { eq: identifier } },
|
|
@@ -151,12 +151,12 @@ class LinearProvider {
|
|
|
151
151
|
if (id)
|
|
152
152
|
return id;
|
|
153
153
|
}
|
|
154
|
-
const byIdQuery = `
|
|
155
|
-
query Issue($id: String!) {
|
|
156
|
-
issue(id: $id) {
|
|
157
|
-
id
|
|
158
|
-
}
|
|
159
|
-
}
|
|
154
|
+
const byIdQuery = `
|
|
155
|
+
query Issue($id: String!) {
|
|
156
|
+
issue(id: $id) {
|
|
157
|
+
id
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
160
|
`;
|
|
161
161
|
const byId = await this.graphql(byIdQuery, { id: identifier });
|
|
162
162
|
if (byId.issue?.id)
|
|
@@ -173,12 +173,12 @@ class LinearProvider {
|
|
|
173
173
|
throw new Error(`Linear: no workflow state matching "${status}". Available: ${names}`);
|
|
174
174
|
}
|
|
175
175
|
const issueId = await this.resolveIssueId(taskId);
|
|
176
|
-
const mutation = `
|
|
177
|
-
mutation IssueUpdate($id: String!, $input: IssueUpdateInput!) {
|
|
178
|
-
issueUpdate(id: $id, input: $input) {
|
|
179
|
-
success
|
|
180
|
-
}
|
|
181
|
-
}
|
|
176
|
+
const mutation = `
|
|
177
|
+
mutation IssueUpdate($id: String!, $input: IssueUpdateInput!) {
|
|
178
|
+
issueUpdate(id: $id, input: $input) {
|
|
179
|
+
success
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
182
|
`;
|
|
183
183
|
await this.graphql(mutation, {
|
|
184
184
|
id: issueId,
|
|
@@ -186,13 +186,13 @@ class LinearProvider {
|
|
|
186
186
|
});
|
|
187
187
|
}
|
|
188
188
|
async createTask(params) {
|
|
189
|
-
const mutation = `
|
|
190
|
-
mutation IssueCreate($input: IssueCreateInput!) {
|
|
191
|
-
issueCreate(input: $input) {
|
|
192
|
-
success
|
|
193
|
-
issue { id identifier url }
|
|
194
|
-
}
|
|
195
|
-
}
|
|
189
|
+
const mutation = `
|
|
190
|
+
mutation IssueCreate($input: IssueCreateInput!) {
|
|
191
|
+
issueCreate(input: $input) {
|
|
192
|
+
success
|
|
193
|
+
issue { id identifier url }
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
196
|
`;
|
|
197
197
|
const input = {
|
|
198
198
|
teamId: this.teamId,
|
package/dist/providers/monday.js
CHANGED
|
@@ -53,21 +53,21 @@ class MondayProvider {
|
|
|
53
53
|
}
|
|
54
54
|
async fetchTasks() {
|
|
55
55
|
logger_1.logger.debug(`Fetching items from Monday board ${this.boardId}`);
|
|
56
|
-
const query = `
|
|
57
|
-
query ($boardId: ID!, $limit: Int!) {
|
|
58
|
-
boards(ids: [$boardId]) {
|
|
59
|
-
items_page(limit: $limit) {
|
|
60
|
-
cursor
|
|
61
|
-
items {
|
|
62
|
-
id
|
|
63
|
-
name
|
|
64
|
-
url
|
|
65
|
-
description { description }
|
|
66
|
-
column_values { id value text }
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
56
|
+
const query = `
|
|
57
|
+
query ($boardId: ID!, $limit: Int!) {
|
|
58
|
+
boards(ids: [$boardId]) {
|
|
59
|
+
items_page(limit: $limit) {
|
|
60
|
+
cursor
|
|
61
|
+
items {
|
|
62
|
+
id
|
|
63
|
+
name
|
|
64
|
+
url
|
|
65
|
+
description { description }
|
|
66
|
+
column_values { id value text }
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
71
|
`;
|
|
72
72
|
const data = await this.graphql(query, {
|
|
73
73
|
boardId: this.boardId,
|
|
@@ -97,10 +97,10 @@ class MondayProvider {
|
|
|
97
97
|
}
|
|
98
98
|
async postComment(taskId, text) {
|
|
99
99
|
logger_1.logger.debug(`Posting update to Monday item ${taskId}`);
|
|
100
|
-
const mutation = `
|
|
101
|
-
mutation ($itemId: ID!, $body: String!) {
|
|
102
|
-
create_update(item_id: $itemId, body: $body) { id }
|
|
103
|
-
}
|
|
100
|
+
const mutation = `
|
|
101
|
+
mutation ($itemId: ID!, $body: String!) {
|
|
102
|
+
create_update(item_id: $itemId, body: $body) { id }
|
|
103
|
+
}
|
|
104
104
|
`;
|
|
105
105
|
await this.graphql(mutation, {
|
|
106
106
|
itemId: taskId,
|
|
@@ -109,18 +109,18 @@ class MondayProvider {
|
|
|
109
109
|
}
|
|
110
110
|
async getComments(taskId) {
|
|
111
111
|
logger_1.logger.debug(`Fetching updates for Monday item ${taskId}`);
|
|
112
|
-
const query = `
|
|
113
|
-
query ($itemId: ID!) {
|
|
114
|
-
items(ids: [$itemId]) {
|
|
115
|
-
updates(limit: 100) {
|
|
116
|
-
id
|
|
117
|
-
text_body
|
|
118
|
-
body
|
|
119
|
-
created_at
|
|
120
|
-
creator { id name }
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
112
|
+
const query = `
|
|
113
|
+
query ($itemId: ID!) {
|
|
114
|
+
items(ids: [$itemId]) {
|
|
115
|
+
updates(limit: 100) {
|
|
116
|
+
id
|
|
117
|
+
text_body
|
|
118
|
+
body
|
|
119
|
+
created_at
|
|
120
|
+
creator { id name }
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
124
|
`;
|
|
125
125
|
const data = await this.graphql(query, { itemId: taskId });
|
|
126
126
|
const item = data.items?.[0];
|
|
@@ -137,10 +137,10 @@ class MondayProvider {
|
|
|
137
137
|
}
|
|
138
138
|
async updateStatus(taskId, status) {
|
|
139
139
|
logger_1.logger.debug(`Updating Monday item ${taskId} status to "${status}"`);
|
|
140
|
-
const mutation = `
|
|
141
|
-
mutation ($boardId: ID!, $itemId: ID!, $columnId: String!, $value: String!) {
|
|
142
|
-
change_column_value(board_id: $boardId, item_id: $itemId, column_id: $columnId, value: $value) { id }
|
|
143
|
-
}
|
|
140
|
+
const mutation = `
|
|
141
|
+
mutation ($boardId: ID!, $itemId: ID!, $columnId: String!, $value: String!) {
|
|
142
|
+
change_column_value(board_id: $boardId, item_id: $itemId, column_id: $columnId, value: $value) { id }
|
|
143
|
+
}
|
|
144
144
|
`;
|
|
145
145
|
const value = JSON.stringify({ label: status });
|
|
146
146
|
await this.graphql(mutation, {
|
|
@@ -152,10 +152,10 @@ class MondayProvider {
|
|
|
152
152
|
}
|
|
153
153
|
async createTask(params) {
|
|
154
154
|
const groupId = this.groupId || 'topics';
|
|
155
|
-
const mutation = `
|
|
156
|
-
mutation ($boardId: ID!, $groupId: String!, $itemName: String!, $columnValues: JSON) {
|
|
157
|
-
create_item(board_id: $boardId, group_id: $groupId, item_name: $itemName, column_values: $columnValues) { id }
|
|
158
|
-
}
|
|
155
|
+
const mutation = `
|
|
156
|
+
mutation ($boardId: ID!, $groupId: String!, $itemName: String!, $columnValues: JSON) {
|
|
157
|
+
create_item(board_id: $boardId, group_id: $groupId, item_name: $itemName, column_values: $columnValues) { id }
|
|
158
|
+
}
|
|
159
159
|
`;
|
|
160
160
|
const columnValues = {};
|
|
161
161
|
if (this.statusColumnId) {
|
package/package.json
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@qelos/aidev",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "AI-powered task executor — polls ClickUp (and more) to implement tasks with Claude, Cursor, Windsurf, or Antigravity",
|
|
5
|
-
"type": "commonjs",
|
|
6
|
-
"bin": {
|
|
7
|
-
"aidev": "dist/cli.js"
|
|
8
|
-
},
|
|
9
|
-
"main": "./dist/cli.js",
|
|
10
|
-
"engines": {
|
|
11
|
-
"node": ">=22.0.0"
|
|
12
|
-
},
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "tsc && node -e \"if(process.platform!=='win32')require('node:fs').chmodSync('dist/cli.js',0o755)\"",
|
|
15
|
-
"dev": "tsx src/cli.ts",
|
|
16
|
-
"test": "node scripts/run-tests.cjs",
|
|
17
|
-
"prepublishOnly": "npm run build"
|
|
18
|
-
},
|
|
19
|
-
"keywords": [
|
|
20
|
-
"ai",
|
|
21
|
-
"cli",
|
|
22
|
-
"clickup",
|
|
23
|
-
"claude",
|
|
24
|
-
"cursor",
|
|
25
|
-
"automation"
|
|
26
|
-
],
|
|
27
|
-
"author": "",
|
|
28
|
-
"license": "MIT",
|
|
29
|
-
"repository": {
|
|
30
|
-
"type": "git",
|
|
31
|
-
"url": "git+https://github.com/qelos-io/aidev.git"
|
|
32
|
-
},
|
|
33
|
-
"bugs": {
|
|
34
|
-
"url": "https://github.com/qelos-io/aidev/issues"
|
|
35
|
-
},
|
|
36
|
-
"homepage": "https://github.com/qelos-io/aidev#readme",
|
|
37
|
-
"publishConfig": {
|
|
38
|
-
"access": "public"
|
|
39
|
-
},
|
|
40
|
-
"dependencies": {
|
|
41
|
-
"chalk": "^4.1.2",
|
|
42
|
-
"commander": "^12.0.0",
|
|
43
|
-
"dotenv": "^16.4.0"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@types/node": "^22.0.0",
|
|
47
|
-
"tsx": "^4.0.0",
|
|
48
|
-
"typescript": "^5.0.0"
|
|
49
|
-
}
|
|
50
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@qelos/aidev",
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "AI-powered task executor — polls ClickUp (and more) to implement tasks with Claude, Cursor, Windsurf, or Antigravity",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"bin": {
|
|
7
|
+
"aidev": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/cli.js",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=22.0.0"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc && node -e \"if(process.platform!=='win32')require('node:fs').chmodSync('dist/cli.js',0o755)\"",
|
|
15
|
+
"dev": "tsx src/cli.ts",
|
|
16
|
+
"test": "node scripts/run-tests.cjs",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"ai",
|
|
21
|
+
"cli",
|
|
22
|
+
"clickup",
|
|
23
|
+
"claude",
|
|
24
|
+
"cursor",
|
|
25
|
+
"automation"
|
|
26
|
+
],
|
|
27
|
+
"author": "",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/qelos-io/aidev.git"
|
|
32
|
+
},
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/qelos-io/aidev/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/qelos-io/aidev#readme",
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"chalk": "^4.1.2",
|
|
42
|
+
"commander": "^12.0.0",
|
|
43
|
+
"dotenv": "^16.4.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^22.0.0",
|
|
47
|
+
"tsx": "^4.0.0",
|
|
48
|
+
"typescript": "^5.0.0"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/scripts/run-tests.cjs
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { spawnSync } = require('node:child_process');
|
|
4
|
-
const { globSync } = require('node:fs');
|
|
5
|
-
const path = require('node:path');
|
|
6
|
-
|
|
7
|
-
const root = path.join(__dirname, '..');
|
|
8
|
-
const files = globSync('src/__tests__/**/*.test.ts', { cwd: root }).sort();
|
|
9
|
-
if (files.length === 0) {
|
|
10
|
-
console.error('No test files found under src/__tests__');
|
|
11
|
-
process.exit(1);
|
|
12
|
-
}
|
|
13
|
-
const abs = files.map((f) => path.join(root, f));
|
|
14
|
-
const r = spawnSync(process.execPath, ['--require', 'tsx/cjs', '--test', ...abs], {
|
|
15
|
-
cwd: root,
|
|
16
|
-
stdio: 'inherit',
|
|
17
|
-
});
|
|
18
|
-
process.exit(r.status === null ? 1 : r.status);
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { spawnSync } = require('node:child_process');
|
|
4
|
+
const { globSync } = require('node:fs');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
|
|
7
|
+
const root = path.join(__dirname, '..');
|
|
8
|
+
const files = globSync('src/__tests__/**/*.test.ts', { cwd: root }).sort();
|
|
9
|
+
if (files.length === 0) {
|
|
10
|
+
console.error('No test files found under src/__tests__');
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
const abs = files.map((f) => path.join(root, f));
|
|
14
|
+
const r = spawnSync(process.execPath, ['--require', 'tsx/cjs', '--test', ...abs], {
|
|
15
|
+
cwd: root,
|
|
16
|
+
stdio: 'inherit',
|
|
17
|
+
});
|
|
18
|
+
process.exit(r.status === null ? 1 : r.status);
|