@elizaos/plugin-linear 1.2.5 → 1.2.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/dist/index.js CHANGED
@@ -360,770 +360,992 @@ var LinearService = _LinearService;
360
360
 
361
361
  // src/actions/createIssue.ts
362
362
  import {
363
+ ModelType,
363
364
  logger as logger2
364
365
  } from "@elizaos/core";
365
- var createIssueTemplate = `Create a new Linear issue based on the user's request. Extract the necessary information from the conversation.
366
+ var createIssueTemplate = `Given the user's request, extract the information needed to create a Linear issue.
366
367
 
367
- Recent conversation:
368
- {{recentMessages}}
368
+ User request: "{{userMessage}}"
369
369
 
370
- When creating the issue:
371
- 1. The title should be clear and concise
372
- 2. The description should include all relevant details from the conversation
373
- 3. Determine the appropriate team based on context
374
- 4. Set priority if mentioned (1=Urgent, 2=High, 3=Normal, 4=Low)
375
- 5. If no team is specified, use the default team
376
-
377
- Response format should be a valid JSON block:
378
- \`\`\`json
370
+ Extract and return a JSON object with the following structure:
379
371
  {
380
- "title": "Clear, actionable issue title",
381
- "description": "Detailed description with context from the conversation",
382
- "teamId": "team-id or null to use default",
383
- "priority": 3,
384
- "shouldCreate": true
372
+ "title": "Brief, clear issue title",
373
+ "description": "Detailed description of the issue (optional)",
374
+ "teamKey": "Team key if mentioned (e.g., ENG, PROD)",
375
+ "priority": "Priority level if mentioned (1=urgent, 2=high, 3=normal, 4=low)",
376
+ "labels": ["label1", "label2"] (if any labels are mentioned),
377
+ "assignee": "Assignee username or email if mentioned"
385
378
  }
386
- \`\`\`
387
- `;
388
- var createLinearIssueAction = {
379
+
380
+ Return only the JSON object, no other text.`;
381
+ var createIssueAction = {
389
382
  name: "CREATE_LINEAR_ISSUE",
390
383
  description: "Create a new issue in Linear",
391
- similes: ["create issue", "new issue", "file issue", "report issue", "create ticket", "new ticket"],
392
- async validate(runtime, _message, state) {
384
+ similes: ["create-linear-issue", "new-linear-issue", "add-linear-issue"],
385
+ examples: [[
386
+ {
387
+ name: "User",
388
+ content: {
389
+ text: "Create a new issue: Fix login button not working on mobile devices"
390
+ }
391
+ },
392
+ {
393
+ name: "Assistant",
394
+ content: {
395
+ text: "I'll create that issue for you in Linear.",
396
+ actions: ["CREATE_LINEAR_ISSUE"]
397
+ }
398
+ }
399
+ ], [
400
+ {
401
+ name: "User",
402
+ content: {
403
+ text: "Create a bug report for the ENG team: API returns 500 error when updating user profile"
404
+ }
405
+ },
406
+ {
407
+ name: "Assistant",
408
+ content: {
409
+ text: "I'll create a bug report for the engineering team right away.",
410
+ actions: ["CREATE_LINEAR_ISSUE"]
411
+ }
412
+ }
413
+ ]],
414
+ async validate(runtime, _message, _state) {
393
415
  try {
394
- const linearService = runtime.getService("linear");
395
- return !!linearService;
416
+ const apiKey = runtime.getSetting("LINEAR_API_KEY");
417
+ return !!apiKey;
396
418
  } catch {
397
419
  return false;
398
420
  }
399
421
  },
400
- async handler(runtime, message, state, options) {
422
+ async handler(runtime, message, _state, _options) {
401
423
  try {
402
424
  const linearService = runtime.getService("linear");
403
425
  if (!linearService) {
404
426
  throw new Error("Linear service not available");
405
427
  }
406
- if (options?.title && options?.teamId) {
407
- const issueInput2 = {
408
- title: String(options.title),
409
- description: options.description ? String(options.description) : void 0,
410
- teamId: String(options.teamId),
411
- priority: options.priority ? Number(options.priority) : 3,
412
- assigneeId: options.assigneeId ? String(options.assigneeId) : void 0,
413
- labelIds: options.labelIds ? options.labelIds : void 0,
414
- projectId: options.projectId ? String(options.projectId) : void 0
415
- };
416
- const issue2 = await linearService.createIssue(issueInput2);
428
+ const content = message.content.text;
429
+ if (!content) {
417
430
  return {
418
- success: true,
419
- data: {
420
- issue: {
421
- id: issue2.id,
422
- identifier: issue2.identifier,
423
- title: issue2.title,
424
- url: issue2.url
425
- }
426
- },
427
- metadata: {
428
- issueId: issue2.id,
429
- identifier: issue2.identifier
430
- }
431
- };
432
- }
433
- const response = await runtime.generateText({
434
- messages: state.messages || [],
435
- context: createIssueTemplate
436
- });
437
- const parsed = JSON.parse(response.trim().replace(/```json\n?|\n?```/g, ""));
438
- if (!parsed.shouldCreate) {
439
- return {
440
- success: false,
441
- error: "Not enough information to create an issue"
431
+ text: "Please provide a description for the issue.",
432
+ success: false
442
433
  };
443
434
  }
444
- let teamId = parsed.teamId;
445
- let teamName;
446
- if (!teamId) {
447
- const teams = await linearService.getTeams();
448
- if (teams.length === 0) {
449
- throw new Error("No teams available in Linear workspace");
450
- }
451
- teamId = teams[0].id;
452
- teamName = teams[0].name;
435
+ const structuredData = _options?.issueData;
436
+ let issueData;
437
+ if (structuredData) {
438
+ issueData = structuredData;
453
439
  } else {
440
+ const prompt = createIssueTemplate.replace("{{userMessage}}", content);
441
+ const response = await runtime.useModel(ModelType.TEXT_LARGE, {
442
+ prompt
443
+ });
444
+ if (!response) {
445
+ throw new Error("Failed to extract issue information");
446
+ }
454
447
  try {
455
- const team = await linearService.getTeam(teamId);
456
- teamName = team.name;
457
- } catch {
448
+ const parsed = JSON.parse(response);
449
+ issueData = {
450
+ title: parsed.title,
451
+ description: parsed.description,
452
+ priority: parsed.priority
453
+ };
454
+ if (parsed.teamKey) {
455
+ const teams = await linearService.getTeams();
456
+ const team = teams.find(
457
+ (t) => t.key.toLowerCase() === parsed.teamKey.toLowerCase()
458
+ );
459
+ if (team) {
460
+ issueData.teamId = team.id;
461
+ }
462
+ }
463
+ if (parsed.assignee) {
464
+ const users = await linearService.getUsers();
465
+ const user = users.find(
466
+ (u) => u.email === parsed.assignee || u.name.toLowerCase().includes(parsed.assignee.toLowerCase())
467
+ );
468
+ if (user) {
469
+ issueData.assigneeId = user.id;
470
+ }
471
+ }
472
+ } catch (parseError) {
473
+ logger2.error("Failed to parse LLM response:", parseError);
474
+ issueData = {
475
+ title: content.length > 100 ? content.substring(0, 100) + "..." : content,
476
+ description: content
477
+ };
458
478
  }
459
479
  }
460
- const issueInput = {
461
- title: parsed.title,
462
- description: parsed.description,
463
- teamId,
464
- priority: parsed.priority || 3
465
- };
466
- const issue = await linearService.createIssue(issueInput);
467
- logger2.info(`Created Linear issue: ${issue.identifier} - ${issue.title}`);
480
+ if (!issueData.title) {
481
+ return {
482
+ text: "Could not determine issue title. Please provide more details.",
483
+ success: false
484
+ };
485
+ }
486
+ const issue = await linearService.createIssue(issueData);
468
487
  return {
488
+ text: `Created issue: ${issue.title} (${issue.identifier})`,
469
489
  success: true,
470
490
  data: {
471
- issue: {
472
- id: issue.id,
473
- identifier: issue.identifier,
474
- title: issue.title,
475
- url: issue.url,
476
- teamName
477
- }
478
- },
479
- metadata: {
480
491
  issueId: issue.id,
481
- identifier: issue.identifier
492
+ identifier: issue.identifier,
493
+ url: issue.url
482
494
  }
483
495
  };
484
496
  } catch (error) {
485
- logger2.error("Failed to create Linear issue:", error);
497
+ logger2.error("Failed to create issue:", error);
486
498
  return {
487
- success: false,
488
- error: error instanceof Error ? error.message : "Failed to create issue"
499
+ text: `Failed to create issue: ${error instanceof Error ? error.message : "Unknown error"}`,
500
+ success: false
489
501
  };
490
502
  }
491
- },
492
- examples: [
503
+ }
504
+ };
505
+
506
+ // src/actions/getIssue.ts
507
+ import { logger as logger3 } from "@elizaos/core";
508
+ var getIssueAction = {
509
+ name: "GET_LINEAR_ISSUE",
510
+ description: "Get details of a specific Linear issue",
511
+ similes: ["get-linear-issue", "show-linear-issue", "view-linear-issue"],
512
+ examples: [[
493
513
  {
494
- input: "Create a new issue: Fix login button not working on mobile devices",
495
- output: "Created issue ENG-123: Fix login button not working on mobile devices",
496
- explanation: "Creates a new issue with the provided title"
514
+ name: "User",
515
+ content: {
516
+ text: "Show me issue ENG-123"
517
+ }
497
518
  },
498
519
  {
499
- input: "File a bug report: Users cannot upload images larger than 5MB, getting timeout errors",
500
- output: "Created issue BUG-456: Image upload timeout for files > 5MB",
501
- explanation: "Creates a bug report with extracted details"
520
+ name: "Assistant",
521
+ content: {
522
+ text: "I'll get the details for issue ENG-123.",
523
+ actions: ["GET_LINEAR_ISSUE"]
524
+ }
525
+ }
526
+ ], [
527
+ {
528
+ name: "User",
529
+ content: {
530
+ text: "What's the status of BUG-456?"
531
+ }
502
532
  },
503
533
  {
504
- input: "Create a high priority ticket for the payment processing error we discussed",
505
- output: "Created high priority issue PAY-789: Payment processing error investigation",
506
- explanation: "Creates an issue with priority based on conversation context"
534
+ name: "Assistant",
535
+ content: {
536
+ text: "Let me check the status of BUG-456 for you.",
537
+ actions: ["GET_LINEAR_ISSUE"]
538
+ }
507
539
  }
508
- ]
509
- };
510
-
511
- // src/actions/getIssue.ts
512
- import {
513
- logger as logger3
514
- } from "@elizaos/core";
515
- var getLinearIssueAction = {
516
- name: "GET_LINEAR_ISSUE",
517
- description: "Get details of a specific Linear issue by ID or identifier",
518
- similes: ["get issue", "show issue", "fetch issue", "view issue", "issue details", "what is issue"],
519
- async validate(runtime, _message, state) {
540
+ ]],
541
+ async validate(runtime, _message, _state) {
520
542
  try {
521
- const linearService = runtime.getService("linear");
522
- return !!linearService;
543
+ const apiKey = runtime.getSetting("LINEAR_API_KEY");
544
+ return !!apiKey;
523
545
  } catch {
524
546
  return false;
525
547
  }
526
548
  },
527
- async handler(runtime, message, state, options) {
549
+ async handler(runtime, message, _state, _options) {
528
550
  try {
529
551
  const linearService = runtime.getService("linear");
530
552
  if (!linearService) {
531
553
  throw new Error("Linear service not available");
532
554
  }
533
- let issueId;
534
- if (options?.issueId) {
535
- issueId = String(options.issueId);
536
- } else {
537
- const issuePattern = /\b[A-Z]+-\d+\b/;
538
- const match = message.content.text?.match(issuePattern);
539
- if (match) {
540
- issueId = match[0];
541
- }
555
+ const content = message.content.text;
556
+ if (!content) {
557
+ return {
558
+ text: "Please specify an issue ID.",
559
+ success: false
560
+ };
542
561
  }
543
- if (!issueId) {
562
+ const issueMatch = content.match(/(\w+-\d+)/);
563
+ if (!issueMatch) {
544
564
  return {
545
- success: false,
546
- error: "No issue ID or identifier provided"
565
+ text: "Please provide a valid issue ID (e.g., ENG-123).",
566
+ success: false
547
567
  };
548
568
  }
569
+ const issueId = issueMatch[1];
549
570
  const issue = await linearService.getIssue(issueId);
550
- const [assignee, state2, team, labels] = await Promise.all([
551
- issue.assignee,
552
- issue.state,
553
- issue.team,
554
- issue.labels()
555
- ]);
556
- const labelList = await labels.nodes;
557
- const issueData = {
571
+ const assignee = await issue.assignee;
572
+ const state = await issue.state;
573
+ const team = await issue.team;
574
+ const labels = await issue.labels();
575
+ const project = await issue.project;
576
+ const issueDetails = {
558
577
  id: issue.id,
559
578
  identifier: issue.identifier,
560
579
  title: issue.title,
561
580
  description: issue.description,
562
- url: issue.url,
563
581
  priority: issue.priority,
564
582
  priorityLabel: issue.priorityLabel,
565
- estimate: issue.estimate,
583
+ url: issue.url,
566
584
  createdAt: issue.createdAt,
567
585
  updatedAt: issue.updatedAt,
568
586
  dueDate: issue.dueDate,
587
+ estimate: issue.estimate,
569
588
  assignee: assignee ? {
570
589
  id: assignee.id,
571
590
  name: assignee.name,
572
591
  email: assignee.email
573
592
  } : null,
574
- state: {
575
- id: state2.id,
576
- name: state2.name,
577
- type: state2.type,
578
- color: state2.color
579
- },
580
- team: {
593
+ state: state ? {
594
+ id: state.id,
595
+ name: state.name,
596
+ type: state.type,
597
+ color: state.color
598
+ } : null,
599
+ team: team ? {
581
600
  id: team.id,
582
601
  name: team.name,
583
602
  key: team.key
584
- },
585
- labels: labelList.map((label) => ({
603
+ } : null,
604
+ labels: labels.nodes.map((label) => ({
586
605
  id: label.id,
587
606
  name: label.name,
588
607
  color: label.color
589
- }))
608
+ })),
609
+ project: project ? {
610
+ id: project.id,
611
+ name: project.name
612
+ } : null
590
613
  };
591
- logger3.info(`Retrieved Linear issue: ${issue.identifier}`);
614
+ let responseText = `Issue ${issue.identifier}: ${issue.title}
615
+ `;
616
+ responseText += `Status: ${state?.name || "Unknown"}
617
+ `;
618
+ responseText += `Priority: ${issue.priorityLabel}
619
+ `;
620
+ if (assignee) {
621
+ responseText += `Assignee: ${assignee.name}
622
+ `;
623
+ }
624
+ if (issue.dueDate) {
625
+ responseText += `Due: ${new Date(issue.dueDate).toLocaleDateString()}
626
+ `;
627
+ }
628
+ if (issue.description) {
629
+ responseText += `
630
+ Description: ${issue.description}
631
+ `;
632
+ }
633
+ responseText += `
634
+ View in Linear: ${issue.url}`;
592
635
  return {
636
+ text: responseText,
593
637
  success: true,
594
- data: {
595
- issue: issueData
596
- },
597
- metadata: {
598
- issueId: issue.id,
599
- identifier: issue.identifier
600
- }
638
+ data: issueDetails
601
639
  };
602
640
  } catch (error) {
603
- logger3.error("Failed to get Linear issue:", error);
641
+ logger3.error("Failed to get issue:", error);
604
642
  return {
605
- success: false,
606
- error: error instanceof Error ? error.message : "Failed to get issue"
643
+ text: `Failed to get issue: ${error instanceof Error ? error.message : "Unknown error"}`,
644
+ success: false
607
645
  };
608
646
  }
609
- },
610
- examples: [
647
+ }
648
+ };
649
+
650
+ // src/actions/updateIssue.ts
651
+ import { logger as logger4 } from "@elizaos/core";
652
+ var updateIssueAction = {
653
+ name: "UPDATE_LINEAR_ISSUE",
654
+ description: "Update an existing Linear issue",
655
+ similes: ["update-linear-issue", "edit-linear-issue", "modify-linear-issue"],
656
+ examples: [[
611
657
  {
612
- input: "Show me issue ENG-123",
613
- output: "Issue ENG-123: Fix login button on mobile\nStatus: In Progress\nAssignee: John Doe\nPriority: High",
614
- explanation: "Retrieves issue details by identifier"
658
+ name: "User",
659
+ content: {
660
+ text: 'Update issue ENG-123 title to "Fix login button on all devices"'
661
+ }
615
662
  },
616
663
  {
617
- input: "Get details for BUG-456",
618
- output: "Issue BUG-456: Image upload timeout\nStatus: Todo\nAssignee: Unassigned\nPriority: Urgent\nLabels: bug, performance",
619
- explanation: "Fetches comprehensive issue information"
664
+ name: "Assistant",
665
+ content: {
666
+ text: "I'll update the title of issue ENG-123 for you.",
667
+ actions: ["UPDATE_LINEAR_ISSUE"]
668
+ }
669
+ }
670
+ ], [
671
+ {
672
+ name: "User",
673
+ content: {
674
+ text: "Change the priority of BUG-456 to high"
675
+ }
620
676
  },
621
677
  {
622
- input: "What is the status of FEAT-789?",
623
- output: "Issue FEAT-789: Add dark mode support\nStatus: Done\nAssignee: Jane Smith\nCompleted: 2 days ago",
624
- explanation: "Shows current status and details of an issue"
678
+ name: "Assistant",
679
+ content: {
680
+ text: "I'll change the priority of BUG-456 to high.",
681
+ actions: ["UPDATE_LINEAR_ISSUE"]
682
+ }
625
683
  }
626
- ]
627
- };
628
-
629
- // src/actions/updateIssue.ts
630
- import {
631
- logger as logger4
632
- } from "@elizaos/core";
633
- var updateLinearIssueAction = {
634
- name: "UPDATE_LINEAR_ISSUE",
635
- description: "Update an existing Linear issue",
636
- similes: ["update issue", "modify issue", "change issue", "edit issue"],
637
- async validate(runtime, _message, state) {
684
+ ]],
685
+ async validate(runtime, _message, _state) {
638
686
  try {
639
- const linearService = runtime.getService("linear");
640
- return !!linearService;
687
+ const apiKey = runtime.getSetting("LINEAR_API_KEY");
688
+ return !!apiKey;
641
689
  } catch {
642
690
  return false;
643
691
  }
644
692
  },
645
- async handler(runtime, message, state, options) {
693
+ async handler(runtime, message, _state, _options) {
646
694
  try {
647
695
  const linearService = runtime.getService("linear");
648
696
  if (!linearService) {
649
697
  throw new Error("Linear service not available");
650
698
  }
651
- const issueId = options?.issueId ? String(options.issueId) : void 0;
652
- if (!issueId) {
699
+ const content = message.content.text;
700
+ if (!content) {
653
701
  return {
654
- success: false,
655
- error: "Issue ID is required"
702
+ text: "Please provide update instructions for the issue.",
703
+ success: false
656
704
  };
657
705
  }
706
+ const issueMatch = content.match(/(\w+-\d+)/);
707
+ if (!issueMatch) {
708
+ return {
709
+ text: "Please specify an issue ID (e.g., ENG-123) to update.",
710
+ success: false
711
+ };
712
+ }
713
+ const issueId = issueMatch[1];
658
714
  const updates = {};
659
- if (options?.title !== void 0) updates.title = String(options.title);
660
- if (options?.description !== void 0) updates.description = String(options.description);
661
- if (options?.priority !== void 0) updates.priority = Number(options.priority);
662
- if (options?.assigneeId !== void 0) updates.assigneeId = String(options.assigneeId);
663
- if (options?.stateId !== void 0) updates.stateId = String(options.stateId);
664
- if (options?.labelIds !== void 0) updates.labelIds = options.labelIds;
665
- if (options?.projectId !== void 0) updates.projectId = String(options.projectId);
666
- if (options?.estimate !== void 0) updates.estimate = Number(options.estimate);
667
- if (options?.dueDate !== void 0) updates.dueDate = new Date(String(options.dueDate));
668
- const issue = await linearService.updateIssue(issueId, updates);
669
- logger4.info(`Updated Linear issue: ${issue.identifier}`);
715
+ const titleMatch = content.match(/title to ["'](.+?)["']/i);
716
+ if (titleMatch) {
717
+ updates.title = titleMatch[1];
718
+ }
719
+ const priorityMatch = content.match(/priority (?:to |as )?(\w+)/i);
720
+ if (priorityMatch) {
721
+ const priorityMap = {
722
+ "urgent": 1,
723
+ "high": 2,
724
+ "normal": 3,
725
+ "medium": 3,
726
+ "low": 4
727
+ };
728
+ const priority = priorityMap[priorityMatch[1].toLowerCase()];
729
+ if (priority) {
730
+ updates.priority = priority;
731
+ }
732
+ }
733
+ const descMatch = content.match(/description to ["'](.+?)["']/i);
734
+ if (descMatch) {
735
+ updates.description = descMatch[1];
736
+ }
737
+ const statusMatch = content.match(/status to (\w+)/i);
738
+ if (statusMatch) {
739
+ logger4.warn("Status updates not yet implemented");
740
+ }
741
+ if (Object.keys(updates).length === 0) {
742
+ return {
743
+ text: `No valid updates found. Please specify what to update (e.g., "Update issue ENG-123 title to 'New Title'")`,
744
+ success: false
745
+ };
746
+ }
747
+ const updatedIssue = await linearService.updateIssue(issueId, updates);
748
+ const updateSummary = Object.entries(updates).map(([key, value]) => `${key}: ${value}`).join(", ");
670
749
  return {
750
+ text: `Updated issue ${updatedIssue.identifier}: ${updateSummary}`,
671
751
  success: true,
672
752
  data: {
673
- issue: {
674
- id: issue.id,
675
- identifier: issue.identifier,
676
- title: issue.title,
677
- url: issue.url
678
- }
679
- },
680
- metadata: {
681
- issueId: issue.id,
682
- identifier: issue.identifier,
683
- updates: Object.keys(updates)
753
+ issueId: updatedIssue.id,
754
+ identifier: updatedIssue.identifier,
755
+ updates,
756
+ url: updatedIssue.url
684
757
  }
685
758
  };
686
759
  } catch (error) {
687
- logger4.error("Failed to update Linear issue:", error);
760
+ logger4.error("Failed to update issue:", error);
688
761
  return {
689
- success: false,
690
- error: error instanceof Error ? error.message : "Failed to update issue"
762
+ text: `Failed to update issue: ${error instanceof Error ? error.message : "Unknown error"}`,
763
+ success: false
691
764
  };
692
765
  }
693
- },
694
- examples: [
695
- {
696
- input: 'Update issue ENG-123 title to "Fix login button on all devices"',
697
- output: "Updated issue ENG-123: Fix login button on all devices",
698
- explanation: "Updates the title of an existing issue"
699
- }
700
- ]
766
+ }
701
767
  };
702
768
 
703
769
  // src/actions/searchIssues.ts
704
770
  import {
771
+ ModelType as ModelType2,
705
772
  logger as logger5
706
773
  } from "@elizaos/core";
707
- var searchIssuesTemplate = `Extract search criteria from the user's request to search Linear issues.
774
+ var searchTemplate = `Extract search criteria from the user's request for Linear issues.
708
775
 
709
- Recent conversation:
710
- {{recentMessages}}
776
+ User request: "{{userMessage}}"
711
777
 
712
- Extract search filters like:
713
- - query: Text to search in title/description
714
- - state: Issue states (todo, in-progress, done, canceled)
715
- - assignee: Assignee names or IDs
716
- - label: Label names
717
- - priority: Priority levels (1=Urgent, 2=High, 3=Normal, 4=Low)
718
- - team: Team name or ID
719
- - project: Project name or ID
720
-
721
- Response format should be a valid JSON block:
722
- \`\`\`json
778
+ Extract and return a JSON object with these possible filters:
723
779
  {
724
- "query": "search text or null",
725
- "state": ["state1", "state2"] or null,
726
- "assignee": ["assignee"] or null,
727
- "label": ["label1", "label2"] or null,
728
- "priority": [1, 2] or null,
729
- "team": "team-name" or null,
730
- "project": "project-name" or null,
731
- "limit": 20
780
+ "query": "general search text",
781
+ "state": "filter by state name (e.g., 'In Progress', 'Done', 'Todo')",
782
+ "assignee": "filter by assignee name or email",
783
+ "priority": "filter by priority (1=urgent, 2=high, 3=normal, 4=low)",
784
+ "team": "filter by team name or key",
785
+ "label": "filter by label name",
786
+ "hasAssignee": true/false - whether issue should have an assignee,
787
+ "limit": number of results to return (default 10)
732
788
  }
733
- \`\`\`
734
- `;
735
- var searchLinearIssuesAction = {
789
+
790
+ Only include fields that are mentioned. Return only the JSON object.`;
791
+ var searchIssuesAction = {
736
792
  name: "SEARCH_LINEAR_ISSUES",
737
- description: "Search for issues in Linear based on various criteria",
738
- similes: ["search issues", "find issues", "list issues", "show issues", "query issues", "filter issues"],
739
- async validate(runtime, _message, state) {
793
+ description: "Search for issues in Linear with various filters",
794
+ similes: ["search-linear-issues", "find-linear-issues", "query-linear-issues"],
795
+ examples: [[
796
+ {
797
+ name: "User",
798
+ content: {
799
+ text: "Show me all open bugs"
800
+ }
801
+ },
802
+ {
803
+ name: "Assistant",
804
+ content: {
805
+ text: "I'll search for all open bug issues in Linear.",
806
+ actions: ["SEARCH_LINEAR_ISSUES"]
807
+ }
808
+ }
809
+ ], [
810
+ {
811
+ name: "User",
812
+ content: {
813
+ text: "Find high priority issues assigned to me"
814
+ }
815
+ },
816
+ {
817
+ name: "Assistant",
818
+ content: {
819
+ text: "I'll search for high priority issues assigned to you.",
820
+ actions: ["SEARCH_LINEAR_ISSUES"]
821
+ }
822
+ }
823
+ ]],
824
+ async validate(runtime, _message, _state) {
740
825
  try {
741
- const linearService = runtime.getService("linear");
742
- return !!linearService;
826
+ const apiKey = runtime.getSetting("LINEAR_API_KEY");
827
+ return !!apiKey;
743
828
  } catch {
744
829
  return false;
745
830
  }
746
831
  },
747
- async handler(runtime, message, state, options) {
832
+ async handler(runtime, message, _state, _options) {
748
833
  try {
749
834
  const linearService = runtime.getService("linear");
750
835
  if (!linearService) {
751
836
  throw new Error("Linear service not available");
752
837
  }
753
- let filters;
754
- if (options && Object.keys(options).length > 0) {
755
- filters = {
756
- query: options.query ? String(options.query) : void 0,
757
- state: options.state,
758
- assignee: options.assignee,
759
- label: options.label,
760
- priority: options.priority,
761
- team: options.team ? String(options.team) : void 0,
762
- project: options.project ? String(options.project) : void 0,
763
- limit: options.limit ? Number(options.limit) : 20
838
+ const content = message.content.text;
839
+ if (!content) {
840
+ return {
841
+ text: "Please provide search criteria for issues.",
842
+ success: false
764
843
  };
844
+ }
845
+ let filters = {};
846
+ if (_options?.filters) {
847
+ filters = _options.filters;
765
848
  } else {
766
- const response = await runtime.generateText({
767
- messages: state.messages || [],
768
- context: searchIssuesTemplate
849
+ const prompt = searchTemplate.replace("{{userMessage}}", content);
850
+ const response = await runtime.useModel(ModelType2.TEXT_LARGE, {
851
+ prompt
769
852
  });
770
- filters = JSON.parse(response.trim().replace(/```json\n?|\n?```/g, ""));
771
- }
772
- if (!filters.limit) {
773
- filters.limit = 20;
853
+ if (!response) {
854
+ filters = { query: content };
855
+ } else {
856
+ try {
857
+ const parsed = JSON.parse(response);
858
+ filters = {
859
+ query: parsed.query,
860
+ state: parsed.state ? [parsed.state] : void 0,
861
+ assignee: parsed.assignee ? [parsed.assignee] : void 0,
862
+ priority: parsed.priority ? [parsed.priority] : void 0,
863
+ team: parsed.team,
864
+ label: parsed.label ? [parsed.label] : void 0,
865
+ limit: parsed.limit
866
+ };
867
+ Object.keys(filters).forEach((key) => {
868
+ if (filters[key] === void 0) {
869
+ delete filters[key];
870
+ }
871
+ });
872
+ } catch (parseError) {
873
+ logger5.error("Failed to parse search filters:", parseError);
874
+ filters = { query: content };
875
+ }
876
+ }
774
877
  }
878
+ filters.limit = _options?.limit || 10;
775
879
  const issues = await linearService.searchIssues(filters);
776
- const issuesWithDetails = await Promise.all(
777
- issues.map(async (issue) => {
778
- const [assignee, state2, team] = await Promise.all([
779
- issue.assignee,
780
- issue.state,
781
- issue.team
782
- ]);
783
- return {
784
- id: issue.id,
785
- identifier: issue.identifier,
786
- title: issue.title,
787
- url: issue.url,
788
- priority: issue.priority,
789
- priorityLabel: issue.priorityLabel,
790
- createdAt: issue.createdAt,
791
- updatedAt: issue.updatedAt,
792
- assignee: assignee ? assignee.name : "Unassigned",
793
- state: state2.name,
794
- team: team.name
795
- };
796
- })
797
- );
798
- logger5.info(`Found ${issues.length} Linear issues matching criteria`);
880
+ if (issues.length === 0) {
881
+ return {
882
+ text: "No issues found matching your search criteria.",
883
+ success: true,
884
+ data: {
885
+ issues: [],
886
+ filters,
887
+ count: 0
888
+ }
889
+ };
890
+ }
891
+ const issueList = await Promise.all(issues.map(async (issue, index) => {
892
+ const state = await issue.state;
893
+ return `${index + 1}. ${issue.identifier}: ${issue.title} (${state?.name || "No state"})`;
894
+ }));
895
+ const issueText = issueList.join("\n");
799
896
  return {
897
+ text: `Found ${issues.length} issue${issues.length === 1 ? "" : "s"}:
898
+ ${issueText}`,
800
899
  success: true,
801
900
  data: {
802
- issues: issuesWithDetails,
803
- count: issues.length,
804
- filters
805
- },
806
- metadata: {
807
- searchFilters: filters,
808
- resultCount: issues.length
901
+ issues: issues.map((i) => ({
902
+ id: i.id,
903
+ identifier: i.identifier,
904
+ title: i.title,
905
+ description: i.description,
906
+ url: i.url,
907
+ state: i.state,
908
+ priority: i.priority,
909
+ priorityLabel: i.priorityLabel,
910
+ assignee: i.assignee
911
+ })),
912
+ filters,
913
+ count: issues.length
809
914
  }
810
915
  };
811
916
  } catch (error) {
812
- logger5.error("Failed to search Linear issues:", error);
917
+ logger5.error("Failed to search issues:", error);
813
918
  return {
814
- success: false,
815
- error: error instanceof Error ? error.message : "Failed to search issues"
919
+ text: `Failed to search issues: ${error instanceof Error ? error.message : "Unknown error"}`,
920
+ success: false
816
921
  };
817
922
  }
818
- },
819
- examples: [
923
+ }
924
+ };
925
+
926
+ // src/actions/createComment.ts
927
+ import { logger as logger6 } from "@elizaos/core";
928
+ var createCommentAction = {
929
+ name: "CREATE_LINEAR_COMMENT",
930
+ description: "Create a comment on a Linear issue",
931
+ similes: ["create-linear-comment", "add-linear-comment", "comment-on-linear-issue"],
932
+ examples: [[
820
933
  {
821
- input: "Show me all open bugs",
822
- output: 'Found 5 open issues labeled as "bug":\n1. BUG-123: Login timeout issue\n2. BUG-124: Image upload fails\n...',
823
- explanation: "Searches for issues with bug label in open states"
934
+ name: "User",
935
+ content: {
936
+ text: "Comment on ENG-123: This has been fixed in the latest release"
937
+ }
824
938
  },
825
939
  {
826
- input: "Find high priority issues assigned to me",
827
- output: "Found 3 high priority issues assigned to you:\n1. FEAT-456: Implement user dashboard\n2. BUG-789: Fix payment processing\n...",
828
- explanation: "Searches for high priority issues assigned to the current user"
940
+ name: "Assistant",
941
+ content: {
942
+ text: "I'll add that comment to issue ENG-123.",
943
+ actions: ["CREATE_LINEAR_COMMENT"]
944
+ }
945
+ }
946
+ ], [
947
+ {
948
+ name: "User",
949
+ content: {
950
+ text: "Add a comment to BUG-456: Need more information from the reporter"
951
+ }
829
952
  },
830
953
  {
831
- input: "Search for issues related to authentication",
832
- output: 'Found 4 issues matching "authentication":\n1. SEC-001: Add 2FA support\n2. BUG-234: Password reset not working\n...',
833
- explanation: "Performs text search across issue titles and descriptions"
954
+ name: "Assistant",
955
+ content: {
956
+ text: "I'll post that comment on BUG-456 right away.",
957
+ actions: ["CREATE_LINEAR_COMMENT"]
958
+ }
834
959
  }
835
- ]
836
- };
837
-
838
- // src/actions/createComment.ts
839
- import {
840
- logger as logger6
841
- } from "@elizaos/core";
842
- var createLinearCommentAction = {
843
- name: "CREATE_LINEAR_COMMENT",
844
- description: "Add a comment to a Linear issue",
845
- similes: ["comment on issue", "add comment", "reply to issue"],
846
- async validate(runtime, _message, state) {
960
+ ]],
961
+ async validate(runtime, _message, _state) {
847
962
  try {
848
- const linearService = runtime.getService("linear");
849
- return !!linearService;
963
+ const apiKey = runtime.getSetting("LINEAR_API_KEY");
964
+ return !!apiKey;
850
965
  } catch {
851
966
  return false;
852
967
  }
853
968
  },
854
- async handler(runtime, message, state, options) {
969
+ async handler(runtime, message, _state, _options) {
855
970
  try {
856
971
  const linearService = runtime.getService("linear");
857
972
  if (!linearService) {
858
973
  throw new Error("Linear service not available");
859
974
  }
860
- const issueId = options?.issueId ? String(options.issueId) : void 0;
861
- const body = options?.body ? String(options.body) : message.content.text;
862
- if (!issueId || !body) {
975
+ const content = message.content.text;
976
+ if (!content) {
863
977
  return {
864
- success: false,
865
- error: "Issue ID and comment body are required"
978
+ text: "Please provide a message with the issue ID and comment content.",
979
+ success: false
866
980
  };
867
981
  }
868
- const commentInput = {
869
- issueId,
870
- body
871
- };
872
- const comment = await linearService.createComment(commentInput);
873
- logger6.info(`Created comment on Linear issue: ${issueId}`);
982
+ const issueMatch = content.match(/(?:comment on|add.*comment.*to)\s+(\w+-\d+):?\s*(.*)/i);
983
+ if (!issueMatch) {
984
+ return {
985
+ text: 'Please specify the issue ID and comment content. Example: "Comment on ENG-123: This looks good"',
986
+ success: false
987
+ };
988
+ }
989
+ const [, issueIdentifier, commentBody] = issueMatch;
990
+ const issue = await linearService.getIssue(issueIdentifier);
991
+ const comment = await linearService.createComment({
992
+ issueId: issue.id,
993
+ body: commentBody.trim()
994
+ });
874
995
  return {
996
+ text: `Comment added to issue ${issueIdentifier}: "${commentBody.trim()}"`,
875
997
  success: true,
876
998
  data: {
877
- comment: {
878
- id: comment.id,
879
- body: comment.body,
880
- createdAt: comment.createdAt
881
- }
882
- },
883
- metadata: {
884
999
  commentId: comment.id,
885
- issueId
1000
+ issueId: issue.id
886
1001
  }
887
1002
  };
888
1003
  } catch (error) {
889
- logger6.error("Failed to create Linear comment:", error);
1004
+ logger6.error("Failed to create comment:", error);
890
1005
  return {
891
- success: false,
892
- error: error instanceof Error ? error.message : "Failed to create comment"
1006
+ text: `Failed to create comment: ${error instanceof Error ? error.message : "Unknown error"}`,
1007
+ success: false
893
1008
  };
894
1009
  }
895
- },
896
- examples: [
897
- {
898
- input: "Comment on ENG-123: This has been fixed in the latest release",
899
- output: "Added comment to issue ENG-123",
900
- explanation: "Adds a comment to an existing issue"
901
- }
902
- ]
1010
+ }
903
1011
  };
904
1012
 
905
1013
  // src/actions/listTeams.ts
906
- import {
907
- logger as logger7
908
- } from "@elizaos/core";
909
- var listLinearTeamsAction = {
1014
+ import { logger as logger7 } from "@elizaos/core";
1015
+ var listTeamsAction = {
910
1016
  name: "LIST_LINEAR_TEAMS",
911
- description: "List all teams in the Linear workspace",
912
- similes: ["show teams", "get teams", "list teams", "view teams"],
913
- async validate(runtime, _message, state) {
1017
+ description: "List all teams in Linear",
1018
+ similes: ["list-linear-teams", "show-linear-teams", "get-linear-teams"],
1019
+ examples: [[
1020
+ {
1021
+ name: "User",
1022
+ content: {
1023
+ text: "Show me all teams"
1024
+ }
1025
+ },
1026
+ {
1027
+ name: "Assistant",
1028
+ content: {
1029
+ text: "I'll list all the teams in Linear for you.",
1030
+ actions: ["LIST_LINEAR_TEAMS"]
1031
+ }
1032
+ }
1033
+ ], [
1034
+ {
1035
+ name: "User",
1036
+ content: {
1037
+ text: "What teams are available?"
1038
+ }
1039
+ },
1040
+ {
1041
+ name: "Assistant",
1042
+ content: {
1043
+ text: "Let me show you all the available teams.",
1044
+ actions: ["LIST_LINEAR_TEAMS"]
1045
+ }
1046
+ }
1047
+ ]],
1048
+ async validate(runtime, _message, _state) {
914
1049
  try {
915
- const linearService = runtime.getService("linear");
916
- return !!linearService;
1050
+ const apiKey = runtime.getSetting("LINEAR_API_KEY");
1051
+ return !!apiKey;
917
1052
  } catch {
918
1053
  return false;
919
1054
  }
920
1055
  },
921
- async handler(runtime, message, state, options) {
1056
+ async handler(runtime, _message, _state, _options) {
922
1057
  try {
923
1058
  const linearService = runtime.getService("linear");
924
1059
  if (!linearService) {
925
1060
  throw new Error("Linear service not available");
926
1061
  }
927
1062
  const teams = await linearService.getTeams();
928
- const teamsData = teams.map((team) => ({
929
- id: team.id,
930
- name: team.name,
931
- key: team.key,
932
- description: team.description
933
- }));
934
- logger7.info(`Retrieved ${teams.length} Linear teams`);
1063
+ if (teams.length === 0) {
1064
+ return {
1065
+ text: "No teams found in Linear.",
1066
+ success: true,
1067
+ data: {
1068
+ teams: []
1069
+ }
1070
+ };
1071
+ }
1072
+ const teamList = teams.map(
1073
+ (team, index) => `${index + 1}. ${team.name} (${team.key})${team.description ? ` - ${team.description}` : ""}`
1074
+ ).join("\n");
935
1075
  return {
1076
+ text: `Found ${teams.length} team${teams.length === 1 ? "" : "s"}:
1077
+ ${teamList}`,
936
1078
  success: true,
937
1079
  data: {
938
- teams: teamsData,
1080
+ teams: teams.map((t) => ({
1081
+ id: t.id,
1082
+ name: t.name,
1083
+ key: t.key,
1084
+ description: t.description
1085
+ })),
939
1086
  count: teams.length
940
- },
941
- metadata: {
942
- teamCount: teams.length
943
1087
  }
944
1088
  };
945
1089
  } catch (error) {
946
- logger7.error("Failed to list Linear teams:", error);
1090
+ logger7.error("Failed to list teams:", error);
947
1091
  return {
948
- success: false,
949
- error: error instanceof Error ? error.message : "Failed to list teams"
1092
+ text: `Failed to list teams: ${error instanceof Error ? error.message : "Unknown error"}`,
1093
+ success: false
950
1094
  };
951
1095
  }
952
- },
953
- examples: [
954
- {
955
- input: "Show me all teams",
956
- output: "Found 3 teams:\n1. Engineering (ENG)\n2. Design (DES)\n3. Product (PROD)",
957
- explanation: "Lists all teams in the workspace"
958
- }
959
- ]
1096
+ }
960
1097
  };
961
1098
 
962
1099
  // src/actions/listProjects.ts
963
- import {
964
- logger as logger8
965
- } from "@elizaos/core";
966
- var listLinearProjectsAction = {
1100
+ import { logger as logger8 } from "@elizaos/core";
1101
+ var listProjectsAction = {
967
1102
  name: "LIST_LINEAR_PROJECTS",
968
- description: "List projects in Linear, optionally filtered by team",
969
- similes: ["show projects", "get projects", "list projects", "view projects"],
970
- async validate(runtime, _message, state) {
1103
+ description: "List all projects in Linear",
1104
+ similes: ["list-linear-projects", "show-linear-projects", "get-linear-projects"],
1105
+ examples: [[
1106
+ {
1107
+ name: "User",
1108
+ content: {
1109
+ text: "Show me all projects"
1110
+ }
1111
+ },
1112
+ {
1113
+ name: "Assistant",
1114
+ content: {
1115
+ text: "I'll list all the projects in Linear for you.",
1116
+ actions: ["LIST_LINEAR_PROJECTS"]
1117
+ }
1118
+ }
1119
+ ], [
1120
+ {
1121
+ name: "User",
1122
+ content: {
1123
+ text: "What projects do we have?"
1124
+ }
1125
+ },
1126
+ {
1127
+ name: "Assistant",
1128
+ content: {
1129
+ text: "Let me show you all the available projects.",
1130
+ actions: ["LIST_LINEAR_PROJECTS"]
1131
+ }
1132
+ }
1133
+ ]],
1134
+ async validate(runtime, _message, _state) {
971
1135
  try {
972
- const linearService = runtime.getService("linear");
973
- return !!linearService;
1136
+ const apiKey = runtime.getSetting("LINEAR_API_KEY");
1137
+ return !!apiKey;
974
1138
  } catch {
975
1139
  return false;
976
1140
  }
977
1141
  },
978
- async handler(runtime, message, state, options) {
1142
+ async handler(runtime, _message, _state, _options) {
979
1143
  try {
980
1144
  const linearService = runtime.getService("linear");
981
1145
  if (!linearService) {
982
1146
  throw new Error("Linear service not available");
983
1147
  }
984
- const teamId = options?.teamId ? String(options.teamId) : void 0;
985
- const projects = await linearService.getProjects(teamId);
986
- const projectsData = await Promise.all(
1148
+ const projects = await linearService.getProjects();
1149
+ if (projects.length === 0) {
1150
+ return {
1151
+ text: "No projects found in Linear.",
1152
+ success: true,
1153
+ data: {
1154
+ projects: []
1155
+ }
1156
+ };
1157
+ }
1158
+ const projectsWithDetails = await Promise.all(
987
1159
  projects.map(async (project) => {
988
- const team = await project.team;
1160
+ const teamsQuery = await project.teams();
1161
+ const teams = await teamsQuery.nodes;
989
1162
  return {
990
- id: project.id,
991
- name: project.name,
992
- description: project.description,
993
- state: project.state,
994
- teamName: team?.name,
995
- startDate: project.startDate,
996
- targetDate: project.targetDate
1163
+ ...project,
1164
+ teamsList: teams
997
1165
  };
998
1166
  })
999
1167
  );
1000
- logger8.info(`Retrieved ${projects.length} Linear projects`);
1168
+ const projectList = projectsWithDetails.map((project, index) => {
1169
+ const teamNames = project.teamsList.map((t) => t.name).join(", ") || "No teams";
1170
+ return `${index + 1}. ${project.name}${project.description ? ` - ${project.description}` : ""} (Teams: ${teamNames})`;
1171
+ }).join("\n");
1001
1172
  return {
1173
+ text: `Found ${projects.length} project${projects.length === 1 ? "" : "s"}:
1174
+ ${projectList}`,
1002
1175
  success: true,
1003
1176
  data: {
1004
- projects: projectsData,
1177
+ projects: projectsWithDetails.map((p) => ({
1178
+ id: p.id,
1179
+ name: p.name,
1180
+ description: p.description,
1181
+ url: p.url,
1182
+ teams: p.teamsList.map((t) => ({
1183
+ id: t.id,
1184
+ name: t.name,
1185
+ key: t.key
1186
+ })),
1187
+ state: p.state,
1188
+ progress: p.progress,
1189
+ startDate: p.startDate,
1190
+ targetDate: p.targetDate
1191
+ })),
1005
1192
  count: projects.length
1006
- },
1007
- metadata: {
1008
- projectCount: projects.length,
1009
- teamFilter: teamId
1010
1193
  }
1011
1194
  };
1012
1195
  } catch (error) {
1013
- logger8.error("Failed to list Linear projects:", error);
1196
+ logger8.error("Failed to list projects:", error);
1014
1197
  return {
1015
- success: false,
1016
- error: error instanceof Error ? error.message : "Failed to list projects"
1198
+ text: `Failed to list projects: ${error instanceof Error ? error.message : "Unknown error"}`,
1199
+ success: false
1017
1200
  };
1018
1201
  }
1019
- },
1020
- examples: [
1021
- {
1022
- input: "Show me all projects",
1023
- output: "Found 5 projects:\n1. Q1 2024 Roadmap\n2. Mobile App Redesign\n3. API v2 Migration...",
1024
- explanation: "Lists all projects in the workspace"
1025
- }
1026
- ]
1202
+ }
1027
1203
  };
1028
1204
 
1029
1205
  // src/actions/getActivity.ts
1030
- import {
1031
- logger as logger9
1032
- } from "@elizaos/core";
1033
- var getLinearActivityAction = {
1206
+ import { logger as logger9 } from "@elizaos/core";
1207
+ var getActivityAction = {
1034
1208
  name: "GET_LINEAR_ACTIVITY",
1035
- description: "Get recent Linear activity log",
1036
- similes: ["show activity", "get activity", "view activity", "activity log"],
1037
- async validate(runtime, _message, state) {
1209
+ description: "Get recent Linear activity",
1210
+ similes: ["get-linear-activity", "show-linear-activity", "view-linear-activity"],
1211
+ examples: [[
1212
+ {
1213
+ name: "User",
1214
+ content: {
1215
+ text: "Show me recent Linear activity"
1216
+ }
1217
+ },
1218
+ {
1219
+ name: "Assistant",
1220
+ content: {
1221
+ text: "I'll check the recent Linear activity for you.",
1222
+ actions: ["GET_LINEAR_ACTIVITY"]
1223
+ }
1224
+ }
1225
+ ], [
1226
+ {
1227
+ name: "User",
1228
+ content: {
1229
+ text: "What's been happening in Linear?"
1230
+ }
1231
+ },
1232
+ {
1233
+ name: "Assistant",
1234
+ content: {
1235
+ text: "Let me show you the recent Linear activity.",
1236
+ actions: ["GET_LINEAR_ACTIVITY"]
1237
+ }
1238
+ }
1239
+ ]],
1240
+ async validate(runtime, _message, _state) {
1038
1241
  try {
1039
- const linearService = runtime.getService("linear");
1040
- return !!linearService;
1242
+ const apiKey = runtime.getSetting("LINEAR_API_KEY");
1243
+ return !!apiKey;
1041
1244
  } catch {
1042
1245
  return false;
1043
1246
  }
1044
1247
  },
1045
- async handler(runtime, message, state, options) {
1248
+ async handler(runtime, _message, _state, _options) {
1046
1249
  try {
1047
1250
  const linearService = runtime.getService("linear");
1048
1251
  if (!linearService) {
1049
1252
  throw new Error("Linear service not available");
1050
1253
  }
1051
- const limit = options?.limit ? Number(options.limit) : 50;
1052
- const filter = options?.filter ? options.filter : void 0;
1053
- const activity = linearService.getActivityLog(limit, filter);
1054
- logger9.info(`Retrieved ${activity.length} Linear activity items`);
1254
+ const activity = linearService.getActivityLog();
1255
+ if (activity.length === 0) {
1256
+ return {
1257
+ text: "No recent Linear activity found.",
1258
+ success: true,
1259
+ data: {
1260
+ activity: []
1261
+ }
1262
+ };
1263
+ }
1264
+ const activityText = activity.slice(0, 10).map((item, index) => {
1265
+ const description = `${item.action} ${item.resource_type} ${item.resource_id}${item.error ? ` (failed: ${item.error})` : ""}`;
1266
+ return `${index + 1}. ${description}`;
1267
+ }).join("\n");
1055
1268
  return {
1269
+ text: `Recent Linear activity:
1270
+ ${activityText}`,
1056
1271
  success: true,
1057
1272
  data: {
1058
- activity,
1273
+ activity: activity.slice(0, 10),
1059
1274
  count: activity.length
1060
- },
1061
- metadata: {
1062
- activityCount: activity.length
1063
1275
  }
1064
1276
  };
1065
1277
  } catch (error) {
1066
1278
  logger9.error("Failed to get Linear activity:", error);
1067
1279
  return {
1068
- success: false,
1069
- error: error instanceof Error ? error.message : "Failed to get activity"
1280
+ text: `Failed to get Linear activity: ${error instanceof Error ? error.message : "Unknown error"}`,
1281
+ success: false
1070
1282
  };
1071
1283
  }
1072
- },
1073
- examples: [
1074
- {
1075
- input: "Show me recent Linear activity",
1076
- output: "Recent activity:\n1. Created issue ENG-123\n2. Updated issue BUG-456\n3. Added comment to FEAT-789...",
1077
- explanation: "Shows recent Linear operations performed by the agent"
1078
- }
1079
- ]
1284
+ }
1080
1285
  };
1081
1286
 
1082
1287
  // src/actions/clearActivity.ts
1083
- import {
1084
- logger as logger10
1085
- } from "@elizaos/core";
1086
- var clearLinearActivityAction = {
1288
+ import { logger as logger10 } from "@elizaos/core";
1289
+ var clearActivityAction = {
1087
1290
  name: "CLEAR_LINEAR_ACTIVITY",
1088
1291
  description: "Clear the Linear activity log",
1089
- similes: ["clear activity", "reset activity", "delete activity log"],
1090
- async validate(runtime, _message, state) {
1292
+ similes: ["clear-linear-activity", "reset-linear-activity", "delete-linear-activity"],
1293
+ examples: [[
1294
+ {
1295
+ name: "User",
1296
+ content: {
1297
+ text: "Clear the Linear activity log"
1298
+ }
1299
+ },
1300
+ {
1301
+ name: "Assistant",
1302
+ content: {
1303
+ text: "I'll clear the Linear activity log for you.",
1304
+ actions: ["CLEAR_LINEAR_ACTIVITY"]
1305
+ }
1306
+ }
1307
+ ], [
1308
+ {
1309
+ name: "User",
1310
+ content: {
1311
+ text: "Reset Linear activity"
1312
+ }
1313
+ },
1314
+ {
1315
+ name: "Assistant",
1316
+ content: {
1317
+ text: "I'll reset the Linear activity log now.",
1318
+ actions: ["CLEAR_LINEAR_ACTIVITY"]
1319
+ }
1320
+ }
1321
+ ]],
1322
+ async validate(runtime, _message, _state) {
1091
1323
  try {
1092
- const linearService = runtime.getService("linear");
1093
- return !!linearService;
1324
+ const apiKey = runtime.getSetting("LINEAR_API_KEY");
1325
+ return !!apiKey;
1094
1326
  } catch {
1095
1327
  return false;
1096
1328
  }
1097
1329
  },
1098
- async handler(runtime, message, state, options) {
1330
+ async handler(runtime, message, _state, _options) {
1099
1331
  try {
1100
1332
  const linearService = runtime.getService("linear");
1101
1333
  if (!linearService) {
1102
1334
  throw new Error("Linear service not available");
1103
1335
  }
1104
- linearService.clearActivityLog();
1105
- logger10.info("Cleared Linear activity log");
1336
+ await linearService.clearActivityLog();
1106
1337
  return {
1107
- success: true,
1108
- data: {
1109
- message: "Activity log cleared successfully"
1110
- }
1338
+ text: "Linear activity log has been cleared.",
1339
+ success: true
1111
1340
  };
1112
1341
  } catch (error) {
1113
1342
  logger10.error("Failed to clear Linear activity:", error);
1114
1343
  return {
1115
- success: false,
1116
- error: error instanceof Error ? error.message : "Failed to clear activity"
1344
+ text: `Failed to clear Linear activity: ${error instanceof Error ? error.message : "Unknown error"}`,
1345
+ success: false
1117
1346
  };
1118
1347
  }
1119
- },
1120
- examples: [
1121
- {
1122
- input: "Clear the Linear activity log",
1123
- output: "Linear activity log has been cleared",
1124
- explanation: "Clears all stored activity history"
1125
- }
1126
- ]
1348
+ }
1127
1349
  };
1128
1350
 
1129
1351
  // src/providers/issues.ts
@@ -1299,29 +1521,26 @@ ${activityList.join("\n")}`;
1299
1521
 
1300
1522
  // src/index.ts
1301
1523
  var linearPlugin = {
1302
- name: "linear",
1303
- description: "Linear integration plugin for issue tracking and project management",
1524
+ name: "@elizaos/plugin-linear",
1525
+ description: "Plugin for integrating with Linear issue tracking system",
1304
1526
  services: [LinearService],
1305
1527
  actions: [
1306
- createLinearIssueAction,
1307
- getLinearIssueAction,
1308
- updateLinearIssueAction,
1309
- searchLinearIssuesAction,
1310
- createLinearCommentAction,
1311
- listLinearTeamsAction,
1312
- listLinearProjectsAction,
1313
- getLinearActivityAction,
1314
- clearLinearActivityAction
1528
+ createIssueAction,
1529
+ getIssueAction,
1530
+ updateIssueAction,
1531
+ searchIssuesAction,
1532
+ createCommentAction,
1533
+ listTeamsAction,
1534
+ listProjectsAction,
1535
+ getActivityAction,
1536
+ clearActivityAction
1315
1537
  ],
1316
1538
  providers: [
1317
1539
  linearIssuesProvider,
1318
1540
  linearTeamsProvider,
1319
1541
  linearProjectsProvider,
1320
1542
  linearActivityProvider
1321
- ],
1322
- // No evaluators or events for this plugin
1323
- evaluators: [],
1324
- events: {}
1543
+ ]
1325
1544
  };
1326
1545
  export {
1327
1546
  LinearAPIError,