@elizaos/plugin-linear 1.2.5 → 1.2.7

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