@renseiai/plugin-linear 0.8.6
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/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/src/__tests__/subpath-exports.test.d.ts +2 -0
- package/dist/src/__tests__/subpath-exports.test.d.ts.map +1 -0
- package/dist/src/__tests__/subpath-exports.test.js +136 -0
- package/dist/src/agent-client-project-repo.test.d.ts +2 -0
- package/dist/src/agent-client-project-repo.test.d.ts.map +1 -0
- package/dist/src/agent-client-project-repo.test.js +153 -0
- package/dist/src/agent-client.d.ts +261 -0
- package/dist/src/agent-client.d.ts.map +1 -0
- package/dist/src/agent-client.js +902 -0
- package/dist/src/agent-session.d.ts +303 -0
- package/dist/src/agent-session.d.ts.map +1 -0
- package/dist/src/agent-session.js +969 -0
- package/dist/src/checkbox-utils.d.ts +88 -0
- package/dist/src/checkbox-utils.d.ts.map +1 -0
- package/dist/src/checkbox-utils.js +120 -0
- package/dist/src/circuit-breaker.d.ts +76 -0
- package/dist/src/circuit-breaker.d.ts.map +1 -0
- package/dist/src/circuit-breaker.js +229 -0
- package/dist/src/circuit-breaker.test.d.ts +2 -0
- package/dist/src/circuit-breaker.test.d.ts.map +1 -0
- package/dist/src/circuit-breaker.test.js +292 -0
- package/dist/src/constants.d.ts +87 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +101 -0
- package/dist/src/defaults/auto-trigger.d.ts +35 -0
- package/dist/src/defaults/auto-trigger.d.ts.map +1 -0
- package/dist/src/defaults/auto-trigger.js +36 -0
- package/dist/src/defaults/index.d.ts +12 -0
- package/dist/src/defaults/index.d.ts.map +1 -0
- package/dist/src/defaults/index.js +11 -0
- package/dist/src/defaults/priority.d.ts +20 -0
- package/dist/src/defaults/priority.d.ts.map +1 -0
- package/dist/src/defaults/priority.js +38 -0
- package/dist/src/defaults/prompts.d.ts +42 -0
- package/dist/src/defaults/prompts.d.ts.map +1 -0
- package/dist/src/defaults/prompts.js +313 -0
- package/dist/src/defaults/prompts.test.d.ts +2 -0
- package/dist/src/defaults/prompts.test.d.ts.map +1 -0
- package/dist/src/defaults/prompts.test.js +263 -0
- package/dist/src/defaults/work-type-detection.d.ts +19 -0
- package/dist/src/defaults/work-type-detection.d.ts.map +1 -0
- package/dist/src/defaults/work-type-detection.js +98 -0
- package/dist/src/errors.d.ts +91 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +173 -0
- package/dist/src/frontend-adapter.d.ts +168 -0
- package/dist/src/frontend-adapter.d.ts.map +1 -0
- package/dist/src/frontend-adapter.js +314 -0
- package/dist/src/frontend-adapter.test.d.ts +2 -0
- package/dist/src/frontend-adapter.test.d.ts.map +1 -0
- package/dist/src/frontend-adapter.test.js +545 -0
- package/dist/src/index.d.ts +32 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +35 -0
- package/dist/src/issue-tracker-adapter.d.ts +113 -0
- package/dist/src/issue-tracker-adapter.d.ts.map +1 -0
- package/dist/src/issue-tracker-adapter.js +169 -0
- package/dist/src/issue-tracker-proxy.d.ts +140 -0
- package/dist/src/issue-tracker-proxy.d.ts.map +1 -0
- package/dist/src/issue-tracker-proxy.js +10 -0
- package/dist/src/platform-adapter.d.ts +132 -0
- package/dist/src/platform-adapter.d.ts.map +1 -0
- package/dist/src/platform-adapter.js +260 -0
- package/dist/src/platform-adapter.test.d.ts +2 -0
- package/dist/src/platform-adapter.test.d.ts.map +1 -0
- package/dist/src/platform-adapter.test.js +468 -0
- package/dist/src/proxy-client.d.ts +103 -0
- package/dist/src/proxy-client.d.ts.map +1 -0
- package/dist/src/proxy-client.js +191 -0
- package/dist/src/rate-limiter.d.ts +64 -0
- package/dist/src/rate-limiter.d.ts.map +1 -0
- package/dist/src/rate-limiter.js +163 -0
- package/dist/src/rate-limiter.test.d.ts +2 -0
- package/dist/src/rate-limiter.test.d.ts.map +1 -0
- package/dist/src/rate-limiter.test.js +217 -0
- package/dist/src/retry.d.ts +59 -0
- package/dist/src/retry.d.ts.map +1 -0
- package/dist/src/retry.js +82 -0
- package/dist/src/retry.test.d.ts +2 -0
- package/dist/src/retry.test.d.ts.map +1 -0
- package/dist/src/retry.test.js +266 -0
- package/dist/src/tools/deployment-bridge.d.ts +34 -0
- package/dist/src/tools/deployment-bridge.d.ts.map +1 -0
- package/dist/src/tools/deployment-bridge.js +122 -0
- package/dist/src/tools/linear-plugin.d.ts +23 -0
- package/dist/src/tools/linear-plugin.d.ts.map +1 -0
- package/dist/src/tools/linear-plugin.js +175 -0
- package/dist/src/tools/linear-runner.d.ts +37 -0
- package/dist/src/tools/linear-runner.d.ts.map +1 -0
- package/dist/src/tools/linear-runner.js +810 -0
- package/dist/src/types.d.ts +492 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +148 -0
- package/dist/src/utils.d.ts +52 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +277 -0
- package/dist/src/webhook-types.d.ts +308 -0
- package/dist/src/webhook-types.d.ts.map +1 -0
- package/dist/src/webhook-types.js +46 -0
- package/package.json +73 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linear Tool Plugin
|
|
3
|
+
*
|
|
4
|
+
* Exposes all Linear CLI commands as typed, in-process agent tools.
|
|
5
|
+
* Agents call these directly instead of shelling out to `pnpm af-linear`.
|
|
6
|
+
*
|
|
7
|
+
* Moved from packages/core/src/tools/plugins/linear.ts to keep
|
|
8
|
+
* Linear-specific tool code in the Linear package.
|
|
9
|
+
*/
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { tool } from '@anthropic-ai/claude-agent-sdk';
|
|
12
|
+
import { runLinear } from './linear-runner.js';
|
|
13
|
+
function makeTools(apiKey, teamName) {
|
|
14
|
+
async function run(command, args = {}, positionalArgs = []) {
|
|
15
|
+
try {
|
|
16
|
+
const result = await runLinear({ command, args, positionalArgs, apiKey });
|
|
17
|
+
return {
|
|
18
|
+
content: [{ type: 'text', text: JSON.stringify(result.output, null, 2) }],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
return {
|
|
23
|
+
content: [{ type: 'text', text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
24
|
+
isError: true,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return [
|
|
29
|
+
tool('af_linear_get_issue', 'Get a Linear issue by ID or identifier', { issue_id: z.string().describe('Issue ID or identifier (e.g. SUP-123)') }, async (args) => run('get-issue', {}, [args.issue_id])),
|
|
30
|
+
tool('af_linear_create_issue', 'Create a new Linear issue', {
|
|
31
|
+
title: z.string().describe('Issue title'),
|
|
32
|
+
team: z.string().optional().describe('Team name (defaults to LINEAR_TEAM_NAME env var)'),
|
|
33
|
+
description: z.string().optional().describe('Issue description (markdown)'),
|
|
34
|
+
project: z.string().optional().describe('Project name'),
|
|
35
|
+
labels: z.array(z.string()).optional().describe('Label names'),
|
|
36
|
+
state: z.string().optional().describe('Initial state (e.g. "Backlog")'),
|
|
37
|
+
parent_id: z.string().optional().describe('Parent issue ID for sub-issues'),
|
|
38
|
+
}, async (args) => {
|
|
39
|
+
const cliArgs = {
|
|
40
|
+
title: args.title,
|
|
41
|
+
};
|
|
42
|
+
const team = args.team ?? teamName;
|
|
43
|
+
if (team)
|
|
44
|
+
cliArgs.team = team;
|
|
45
|
+
if (args.description)
|
|
46
|
+
cliArgs.description = args.description;
|
|
47
|
+
if (args.project)
|
|
48
|
+
cliArgs.project = args.project;
|
|
49
|
+
if (args.labels)
|
|
50
|
+
cliArgs.labels = args.labels;
|
|
51
|
+
if (args.state)
|
|
52
|
+
cliArgs.state = args.state;
|
|
53
|
+
if (args.parent_id)
|
|
54
|
+
cliArgs.parentId = args.parent_id;
|
|
55
|
+
return run('create-issue', cliArgs);
|
|
56
|
+
}),
|
|
57
|
+
tool('af_linear_update_issue', 'Update an existing Linear issue', {
|
|
58
|
+
issue_id: z.string().describe('Issue ID or identifier'),
|
|
59
|
+
title: z.string().optional().describe('New title'),
|
|
60
|
+
description: z.string().optional().describe('New description (markdown)'),
|
|
61
|
+
state: z.string().optional().describe('New state (e.g. "In Progress", "Done")'),
|
|
62
|
+
labels: z.array(z.string()).optional().describe('Label names to set'),
|
|
63
|
+
}, async (args) => {
|
|
64
|
+
const cliArgs = {};
|
|
65
|
+
if (args.title)
|
|
66
|
+
cliArgs.title = args.title;
|
|
67
|
+
if (args.description)
|
|
68
|
+
cliArgs.description = args.description;
|
|
69
|
+
if (args.state)
|
|
70
|
+
cliArgs.state = args.state;
|
|
71
|
+
if (args.labels)
|
|
72
|
+
cliArgs.labels = args.labels;
|
|
73
|
+
return run('update-issue', cliArgs, [args.issue_id]);
|
|
74
|
+
}),
|
|
75
|
+
tool('af_linear_list_comments', 'List comments on a Linear issue', { issue_id: z.string().describe('Issue ID or identifier') }, async (args) => run('list-comments', {}, [args.issue_id])),
|
|
76
|
+
tool('af_linear_create_comment', 'Add a comment to a Linear issue', {
|
|
77
|
+
issue_id: z.string().describe('Issue ID or identifier'),
|
|
78
|
+
body: z.string().describe('Comment text (markdown)'),
|
|
79
|
+
}, async (args) => run('create-comment', { body: args.body }, [args.issue_id])),
|
|
80
|
+
tool('af_linear_add_relation', 'Add a relation between two Linear issues', {
|
|
81
|
+
issue_id: z.string().describe('Source issue ID or identifier'),
|
|
82
|
+
related_issue_id: z.string().describe('Related issue ID or identifier'),
|
|
83
|
+
type: z.enum(['related', 'blocks', 'duplicate']).describe('Relation type'),
|
|
84
|
+
}, async (args) => run('add-relation', { type: args.type }, [args.issue_id, args.related_issue_id])),
|
|
85
|
+
tool('af_linear_list_relations', 'List relations for a Linear issue', { issue_id: z.string().describe('Issue ID or identifier') }, async (args) => run('list-relations', {}, [args.issue_id])),
|
|
86
|
+
tool('af_linear_remove_relation', 'Remove a relation between Linear issues', { relation_id: z.string().describe('Relation ID to remove') }, async (args) => run('remove-relation', {}, [args.relation_id])),
|
|
87
|
+
tool('af_linear_list_sub_issues', 'List sub-issues of a parent Linear issue with dependency graph', { issue_id: z.string().describe('Parent issue ID or identifier') }, async (args) => run('list-sub-issues', {}, [args.issue_id])),
|
|
88
|
+
tool('af_linear_list_sub_issue_statuses', 'List status of all sub-issues for a parent issue', { issue_id: z.string().describe('Parent issue ID or identifier') }, async (args) => run('list-sub-issue-statuses', {}, [args.issue_id])),
|
|
89
|
+
tool('af_linear_update_sub_issue', 'Update a sub-issue state and optionally add a comment', {
|
|
90
|
+
issue_id: z.string().describe('Sub-issue ID or identifier'),
|
|
91
|
+
state: z.string().optional().describe('New state (e.g. "Started", "Finished")'),
|
|
92
|
+
comment: z.string().optional().describe('Comment to add'),
|
|
93
|
+
}, async (args) => {
|
|
94
|
+
const cliArgs = {};
|
|
95
|
+
if (args.state)
|
|
96
|
+
cliArgs.state = args.state;
|
|
97
|
+
if (args.comment)
|
|
98
|
+
cliArgs.comment = args.comment;
|
|
99
|
+
return run('update-sub-issue', cliArgs, [args.issue_id]);
|
|
100
|
+
}),
|
|
101
|
+
tool('af_linear_check_blocked', 'Check if a Linear issue is blocked by other issues', { issue_id: z.string().describe('Issue ID or identifier') }, async (args) => run('check-blocked', {}, [args.issue_id])),
|
|
102
|
+
tool('af_linear_list_backlog_issues', 'List all backlog issues for a project', { project: z.string().describe('Project name') }, async (args) => run('list-backlog-issues', { project: args.project })),
|
|
103
|
+
tool('af_linear_list_unblocked_backlog', 'List unblocked backlog issues for a project (sorted by priority)', { project: z.string().describe('Project name') }, async (args) => run('list-unblocked-backlog', { project: args.project })),
|
|
104
|
+
tool('af_linear_check_deployment', 'Check deployment status of a pull request', {
|
|
105
|
+
pr_number: z.number().describe('Pull request number'),
|
|
106
|
+
format: z.enum(['json', 'markdown']).optional().describe('Output format (default: json)'),
|
|
107
|
+
}, async (args) => run('check-deployment', args.format ? { format: args.format } : {}, [String(args.pr_number)])),
|
|
108
|
+
tool('af_linear_list_issues', 'List Linear issues with filters (project, status, label, priority, assignee)', {
|
|
109
|
+
project: z.string().optional().describe('Filter by project name'),
|
|
110
|
+
status: z.string().optional().describe('Filter by status (Icebox, Backlog, Started, Finished, etc.)'),
|
|
111
|
+
label: z.string().optional().describe('Filter by label name'),
|
|
112
|
+
priority: z.number().optional().describe('Filter by priority (1=Urgent, 2=High, 3=Medium, 4=Low)'),
|
|
113
|
+
assignee: z.string().optional().describe('Filter by assignee (name, email, or "me")'),
|
|
114
|
+
team: z.string().optional().describe('Filter by team name'),
|
|
115
|
+
limit: z.number().optional().describe('Max results (default 50)'),
|
|
116
|
+
order_by: z.enum(['createdAt', 'updatedAt']).optional().describe('Sort order'),
|
|
117
|
+
query: z.string().optional().describe('Search title/description text'),
|
|
118
|
+
}, async (args) => {
|
|
119
|
+
const cliArgs = {};
|
|
120
|
+
if (args.project)
|
|
121
|
+
cliArgs.project = args.project;
|
|
122
|
+
if (args.status)
|
|
123
|
+
cliArgs.status = args.status;
|
|
124
|
+
if (args.label)
|
|
125
|
+
cliArgs.label = args.label;
|
|
126
|
+
if (args.priority != null)
|
|
127
|
+
cliArgs.priority = String(args.priority);
|
|
128
|
+
if (args.assignee)
|
|
129
|
+
cliArgs.assignee = args.assignee;
|
|
130
|
+
if (args.team)
|
|
131
|
+
cliArgs.team = args.team;
|
|
132
|
+
else if (teamName)
|
|
133
|
+
cliArgs.team = teamName;
|
|
134
|
+
if (args.limit != null)
|
|
135
|
+
cliArgs.limit = String(args.limit);
|
|
136
|
+
if (args.order_by)
|
|
137
|
+
cliArgs['order-by'] = args.order_by;
|
|
138
|
+
if (args.query)
|
|
139
|
+
cliArgs.query = args.query;
|
|
140
|
+
return run('list-issues', cliArgs);
|
|
141
|
+
}),
|
|
142
|
+
tool('af_linear_create_blocker', 'Create a human-needed blocker issue linked to a source issue', {
|
|
143
|
+
source_issue_id: z.string().describe('Source issue ID or identifier that is blocked'),
|
|
144
|
+
title: z.string().describe('What the human needs to do'),
|
|
145
|
+
description: z.string().optional().describe('Detailed steps for the human'),
|
|
146
|
+
team: z.string().optional().describe('Team name (defaults to source issue team)'),
|
|
147
|
+
project: z.string().optional().describe('Project name (defaults to source issue project)'),
|
|
148
|
+
assignee: z.string().optional().describe('Assignee name or email'),
|
|
149
|
+
}, async (args) => {
|
|
150
|
+
const cliArgs = {
|
|
151
|
+
title: args.title,
|
|
152
|
+
};
|
|
153
|
+
if (args.description)
|
|
154
|
+
cliArgs.description = args.description;
|
|
155
|
+
if (args.team)
|
|
156
|
+
cliArgs.team = args.team;
|
|
157
|
+
if (args.project)
|
|
158
|
+
cliArgs.project = args.project;
|
|
159
|
+
if (args.assignee)
|
|
160
|
+
cliArgs.assignee = args.assignee;
|
|
161
|
+
return run('create-blocker', cliArgs, [args.source_issue_id]);
|
|
162
|
+
}),
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
export const linearPlugin = {
|
|
166
|
+
name: 'af-linear',
|
|
167
|
+
description: 'Linear project management operations',
|
|
168
|
+
createTools(context) {
|
|
169
|
+
const apiKey = context.env.LINEAR_API_KEY;
|
|
170
|
+
if (!apiKey) {
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
return makeTools(apiKey, context.env.LINEAR_TEAM_NAME);
|
|
174
|
+
},
|
|
175
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linear CLI Runner — process-agnostic Linear operations.
|
|
3
|
+
*
|
|
4
|
+
* All 16 command implementations. This module does NOT call process.exit,
|
|
5
|
+
* read process.argv, or load dotenv. Shared by both the CLI entry point
|
|
6
|
+
* and the in-process tool plugin.
|
|
7
|
+
*
|
|
8
|
+
* Moved from packages/core/src/tools/linear-runner.ts to keep Linear-specific
|
|
9
|
+
* code in the Linear package.
|
|
10
|
+
*/
|
|
11
|
+
export interface LinearRunnerConfig {
|
|
12
|
+
command: string;
|
|
13
|
+
args: Record<string, string | string[] | boolean>;
|
|
14
|
+
positionalArgs: string[];
|
|
15
|
+
apiKey?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface LinearRunnerResult {
|
|
18
|
+
output: unknown;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Parse CLI arguments into a structured object.
|
|
22
|
+
*
|
|
23
|
+
* Supports:
|
|
24
|
+
* - `--key value` pairs
|
|
25
|
+
* - JSON array values: `--labels '["Bug", "Feature"]'`
|
|
26
|
+
* - Comma-separated values for array fields: `--labels "Bug,Feature"`
|
|
27
|
+
* - Boolean flags: `--dry-run` (value = "true")
|
|
28
|
+
*
|
|
29
|
+
* Returns the command (first non-flag arg), named args, and positional args.
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseLinearArgs(argv: string[]): {
|
|
32
|
+
command: string | undefined;
|
|
33
|
+
args: Record<string, string | string[] | boolean>;
|
|
34
|
+
positionalArgs: string[];
|
|
35
|
+
};
|
|
36
|
+
export declare function runLinear(config: LinearRunnerConfig): Promise<LinearRunnerResult>;
|
|
37
|
+
//# sourceMappingURL=linear-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear-runner.d.ts","sourceRoot":"","sources":["../../../src/tools/linear-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,CAAA;IACjD,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAA;CAChB;AAOD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAC/C,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,CAAA;IACjD,cAAc,EAAE,MAAM,EAAE,CAAA;CACzB,CA2CA;AAgvBD,wBAAsB,SAAS,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAwOvF"}
|