@alasano/pi-linear 0.1.1 → 0.2.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 +14 -2
- package/assets/linear_list_issues.png +0 -0
- package/assets/screenshot.png +0 -0
- package/extensions/renderers/comments.ts +323 -0
- package/extensions/renderers/common.ts +305 -0
- package/extensions/renderers/documents.ts +326 -0
- package/extensions/renderers/initiatives.ts +344 -0
- package/extensions/renderers/issue-labels.ts +294 -0
- package/extensions/renderers/issue-relations.ts +318 -0
- package/extensions/renderers/issue-statuses.ts +199 -0
- package/extensions/renderers/issues.ts +373 -0
- package/extensions/renderers/milestones.ts +294 -0
- package/extensions/renderers/project-labels.ts +279 -0
- package/extensions/renderers/project-relations.ts +344 -0
- package/extensions/renderers/projects.ts +430 -0
- package/extensions/renderers/state.ts +35 -0
- package/extensions/renderers/teams.ts +246 -0
- package/extensions/renderers/users.ts +242 -0
- package/extensions/renderers/workspaces.ts +44 -0
- package/extensions/settings.ts +40 -7
- package/extensions/tools/comments.ts +17 -0
- package/extensions/tools/documents.ts +23 -0
- package/extensions/tools/initiatives.ts +24 -0
- package/extensions/tools/issue-labels.ts +17 -0
- package/extensions/tools/issue-relations.ts +17 -0
- package/extensions/tools/issue-statuses.ts +6 -0
- package/extensions/tools/issues.ts +29 -0
- package/extensions/tools/milestones.ts +18 -0
- package/extensions/tools/project-labels.ts +17 -0
- package/extensions/tools/project-relations.ts +17 -0
- package/extensions/tools/projects.ts +24 -0
- package/extensions/tools/teams.ts +10 -0
- package/extensions/tools/users.ts +10 -0
- package/extensions/tools/workspaces.ts +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AgentToolResult,
|
|
3
|
+
type Theme,
|
|
4
|
+
type ToolRenderResultOptions,
|
|
5
|
+
} from '@mariozechner/pi-coding-agent';
|
|
6
|
+
import { Text } from '@mariozechner/pi-tui';
|
|
7
|
+
import {
|
|
8
|
+
asString,
|
|
9
|
+
cleanOneLine,
|
|
10
|
+
dimStyle,
|
|
11
|
+
expandedJson,
|
|
12
|
+
shouldShowJson,
|
|
13
|
+
jsonHint,
|
|
14
|
+
LinearListResultComponent,
|
|
15
|
+
mutedStyle,
|
|
16
|
+
renderLinearToolCall,
|
|
17
|
+
renderResponsiveTable,
|
|
18
|
+
toolOutputStyle,
|
|
19
|
+
truncate,
|
|
20
|
+
truncateLine,
|
|
21
|
+
type LinearToolRenderContext,
|
|
22
|
+
type TableColumn,
|
|
23
|
+
type ToolArgs,
|
|
24
|
+
} from './common';
|
|
25
|
+
|
|
26
|
+
type UserLike = {
|
|
27
|
+
id?: string | null;
|
|
28
|
+
name?: string | null;
|
|
29
|
+
displayName?: string | null;
|
|
30
|
+
email?: string | null;
|
|
31
|
+
active?: boolean | null;
|
|
32
|
+
admin?: boolean | null;
|
|
33
|
+
guest?: boolean | null;
|
|
34
|
+
isAssignable?: boolean | null;
|
|
35
|
+
createdAt?: string | null;
|
|
36
|
+
updatedAt?: string | null;
|
|
37
|
+
url?: string | null;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
type UserResultDetails = {
|
|
41
|
+
user?: UserLike | null;
|
|
42
|
+
users?: UserLike[];
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const USER_LIST_PREVIEW_LIMIT = 20;
|
|
46
|
+
const NAME_LIMIT = 90;
|
|
47
|
+
const TABLE_NAME_MIN_WIDTH = 24;
|
|
48
|
+
|
|
49
|
+
function userDetails(result: AgentToolResult<any>): UserResultDetails {
|
|
50
|
+
return (result.details ?? {}) as UserResultDetails;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function userName(user: UserLike): string {
|
|
54
|
+
return truncate(
|
|
55
|
+
cleanOneLine(asString(user.name) ?? asString(user.displayName) ?? '(unnamed user)'),
|
|
56
|
+
NAME_LIMIT,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function displayNameText(user: UserLike): string | undefined {
|
|
61
|
+
const displayName = asString(user.displayName);
|
|
62
|
+
const name = asString(user.name);
|
|
63
|
+
if (!displayName || !name || displayName === name) return undefined;
|
|
64
|
+
return displayName;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function activeText(user: UserLike): string {
|
|
68
|
+
if (user.active === true) return 'active';
|
|
69
|
+
if (user.active === false) return 'disabled';
|
|
70
|
+
return '—';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function roleText(user: UserLike): string {
|
|
74
|
+
if (user.admin === true) return 'admin';
|
|
75
|
+
if (user.guest === true) return 'guest';
|
|
76
|
+
return 'member';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function assignableText(user: UserLike): string {
|
|
80
|
+
if (user.isAssignable === true) return 'yes';
|
|
81
|
+
if (user.isAssignable === false) return 'no';
|
|
82
|
+
return '—';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function metadataParts(user: UserLike): string[] {
|
|
86
|
+
const displayName = displayNameText(user);
|
|
87
|
+
const email = asString(user.email);
|
|
88
|
+
|
|
89
|
+
return [
|
|
90
|
+
displayName ? `display: ${displayName}` : undefined,
|
|
91
|
+
email,
|
|
92
|
+
activeText(user),
|
|
93
|
+
roleText(user),
|
|
94
|
+
`assignable: ${assignableText(user)}`,
|
|
95
|
+
].filter((part): part is string => !!part);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function formatUserListLine(user: UserLike, theme: Theme, width: number): string {
|
|
99
|
+
const metadata = metadataParts(user);
|
|
100
|
+
const suffix = metadata.length ? theme.fg('dim', ` · ${metadata.join(' · ')}`) : '';
|
|
101
|
+
|
|
102
|
+
return truncateLine(` ${theme.fg('toolOutput', userName(user))}${suffix}`, width);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function activeStyle(theme: Theme, value: string): (text: string) => string {
|
|
106
|
+
if (value === 'active') return (text) => theme.fg('success', text);
|
|
107
|
+
if (value === 'disabled') return dimStyle(theme);
|
|
108
|
+
return mutedStyle(theme);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function roleStyle(theme: Theme, value: string): (text: string) => string {
|
|
112
|
+
if (value === 'admin') return (text) => theme.fg('warning', text);
|
|
113
|
+
if (value === 'guest') return mutedStyle(theme);
|
|
114
|
+
return dimStyle(theme);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function assignableStyle(theme: Theme, value: string): (text: string) => string {
|
|
118
|
+
if (value === 'yes') return (text) => theme.fg('success', text);
|
|
119
|
+
if (value === 'no') return dimStyle(theme);
|
|
120
|
+
return mutedStyle(theme);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const USER_TABLE_COLUMNS: TableColumn<UserLike>[] = [
|
|
124
|
+
{
|
|
125
|
+
id: 'email',
|
|
126
|
+
label: 'Email',
|
|
127
|
+
width: 30,
|
|
128
|
+
value: (user) => asString(user.email) ?? '—',
|
|
129
|
+
style: (theme) => mutedStyle(theme),
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: 'active',
|
|
133
|
+
label: 'Active',
|
|
134
|
+
width: 8,
|
|
135
|
+
value: activeText,
|
|
136
|
+
style: activeStyle,
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: 'role',
|
|
140
|
+
label: 'Role',
|
|
141
|
+
width: 7,
|
|
142
|
+
value: roleText,
|
|
143
|
+
style: roleStyle,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
id: 'assignable',
|
|
147
|
+
label: 'Assignable',
|
|
148
|
+
width: 10,
|
|
149
|
+
value: assignableText,
|
|
150
|
+
style: assignableStyle,
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
function renderUserTable(users: UserLike[], theme: Theme, width: number): string[] {
|
|
155
|
+
return renderResponsiveTable(users, theme, width, {
|
|
156
|
+
columns: USER_TABLE_COLUMNS,
|
|
157
|
+
primary: {
|
|
158
|
+
label: 'Name',
|
|
159
|
+
minWidth: TABLE_NAME_MIN_WIDTH,
|
|
160
|
+
value: userName,
|
|
161
|
+
style: (theme) => toolOutputStyle(theme),
|
|
162
|
+
},
|
|
163
|
+
dropOrder: ['assignable', 'role', 'active', 'email'],
|
|
164
|
+
fallback: formatUserListLine,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function formatUserTitle(user: UserLike, theme: Theme): string {
|
|
169
|
+
const displayName = displayNameText(user);
|
|
170
|
+
const name = userName(user);
|
|
171
|
+
const title = displayName ? `${name} (${truncate(cleanOneLine(displayName), NAME_LIMIT)})` : name;
|
|
172
|
+
return theme.fg('toolOutput', title);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function renderUserCard(user: UserLike | null | undefined, theme: Theme): Text {
|
|
176
|
+
if (!user) {
|
|
177
|
+
return new Text(`\n${theme.fg('dim', 'User not found')}\n\n${jsonHint()}`, 0, 0);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const email = asString(user.email);
|
|
181
|
+
const url = asString(user.url);
|
|
182
|
+
const metadata = [
|
|
183
|
+
email,
|
|
184
|
+
activeText(user),
|
|
185
|
+
roleText(user),
|
|
186
|
+
`assignable: ${assignableText(user)}`,
|
|
187
|
+
].filter((part): part is string => !!part);
|
|
188
|
+
|
|
189
|
+
let text = `\n${theme.fg('success', '✓ User')} ${formatUserTitle(user, theme)}`;
|
|
190
|
+
if (metadata.length) text += `\n ${theme.fg('dim', metadata.join(' · '))}`;
|
|
191
|
+
if (url) text += `\n ${theme.fg('dim', url)}`;
|
|
192
|
+
text += `\n\n${jsonHint()}`;
|
|
193
|
+
|
|
194
|
+
return new Text(text, 0, 0);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export function renderLinearUserListCall(args: ToolArgs | undefined, theme: Theme): Text {
|
|
198
|
+
return renderLinearToolCall('linear_list_users', args, theme, [
|
|
199
|
+
['first', 'first'],
|
|
200
|
+
['orderBy', 'order'],
|
|
201
|
+
['filter', 'filter'],
|
|
202
|
+
['includeArchived', 'includeArchived'],
|
|
203
|
+
['includeDisabled', 'includeDisabled'],
|
|
204
|
+
]);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export function renderLinearGetUserCall(args: ToolArgs | undefined, theme: Theme): Text {
|
|
208
|
+
return renderLinearToolCall('linear_get_user', args, theme, [['userId', 'userId']]);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export function renderLinearUserListResult(
|
|
212
|
+
result: AgentToolResult<any>,
|
|
213
|
+
options: ToolRenderResultOptions,
|
|
214
|
+
theme: Theme,
|
|
215
|
+
context: LinearToolRenderContext,
|
|
216
|
+
): Text | LinearListResultComponent<UserLike> {
|
|
217
|
+
if (options.isPartial) return new Text(theme.fg('warning', 'Loading users…'), 0, 0);
|
|
218
|
+
if (shouldShowJson(options, context)) return expandedJson(result, theme);
|
|
219
|
+
|
|
220
|
+
const users = Array.isArray(userDetails(result).users)
|
|
221
|
+
? (userDetails(result).users as UserLike[])
|
|
222
|
+
: [];
|
|
223
|
+
|
|
224
|
+
return new LinearListResultComponent(users, theme, {
|
|
225
|
+
noun: 'user',
|
|
226
|
+
emptyLabel: 'No users found',
|
|
227
|
+
previewLimit: USER_LIST_PREVIEW_LIMIT,
|
|
228
|
+
renderItems: renderUserTable,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export function renderLinearUserResult(
|
|
233
|
+
result: AgentToolResult<any>,
|
|
234
|
+
options: ToolRenderResultOptions,
|
|
235
|
+
theme: Theme,
|
|
236
|
+
context: LinearToolRenderContext,
|
|
237
|
+
): Text {
|
|
238
|
+
if (options.isPartial) return new Text(theme.fg('warning', 'Loading user…'), 0, 0);
|
|
239
|
+
if (shouldShowJson(options, context)) return expandedJson(result, theme);
|
|
240
|
+
|
|
241
|
+
return renderUserCard(userDetails(result).user, theme);
|
|
242
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AgentToolResult,
|
|
3
|
+
type Theme,
|
|
4
|
+
type ToolRenderResultOptions,
|
|
5
|
+
} from '@mariozechner/pi-coding-agent';
|
|
6
|
+
import { Text } from '@mariozechner/pi-tui';
|
|
7
|
+
import {
|
|
8
|
+
asString,
|
|
9
|
+
expandedJson,
|
|
10
|
+
shouldShowJson,
|
|
11
|
+
jsonHint,
|
|
12
|
+
renderLinearToolCall,
|
|
13
|
+
type LinearToolRenderContext,
|
|
14
|
+
type ToolArgs,
|
|
15
|
+
} from './common';
|
|
16
|
+
|
|
17
|
+
type WorkspaceSwitchResultDetails = {
|
|
18
|
+
active?: string | null;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function workspaceSwitchDetails(result: AgentToolResult<any>): WorkspaceSwitchResultDetails {
|
|
22
|
+
return (result.details ?? {}) as WorkspaceSwitchResultDetails;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function renderLinearSwitchWorkspaceCall(args: ToolArgs | undefined, theme: Theme): Text {
|
|
26
|
+
return renderLinearToolCall('linear_switch_workspace', args, theme, [['name', 'name']]);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function renderLinearSwitchWorkspaceResult(
|
|
30
|
+
result: AgentToolResult<any>,
|
|
31
|
+
options: ToolRenderResultOptions,
|
|
32
|
+
theme: Theme,
|
|
33
|
+
context: LinearToolRenderContext,
|
|
34
|
+
): Text {
|
|
35
|
+
if (options.isPartial) return new Text(theme.fg('warning', 'Switching workspace…'), 0, 0);
|
|
36
|
+
if (shouldShowJson(options, context)) return expandedJson(result, theme);
|
|
37
|
+
|
|
38
|
+
const active = asString(workspaceSwitchDetails(result).active) ?? 'unknown';
|
|
39
|
+
return new Text(
|
|
40
|
+
`\n${theme.fg('success', `✓ Active Linear workspace: ${active}`)}\n\n${jsonHint()}`,
|
|
41
|
+
0,
|
|
42
|
+
0,
|
|
43
|
+
);
|
|
44
|
+
}
|
package/extensions/settings.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { dirname, join } from 'node:path';
|
|
|
3
3
|
import type { ExtensionAPI, ExtensionContext } from '@mariozechner/pi-coding-agent';
|
|
4
4
|
import { getAgentDir, getSettingsListTheme } from '@mariozechner/pi-coding-agent';
|
|
5
5
|
import { type SettingItem, SettingsList } from '@mariozechner/pi-tui';
|
|
6
|
+
import { invalidateLinearResultRenderers, setDefaultJsonView } from './renderers/state';
|
|
6
7
|
|
|
7
8
|
const SETTINGS_PATH = join(getAgentDir(), 'state', 'extensions', 'linear', 'tool-settings.json');
|
|
8
9
|
const OVERLAY_MAX_INNER = 60;
|
|
@@ -166,28 +167,37 @@ const ALL_LINEAR_TOOLS = TOOL_CATEGORIES.flatMap((c) => c.tools);
|
|
|
166
167
|
|
|
167
168
|
type ToolSettings = {
|
|
168
169
|
disabledTools: string[];
|
|
170
|
+
defaultJsonView: boolean;
|
|
169
171
|
};
|
|
170
172
|
|
|
171
173
|
function createDefaultSettings(): ToolSettings {
|
|
172
|
-
return { disabledTools: [] };
|
|
174
|
+
return { disabledTools: [], defaultJsonView: false };
|
|
173
175
|
}
|
|
174
176
|
|
|
175
177
|
async function loadSettings(): Promise<ToolSettings> {
|
|
176
178
|
try {
|
|
177
179
|
const raw = JSON.parse(await fs.readFile(SETTINGS_PATH, 'utf8'));
|
|
178
180
|
if (!raw || typeof raw !== 'object' || !Array.isArray(raw.disabledTools)) {
|
|
179
|
-
|
|
181
|
+
const settings = createDefaultSettings();
|
|
182
|
+
setDefaultJsonView(settings.defaultJsonView);
|
|
183
|
+
return settings;
|
|
180
184
|
}
|
|
181
|
-
|
|
185
|
+
const settings = {
|
|
182
186
|
disabledTools: raw.disabledTools.filter((t: unknown) => typeof t === 'string'),
|
|
187
|
+
defaultJsonView: typeof raw.defaultJsonView === 'boolean' ? raw.defaultJsonView : false,
|
|
183
188
|
};
|
|
189
|
+
setDefaultJsonView(settings.defaultJsonView);
|
|
190
|
+
return settings;
|
|
184
191
|
} catch {
|
|
185
|
-
|
|
192
|
+
const settings = createDefaultSettings();
|
|
193
|
+
setDefaultJsonView(settings.defaultJsonView);
|
|
194
|
+
return settings;
|
|
186
195
|
}
|
|
187
196
|
}
|
|
188
197
|
|
|
189
198
|
async function saveSettings(settings: ToolSettings): Promise<boolean> {
|
|
190
199
|
try {
|
|
200
|
+
setDefaultJsonView(settings.defaultJsonView);
|
|
191
201
|
await fs.mkdir(dirname(SETTINGS_PATH), { recursive: true });
|
|
192
202
|
await fs.writeFile(SETTINGS_PATH, `${JSON.stringify(settings, null, 2)}\n`, 'utf8');
|
|
193
203
|
return true;
|
|
@@ -256,8 +266,21 @@ function frameBody(title: string, bodyLines: string[], inner: number): string[]
|
|
|
256
266
|
return [top, ...framedBody, bottom];
|
|
257
267
|
}
|
|
258
268
|
|
|
269
|
+
function defaultOutputViewValue(settings: ToolSettings): string {
|
|
270
|
+
return settings.defaultJsonView ? 'Full JSON' : 'Human readable';
|
|
271
|
+
}
|
|
272
|
+
|
|
259
273
|
function buildItems(settings: ToolSettings): SettingItem[] {
|
|
260
|
-
const items: SettingItem[] = [
|
|
274
|
+
const items: SettingItem[] = [
|
|
275
|
+
{
|
|
276
|
+
id: 'defaultJsonView',
|
|
277
|
+
label: 'Default output view',
|
|
278
|
+
description:
|
|
279
|
+
'Controls Linear tool result display. Ctrl+O toggles the other view per tool call.',
|
|
280
|
+
currentValue: defaultOutputViewValue(settings),
|
|
281
|
+
values: ['Human readable', 'Full JSON'],
|
|
282
|
+
},
|
|
283
|
+
];
|
|
261
284
|
for (const category of TOOL_CATEGORIES) {
|
|
262
285
|
items.push({
|
|
263
286
|
id: `category:${category.id}`,
|
|
@@ -308,7 +331,7 @@ async function showToolSettingsOverlay(
|
|
|
308
331
|
() => {},
|
|
309
332
|
);
|
|
310
333
|
const probeLines = probeList.render(Math.max(8, OVERLAY_MAX_INNER - 2));
|
|
311
|
-
const overlayBodyLines = ['
|
|
334
|
+
const overlayBodyLines = ['Configure Linear output and enabled tools', '', ...probeLines];
|
|
312
335
|
const overlayWidth = computeOverlayInner(overlayBodyLines, OVERLAY_MAX_INNER + 2) + 2;
|
|
313
336
|
|
|
314
337
|
await ctx.ui.custom(
|
|
@@ -318,6 +341,16 @@ async function showToolSettingsOverlay(
|
|
|
318
341
|
maxVisibleItems,
|
|
319
342
|
settingsTheme,
|
|
320
343
|
async (id, newValue) => {
|
|
344
|
+
if (id === 'defaultJsonView') {
|
|
345
|
+
const previousDefaultJsonView = settings.defaultJsonView;
|
|
346
|
+
settings.defaultJsonView = newValue === 'Full JSON';
|
|
347
|
+
await saveSettings(settings);
|
|
348
|
+
if (settings.defaultJsonView !== previousDefaultJsonView) {
|
|
349
|
+
invalidateLinearResultRenderers();
|
|
350
|
+
}
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
321
354
|
const nextEnabled = newValue === '[x]';
|
|
322
355
|
|
|
323
356
|
if (id.startsWith('category:')) {
|
|
@@ -364,7 +397,7 @@ async function showToolSettingsOverlay(
|
|
|
364
397
|
const provisionalInner = Math.max(24, Math.min(safeWidth - 2, OVERLAY_MAX_INNER));
|
|
365
398
|
const listLines = settingsList.render(Math.max(8, provisionalInner - 2));
|
|
366
399
|
const bodyLines = [
|
|
367
|
-
theme.fg('muted', '
|
|
400
|
+
theme.fg('muted', 'Configure Linear output and enabled tools'),
|
|
368
401
|
'',
|
|
369
402
|
...listLines,
|
|
370
403
|
];
|
|
@@ -5,6 +5,15 @@ import { PaginationParams, FilterParam, RawInputParam } from '../params';
|
|
|
5
5
|
import { COMMENT_SELECTION } from '../selections';
|
|
6
6
|
import type { JsonObject } from '../types';
|
|
7
7
|
import { compactObject, asObject, asString, GenericObjectSchema } from '../util';
|
|
8
|
+
import {
|
|
9
|
+
renderLinearCommentListCall,
|
|
10
|
+
renderLinearCommentListResult,
|
|
11
|
+
renderLinearCommentResult,
|
|
12
|
+
renderLinearCreateCommentCall,
|
|
13
|
+
renderLinearDeleteCommentCall,
|
|
14
|
+
renderLinearDeleteCommentResult,
|
|
15
|
+
renderLinearUpdateCommentCall,
|
|
16
|
+
} from '../renderers/comments';
|
|
8
17
|
|
|
9
18
|
export function commentTools() {
|
|
10
19
|
return [
|
|
@@ -16,6 +25,7 @@ export function commentTools() {
|
|
|
16
25
|
...PaginationParams,
|
|
17
26
|
...FilterParam,
|
|
18
27
|
}),
|
|
28
|
+
renderCall: renderLinearCommentListCall,
|
|
19
29
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
20
30
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
21
31
|
const variables = compactObject({
|
|
@@ -66,6 +76,7 @@ export function commentTools() {
|
|
|
66
76
|
};
|
|
67
77
|
});
|
|
68
78
|
},
|
|
79
|
+
renderResult: renderLinearCommentListResult,
|
|
69
80
|
}),
|
|
70
81
|
defineTool({
|
|
71
82
|
name: 'linear_create_comment',
|
|
@@ -90,6 +101,7 @@ export function commentTools() {
|
|
|
90
101
|
subscriberIds: Type.Optional(Type.Array(Type.String())),
|
|
91
102
|
...RawInputParam,
|
|
92
103
|
}),
|
|
104
|
+
renderCall: renderLinearCreateCommentCall,
|
|
93
105
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
94
106
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
95
107
|
const rawInput = asObject(params.input) || {};
|
|
@@ -146,6 +158,7 @@ export function commentTools() {
|
|
|
146
158
|
};
|
|
147
159
|
});
|
|
148
160
|
},
|
|
161
|
+
renderResult: renderLinearCommentResult('Created comment'),
|
|
149
162
|
}),
|
|
150
163
|
defineTool({
|
|
151
164
|
name: 'linear_update_comment',
|
|
@@ -157,6 +170,7 @@ export function commentTools() {
|
|
|
157
170
|
quotedText: Type.Optional(Type.String()),
|
|
158
171
|
...RawInputParam,
|
|
159
172
|
}),
|
|
173
|
+
renderCall: renderLinearUpdateCommentCall,
|
|
160
174
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
161
175
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
162
176
|
const rawInput = asObject(params.input) || {};
|
|
@@ -199,6 +213,7 @@ export function commentTools() {
|
|
|
199
213
|
};
|
|
200
214
|
});
|
|
201
215
|
},
|
|
216
|
+
renderResult: renderLinearCommentResult('Updated comment'),
|
|
202
217
|
}),
|
|
203
218
|
defineTool({
|
|
204
219
|
name: 'linear_delete_comment',
|
|
@@ -207,6 +222,7 @@ export function commentTools() {
|
|
|
207
222
|
parameters: Type.Object({
|
|
208
223
|
id: Type.String(),
|
|
209
224
|
}),
|
|
225
|
+
renderCall: renderLinearDeleteCommentCall,
|
|
210
226
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
211
227
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
212
228
|
const data = await linearGraphQL<{
|
|
@@ -232,6 +248,7 @@ export function commentTools() {
|
|
|
232
248
|
};
|
|
233
249
|
});
|
|
234
250
|
},
|
|
251
|
+
renderResult: renderLinearDeleteCommentResult,
|
|
235
252
|
}),
|
|
236
253
|
];
|
|
237
254
|
}
|
|
@@ -5,6 +5,17 @@ import { PaginationParams, FilterParam, RawInputParam, TeamConvenienceParams } f
|
|
|
5
5
|
import { DOCUMENT_SELECTION } from '../selections';
|
|
6
6
|
import type { JsonObject } from '../types';
|
|
7
7
|
import { compactObject, asObject, asString } from '../util';
|
|
8
|
+
import {
|
|
9
|
+
renderLinearCreateDocumentCall,
|
|
10
|
+
renderLinearDeleteDocumentCall,
|
|
11
|
+
renderLinearDocumentListCall,
|
|
12
|
+
renderLinearDocumentListResult,
|
|
13
|
+
renderLinearDocumentResult,
|
|
14
|
+
renderLinearDocumentSuccessResult,
|
|
15
|
+
renderLinearGetDocumentCall,
|
|
16
|
+
renderLinearUnarchiveDocumentCall,
|
|
17
|
+
renderLinearUpdateDocumentCall,
|
|
18
|
+
} from '../renderers/documents';
|
|
8
19
|
|
|
9
20
|
export function documentTools() {
|
|
10
21
|
return [
|
|
@@ -16,6 +27,7 @@ export function documentTools() {
|
|
|
16
27
|
...PaginationParams,
|
|
17
28
|
...FilterParam,
|
|
18
29
|
}),
|
|
30
|
+
renderCall: renderLinearDocumentListCall,
|
|
19
31
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
20
32
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
21
33
|
const variables = compactObject({
|
|
@@ -66,6 +78,7 @@ export function documentTools() {
|
|
|
66
78
|
};
|
|
67
79
|
});
|
|
68
80
|
},
|
|
81
|
+
renderResult: renderLinearDocumentListResult,
|
|
69
82
|
}),
|
|
70
83
|
defineTool({
|
|
71
84
|
name: 'linear_get_document',
|
|
@@ -74,6 +87,7 @@ export function documentTools() {
|
|
|
74
87
|
parameters: Type.Object({
|
|
75
88
|
documentId: Type.String(),
|
|
76
89
|
}),
|
|
90
|
+
renderCall: renderLinearGetDocumentCall,
|
|
77
91
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
78
92
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
79
93
|
const data = await linearGraphQL<{ document: JsonObject | null }>(
|
|
@@ -96,6 +110,7 @@ export function documentTools() {
|
|
|
96
110
|
};
|
|
97
111
|
});
|
|
98
112
|
},
|
|
113
|
+
renderResult: renderLinearDocumentResult('Document'),
|
|
99
114
|
}),
|
|
100
115
|
defineTool({
|
|
101
116
|
name: 'linear_create_document',
|
|
@@ -120,6 +135,7 @@ export function documentTools() {
|
|
|
120
135
|
title: Type.Optional(Type.String()),
|
|
121
136
|
...RawInputParam,
|
|
122
137
|
}),
|
|
138
|
+
renderCall: renderLinearCreateDocumentCall,
|
|
123
139
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
124
140
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
125
141
|
const rawInput = asObject(params.input) || {};
|
|
@@ -188,6 +204,7 @@ export function documentTools() {
|
|
|
188
204
|
};
|
|
189
205
|
});
|
|
190
206
|
},
|
|
207
|
+
renderResult: renderLinearDocumentResult('Created document'),
|
|
191
208
|
}),
|
|
192
209
|
defineTool({
|
|
193
210
|
name: 'linear_update_document',
|
|
@@ -214,6 +231,7 @@ export function documentTools() {
|
|
|
214
231
|
trashed: Type.Optional(Type.Boolean()),
|
|
215
232
|
...RawInputParam,
|
|
216
233
|
}),
|
|
234
|
+
renderCall: renderLinearUpdateDocumentCall,
|
|
217
235
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
218
236
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
219
237
|
const rawInput = asObject(params.input) || {};
|
|
@@ -286,6 +304,7 @@ export function documentTools() {
|
|
|
286
304
|
};
|
|
287
305
|
});
|
|
288
306
|
},
|
|
307
|
+
renderResult: renderLinearDocumentResult('Updated document'),
|
|
289
308
|
}),
|
|
290
309
|
defineTool({
|
|
291
310
|
name: 'linear_delete_document',
|
|
@@ -294,6 +313,7 @@ export function documentTools() {
|
|
|
294
313
|
parameters: Type.Object({
|
|
295
314
|
documentId: Type.String(),
|
|
296
315
|
}),
|
|
316
|
+
renderCall: renderLinearDeleteDocumentCall,
|
|
297
317
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
298
318
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
299
319
|
const data = await linearGraphQL<{
|
|
@@ -319,6 +339,7 @@ export function documentTools() {
|
|
|
319
339
|
};
|
|
320
340
|
});
|
|
321
341
|
},
|
|
342
|
+
renderResult: renderLinearDocumentSuccessResult('Deleted'),
|
|
322
343
|
}),
|
|
323
344
|
defineTool({
|
|
324
345
|
name: 'linear_unarchive_document',
|
|
@@ -327,6 +348,7 @@ export function documentTools() {
|
|
|
327
348
|
parameters: Type.Object({
|
|
328
349
|
documentId: Type.String(),
|
|
329
350
|
}),
|
|
351
|
+
renderCall: renderLinearUnarchiveDocumentCall,
|
|
330
352
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
331
353
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
332
354
|
const data = await linearGraphQL<{
|
|
@@ -352,6 +374,7 @@ export function documentTools() {
|
|
|
352
374
|
};
|
|
353
375
|
});
|
|
354
376
|
},
|
|
377
|
+
renderResult: renderLinearDocumentSuccessResult('Unarchived'),
|
|
355
378
|
}),
|
|
356
379
|
];
|
|
357
380
|
}
|
|
@@ -5,6 +5,18 @@ import { PaginationParams, FilterParam, SortParam, RawInputParam } from '../para
|
|
|
5
5
|
import { INITIATIVE_SELECTION } from '../selections';
|
|
6
6
|
import type { JsonObject } from '../types';
|
|
7
7
|
import { compactObject, asObject, asObjectArray, asString } from '../util';
|
|
8
|
+
import {
|
|
9
|
+
renderLinearArchiveInitiativeCall,
|
|
10
|
+
renderLinearDeleteInitiativeCall,
|
|
11
|
+
renderLinearGetInitiativeCall,
|
|
12
|
+
renderLinearInitiativeListCall,
|
|
13
|
+
renderLinearInitiativeListResult,
|
|
14
|
+
renderLinearInitiativeResult,
|
|
15
|
+
renderLinearInitiativeSuccessResult,
|
|
16
|
+
renderLinearSaveInitiativeCall,
|
|
17
|
+
renderLinearSaveInitiativeResult,
|
|
18
|
+
renderLinearUnarchiveInitiativeCall,
|
|
19
|
+
} from '../renderers/initiatives';
|
|
8
20
|
|
|
9
21
|
export function initiativeTools() {
|
|
10
22
|
return [
|
|
@@ -17,6 +29,7 @@ export function initiativeTools() {
|
|
|
17
29
|
...FilterParam,
|
|
18
30
|
...SortParam,
|
|
19
31
|
}),
|
|
32
|
+
renderCall: renderLinearInitiativeListCall,
|
|
20
33
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
21
34
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
22
35
|
const variables = compactObject({
|
|
@@ -70,6 +83,7 @@ export function initiativeTools() {
|
|
|
70
83
|
};
|
|
71
84
|
});
|
|
72
85
|
},
|
|
86
|
+
renderResult: renderLinearInitiativeListResult,
|
|
73
87
|
}),
|
|
74
88
|
defineTool({
|
|
75
89
|
name: 'linear_get_initiative',
|
|
@@ -78,6 +92,7 @@ export function initiativeTools() {
|
|
|
78
92
|
parameters: Type.Object({
|
|
79
93
|
initiativeId: Type.String(),
|
|
80
94
|
}),
|
|
95
|
+
renderCall: renderLinearGetInitiativeCall,
|
|
81
96
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
82
97
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
83
98
|
const data = await linearGraphQL<{ initiative: JsonObject | null }>(
|
|
@@ -100,6 +115,7 @@ export function initiativeTools() {
|
|
|
100
115
|
};
|
|
101
116
|
});
|
|
102
117
|
},
|
|
118
|
+
renderResult: renderLinearInitiativeResult('Initiative'),
|
|
103
119
|
}),
|
|
104
120
|
defineTool({
|
|
105
121
|
name: 'linear_save_initiative',
|
|
@@ -127,6 +143,7 @@ export function initiativeTools() {
|
|
|
127
143
|
updateRemindersHour: Type.Optional(Type.Integer()),
|
|
128
144
|
...RawInputParam,
|
|
129
145
|
}),
|
|
146
|
+
renderCall: renderLinearSaveInitiativeCall,
|
|
130
147
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
131
148
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
132
149
|
const rawInput = asObject(params.input) || {};
|
|
@@ -224,6 +241,7 @@ export function initiativeTools() {
|
|
|
224
241
|
};
|
|
225
242
|
});
|
|
226
243
|
},
|
|
244
|
+
renderResult: renderLinearSaveInitiativeResult,
|
|
227
245
|
}),
|
|
228
246
|
defineTool({
|
|
229
247
|
name: 'linear_delete_initiative',
|
|
@@ -232,6 +250,7 @@ export function initiativeTools() {
|
|
|
232
250
|
parameters: Type.Object({
|
|
233
251
|
initiativeId: Type.String(),
|
|
234
252
|
}),
|
|
253
|
+
renderCall: renderLinearDeleteInitiativeCall,
|
|
235
254
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
236
255
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
237
256
|
const data = await linearGraphQL<{
|
|
@@ -257,6 +276,7 @@ export function initiativeTools() {
|
|
|
257
276
|
};
|
|
258
277
|
});
|
|
259
278
|
},
|
|
279
|
+
renderResult: renderLinearInitiativeSuccessResult('Deleted'),
|
|
260
280
|
}),
|
|
261
281
|
defineTool({
|
|
262
282
|
name: 'linear_archive_initiative',
|
|
@@ -265,6 +285,7 @@ export function initiativeTools() {
|
|
|
265
285
|
parameters: Type.Object({
|
|
266
286
|
initiativeId: Type.String(),
|
|
267
287
|
}),
|
|
288
|
+
renderCall: renderLinearArchiveInitiativeCall,
|
|
268
289
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
269
290
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
270
291
|
const data = await linearGraphQL<{
|
|
@@ -290,6 +311,7 @@ export function initiativeTools() {
|
|
|
290
311
|
};
|
|
291
312
|
});
|
|
292
313
|
},
|
|
314
|
+
renderResult: renderLinearInitiativeSuccessResult('Archived'),
|
|
293
315
|
}),
|
|
294
316
|
defineTool({
|
|
295
317
|
name: 'linear_unarchive_initiative',
|
|
@@ -298,6 +320,7 @@ export function initiativeTools() {
|
|
|
298
320
|
parameters: Type.Object({
|
|
299
321
|
initiativeId: Type.String(),
|
|
300
322
|
}),
|
|
323
|
+
renderCall: renderLinearUnarchiveInitiativeCall,
|
|
301
324
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
302
325
|
return withLinearAuth(ctx, signal, async (apiKey) => {
|
|
303
326
|
const data = await linearGraphQL<{
|
|
@@ -323,6 +346,7 @@ export function initiativeTools() {
|
|
|
323
346
|
};
|
|
324
347
|
});
|
|
325
348
|
},
|
|
349
|
+
renderResult: renderLinearInitiativeSuccessResult('Unarchived'),
|
|
326
350
|
}),
|
|
327
351
|
];
|
|
328
352
|
}
|