opencode-gitlab-plugin 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/index.js +353 -52
- package/dist/opencode-gitlab-plugin-2.0.1.tgz +0 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [2.0.1](https://gitlab.com/vglafirov/opencode-gitlab-plugin/compare/v2.0.0...v2.0.1) (2026-03-22)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### 🐛 Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **work-items:** address review comments ([0173f25](https://gitlab.com/vglafirov/opencode-gitlab-plugin/commit/0173f25afbecf9b01a61a0239a4112c22e96864f))
|
|
11
|
+
* **work-items:** switch to GraphQL API to resolve iid-vs-id 404 bug ([fcd3417](https://gitlab.com/vglafirov/opencode-gitlab-plugin/commit/fcd3417792e9fcea1ef0a08de2e09d483e769e25))
|
|
12
|
+
|
|
5
13
|
## [2.0.0](https://gitlab.com/vglafirov/opencode-gitlab-plugin/compare/v1.9.0...v2.0.0) (2026-03-02)
|
|
6
14
|
|
|
7
15
|
|
package/dist/index.js
CHANGED
|
@@ -718,63 +718,356 @@ var IssuesClient = class extends GitLabApiClient {
|
|
|
718
718
|
};
|
|
719
719
|
|
|
720
720
|
// src/client/work-items.ts
|
|
721
|
+
function toGid(type, id) {
|
|
722
|
+
return `gid://gitlab/${type}/${id}`;
|
|
723
|
+
}
|
|
724
|
+
var WORK_ITEM_LIST_FIELDS = `
|
|
725
|
+
id
|
|
726
|
+
iid
|
|
727
|
+
title
|
|
728
|
+
description
|
|
729
|
+
state
|
|
730
|
+
createdAt
|
|
731
|
+
updatedAt
|
|
732
|
+
workItemType {
|
|
733
|
+
id
|
|
734
|
+
name
|
|
735
|
+
}
|
|
736
|
+
author {
|
|
737
|
+
id
|
|
738
|
+
username
|
|
739
|
+
name
|
|
740
|
+
}
|
|
741
|
+
assignees {
|
|
742
|
+
nodes {
|
|
743
|
+
id
|
|
744
|
+
username
|
|
745
|
+
name
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
labels {
|
|
749
|
+
nodes {
|
|
750
|
+
id
|
|
751
|
+
title
|
|
752
|
+
color
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
webUrl
|
|
756
|
+
`;
|
|
757
|
+
var GET_WORK_ITEM_QUERY = `
|
|
758
|
+
query getWorkItem($fullPath: ID!, $iid: String!) {
|
|
759
|
+
workspace: project(fullPath: $fullPath) {
|
|
760
|
+
workItem(iid: $iid) {
|
|
761
|
+
id
|
|
762
|
+
iid
|
|
763
|
+
title
|
|
764
|
+
description
|
|
765
|
+
state
|
|
766
|
+
createdAt
|
|
767
|
+
updatedAt
|
|
768
|
+
closedAt
|
|
769
|
+
confidential
|
|
770
|
+
workItemType {
|
|
771
|
+
id
|
|
772
|
+
name
|
|
773
|
+
}
|
|
774
|
+
author {
|
|
775
|
+
id
|
|
776
|
+
username
|
|
777
|
+
name
|
|
778
|
+
}
|
|
779
|
+
assignees {
|
|
780
|
+
nodes {
|
|
781
|
+
id
|
|
782
|
+
username
|
|
783
|
+
name
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
labels {
|
|
787
|
+
nodes {
|
|
788
|
+
id
|
|
789
|
+
title
|
|
790
|
+
color
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
webUrl
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
`;
|
|
798
|
+
var LIST_WORK_ITEMS_QUERY = `
|
|
799
|
+
query listWorkItems(
|
|
800
|
+
$fullPath: ID!
|
|
801
|
+
$state: WorkItemState
|
|
802
|
+
$search: String
|
|
803
|
+
$types: [WorkItemTypeEnum!]
|
|
804
|
+
$labelNames: [String!]
|
|
805
|
+
$first: Int
|
|
806
|
+
) {
|
|
807
|
+
workspace: project(fullPath: $fullPath) {
|
|
808
|
+
workItems(
|
|
809
|
+
state: $state
|
|
810
|
+
search: $search
|
|
811
|
+
types: $types
|
|
812
|
+
labelName: $labelNames
|
|
813
|
+
first: $first
|
|
814
|
+
) {
|
|
815
|
+
nodes {
|
|
816
|
+
${WORK_ITEM_LIST_FIELDS}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
`;
|
|
822
|
+
var LIST_GROUP_WORK_ITEMS_QUERY = `
|
|
823
|
+
query listGroupWorkItems(
|
|
824
|
+
$fullPath: ID!
|
|
825
|
+
$state: WorkItemState
|
|
826
|
+
$search: String
|
|
827
|
+
$types: [WorkItemTypeEnum!]
|
|
828
|
+
$labelNames: [String!]
|
|
829
|
+
$first: Int
|
|
830
|
+
) {
|
|
831
|
+
workspace: group(fullPath: $fullPath) {
|
|
832
|
+
workItems(
|
|
833
|
+
state: $state
|
|
834
|
+
search: $search
|
|
835
|
+
types: $types
|
|
836
|
+
labelName: $labelNames
|
|
837
|
+
first: $first
|
|
838
|
+
) {
|
|
839
|
+
nodes {
|
|
840
|
+
${WORK_ITEM_LIST_FIELDS}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
`;
|
|
846
|
+
var GET_WORK_ITEM_NOTES_QUERY = `
|
|
847
|
+
query getWorkItemNotes($fullPath: ID!, $iid: String!) {
|
|
848
|
+
workspace: project(fullPath: $fullPath) {
|
|
849
|
+
workItem(iid: $iid) {
|
|
850
|
+
id
|
|
851
|
+
iid
|
|
852
|
+
notes {
|
|
853
|
+
nodes {
|
|
854
|
+
id
|
|
855
|
+
body
|
|
856
|
+
createdAt
|
|
857
|
+
updatedAt
|
|
858
|
+
author {
|
|
859
|
+
id
|
|
860
|
+
username
|
|
861
|
+
name
|
|
862
|
+
}
|
|
863
|
+
system
|
|
864
|
+
resolvable
|
|
865
|
+
resolved
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
`;
|
|
872
|
+
var CREATE_WORK_ITEM_MUTATION = `
|
|
873
|
+
mutation createWorkItem(
|
|
874
|
+
$projectPath: ID!
|
|
875
|
+
$title: String!
|
|
876
|
+
$workItemTypeId: WorkItemsTypeID!
|
|
877
|
+
$description: String
|
|
878
|
+
$labelIds: [LabelID!]
|
|
879
|
+
$assigneeIds: [UserID!]
|
|
880
|
+
) {
|
|
881
|
+
workItemCreate(input: {
|
|
882
|
+
projectPath: $projectPath
|
|
883
|
+
title: $title
|
|
884
|
+
workItemTypeId: $workItemTypeId
|
|
885
|
+
descriptionWidget: { description: $description }
|
|
886
|
+
labelsWidget: { labelIds: $labelIds }
|
|
887
|
+
assigneesWidget: { assigneeIds: $assigneeIds }
|
|
888
|
+
}) {
|
|
889
|
+
workItem {
|
|
890
|
+
id
|
|
891
|
+
iid
|
|
892
|
+
title
|
|
893
|
+
description
|
|
894
|
+
state
|
|
895
|
+
createdAt
|
|
896
|
+
updatedAt
|
|
897
|
+
workItemType {
|
|
898
|
+
id
|
|
899
|
+
name
|
|
900
|
+
}
|
|
901
|
+
author {
|
|
902
|
+
id
|
|
903
|
+
username
|
|
904
|
+
name
|
|
905
|
+
}
|
|
906
|
+
webUrl
|
|
907
|
+
}
|
|
908
|
+
errors
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
`;
|
|
912
|
+
var UPDATE_WORK_ITEM_MUTATION = `
|
|
913
|
+
mutation updateWorkItem(
|
|
914
|
+
$id: WorkItemID!
|
|
915
|
+
$title: String
|
|
916
|
+
$description: String
|
|
917
|
+
$stateEvent: WorkItemStateEvent
|
|
918
|
+
$labelIds: [LabelID!]
|
|
919
|
+
$assigneeIds: [UserID!]
|
|
920
|
+
) {
|
|
921
|
+
workItemUpdate(input: {
|
|
922
|
+
id: $id
|
|
923
|
+
title: $title
|
|
924
|
+
descriptionWidget: { description: $description }
|
|
925
|
+
stateEvent: $stateEvent
|
|
926
|
+
labelsWidget: { labelIds: $labelIds }
|
|
927
|
+
assigneesWidget: { assigneeIds: $assigneeIds }
|
|
928
|
+
}) {
|
|
929
|
+
workItem {
|
|
930
|
+
id
|
|
931
|
+
iid
|
|
932
|
+
title
|
|
933
|
+
description
|
|
934
|
+
state
|
|
935
|
+
updatedAt
|
|
936
|
+
workItemType {
|
|
937
|
+
id
|
|
938
|
+
name
|
|
939
|
+
}
|
|
940
|
+
webUrl
|
|
941
|
+
}
|
|
942
|
+
errors
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
`;
|
|
946
|
+
var CREATE_NOTE_MUTATION = `
|
|
947
|
+
mutation createWorkItemNote($noteableId: NoteableID!, $body: String!) {
|
|
948
|
+
createNote(input: { noteableId: $noteableId, body: $body }) {
|
|
949
|
+
note {
|
|
950
|
+
id
|
|
951
|
+
body
|
|
952
|
+
createdAt
|
|
953
|
+
author {
|
|
954
|
+
id
|
|
955
|
+
username
|
|
956
|
+
name
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
errors
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
`;
|
|
963
|
+
var GET_WORK_ITEM_GID_QUERY = `
|
|
964
|
+
query getWorkItemGid($fullPath: ID!, $iid: String!) {
|
|
965
|
+
workspace: project(fullPath: $fullPath) {
|
|
966
|
+
workItem(iid: $iid) {
|
|
967
|
+
id
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
`;
|
|
721
972
|
var WorkItemsClient = class extends GitLabApiClient {
|
|
722
|
-
async getWorkItem(projectId,
|
|
723
|
-
const
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
973
|
+
async getWorkItem(projectId, workItemIid) {
|
|
974
|
+
const result = await this.fetchGraphQL(GET_WORK_ITEM_QUERY, {
|
|
975
|
+
fullPath: projectId,
|
|
976
|
+
iid: String(workItemIid)
|
|
977
|
+
});
|
|
978
|
+
const workItem = result.workspace?.workItem;
|
|
979
|
+
if (!workItem) {
|
|
980
|
+
throw new Error(`Work item with iid ${workItemIid} not found in project ${projectId}`);
|
|
981
|
+
}
|
|
982
|
+
return workItem;
|
|
728
983
|
}
|
|
729
984
|
async listWorkItems(options) {
|
|
730
|
-
const
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
985
|
+
const variables = {
|
|
986
|
+
state: options.state ? options.state.toUpperCase() : void 0,
|
|
987
|
+
search: options.search,
|
|
988
|
+
types: options.work_item_type ? [options.work_item_type.toUpperCase()] : void 0,
|
|
989
|
+
labelNames: options.labels ? options.labels.split(",").map((l) => l.trim()) : void 0,
|
|
990
|
+
first: options.limit || 20
|
|
991
|
+
};
|
|
737
992
|
if (options.projectId) {
|
|
738
|
-
const
|
|
739
|
-
|
|
993
|
+
const result = await this.fetchGraphQL(LIST_WORK_ITEMS_QUERY, { fullPath: options.projectId, ...variables });
|
|
994
|
+
return result.workspace?.workItems?.nodes ?? [];
|
|
740
995
|
} else if (options.groupId) {
|
|
741
|
-
const
|
|
742
|
-
|
|
996
|
+
const result = await this.fetchGraphQL(LIST_GROUP_WORK_ITEMS_QUERY, { fullPath: options.groupId, ...variables });
|
|
997
|
+
return result.workspace?.workItems?.nodes ?? [];
|
|
743
998
|
} else {
|
|
744
999
|
throw new Error("Either projectId or groupId must be provided");
|
|
745
1000
|
}
|
|
746
|
-
return this.fetch("GET", path2);
|
|
747
1001
|
}
|
|
748
|
-
async getWorkItemNotes(projectId,
|
|
749
|
-
const
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
1002
|
+
async getWorkItemNotes(projectId, workItemIid) {
|
|
1003
|
+
const result = await this.fetchGraphQL(GET_WORK_ITEM_NOTES_QUERY, {
|
|
1004
|
+
fullPath: projectId,
|
|
1005
|
+
iid: String(workItemIid)
|
|
1006
|
+
});
|
|
1007
|
+
const workItem = result.workspace?.workItem;
|
|
1008
|
+
if (!workItem) {
|
|
1009
|
+
throw new Error(`Work item with iid ${workItemIid} not found in project ${projectId}`);
|
|
1010
|
+
}
|
|
1011
|
+
return workItem.notes?.nodes ?? [];
|
|
754
1012
|
}
|
|
755
1013
|
async createWorkItem(projectId, options) {
|
|
756
|
-
const
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
options
|
|
761
|
-
|
|
1014
|
+
const labelIds = options.labels?.map((l) => toGid("Label", l));
|
|
1015
|
+
const assigneeIds = options.assignee_ids?.map((id) => toGid("User", id));
|
|
1016
|
+
const result = await this.fetchGraphQL(CREATE_WORK_ITEM_MUTATION, {
|
|
1017
|
+
projectPath: projectId,
|
|
1018
|
+
title: options.title,
|
|
1019
|
+
workItemTypeId: toGid("WorkItems::Type", options.work_item_type_id),
|
|
1020
|
+
description: options.description,
|
|
1021
|
+
labelIds: labelIds?.length ? labelIds : void 0,
|
|
1022
|
+
assigneeIds: assigneeIds?.length ? assigneeIds : void 0
|
|
1023
|
+
});
|
|
1024
|
+
if (result.workItemCreate.errors.length > 0) {
|
|
1025
|
+
throw new Error(`Failed to create work item: ${result.workItemCreate.errors.join(", ")}`);
|
|
1026
|
+
}
|
|
1027
|
+
return result.workItemCreate.workItem;
|
|
762
1028
|
}
|
|
763
|
-
async updateWorkItem(projectId,
|
|
764
|
-
const
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
)
|
|
1029
|
+
async updateWorkItem(projectId, workItemIid, options) {
|
|
1030
|
+
const gidResult = await this.fetchGraphQL(GET_WORK_ITEM_GID_QUERY, {
|
|
1031
|
+
fullPath: projectId,
|
|
1032
|
+
iid: String(workItemIid)
|
|
1033
|
+
});
|
|
1034
|
+
const gid = gidResult.workspace?.workItem?.id;
|
|
1035
|
+
if (!gid) {
|
|
1036
|
+
throw new Error(`Work item with iid ${workItemIid} not found in project ${projectId}`);
|
|
1037
|
+
}
|
|
1038
|
+
const stateEvent = options.state_event ? options.state_event === "close" ? "CLOSE" : "REOPEN" : void 0;
|
|
1039
|
+
const labelIds = options.labels?.map((l) => toGid("Label", l));
|
|
1040
|
+
const assigneeIds = options.assignee_ids?.map((id) => toGid("User", id));
|
|
1041
|
+
const result = await this.fetchGraphQL(UPDATE_WORK_ITEM_MUTATION, {
|
|
1042
|
+
id: gid,
|
|
1043
|
+
title: options.title,
|
|
1044
|
+
description: options.description,
|
|
1045
|
+
stateEvent,
|
|
1046
|
+
labelIds: labelIds?.length ? labelIds : void 0,
|
|
1047
|
+
assigneeIds: assigneeIds?.length ? assigneeIds : void 0
|
|
1048
|
+
});
|
|
1049
|
+
if (result.workItemUpdate.errors.length > 0) {
|
|
1050
|
+
throw new Error(`Failed to update work item: ${result.workItemUpdate.errors.join(", ")}`);
|
|
1051
|
+
}
|
|
1052
|
+
return result.workItemUpdate.workItem;
|
|
770
1053
|
}
|
|
771
|
-
async createWorkItemNote(projectId,
|
|
772
|
-
const
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
)
|
|
1054
|
+
async createWorkItemNote(projectId, workItemIid, body) {
|
|
1055
|
+
const gidResult = await this.fetchGraphQL(GET_WORK_ITEM_GID_QUERY, {
|
|
1056
|
+
fullPath: projectId,
|
|
1057
|
+
iid: String(workItemIid)
|
|
1058
|
+
});
|
|
1059
|
+
const gid = gidResult.workspace?.workItem?.id;
|
|
1060
|
+
if (!gid) {
|
|
1061
|
+
throw new Error(`Work item with iid ${workItemIid} not found in project ${projectId}`);
|
|
1062
|
+
}
|
|
1063
|
+
const result = await this.fetchGraphQL(CREATE_NOTE_MUTATION, {
|
|
1064
|
+
noteableId: gid,
|
|
1065
|
+
body
|
|
1066
|
+
});
|
|
1067
|
+
if (result.createNote.errors.length > 0) {
|
|
1068
|
+
throw new Error(`Failed to create note: ${result.createNote.errors.join(", ")}`);
|
|
1069
|
+
}
|
|
1070
|
+
return result.createNote.note;
|
|
778
1071
|
}
|
|
779
1072
|
};
|
|
780
1073
|
|
|
@@ -3598,8 +3891,10 @@ var workItemTools = {
|
|
|
3598
3891
|
description: `Get a single work item (issue, epic, task, etc.).
|
|
3599
3892
|
Work items are the new unified model for issues, epics, tasks, and other work tracking items in GitLab.`,
|
|
3600
3893
|
args: {
|
|
3601
|
-
project_id: z12.string().describe(
|
|
3602
|
-
work_item_id: z12.number().describe(
|
|
3894
|
+
project_id: z12.string().describe('The project ID or full path (e.g. "gitlab-org/gitlab")'),
|
|
3895
|
+
work_item_id: z12.number().describe(
|
|
3896
|
+
"The IID of the work item \u2014 the number visible in the GitLab URL (e.g. for https://gitlab.com/group/project/-/work_items/52, use 52). This is NOT the global database ID."
|
|
3897
|
+
)
|
|
3603
3898
|
},
|
|
3604
3899
|
execute: async (args, _ctx) => {
|
|
3605
3900
|
const client = getGitLabClient();
|
|
@@ -3637,8 +3932,10 @@ Work items include issues, epics, tasks, and other work tracking items.`,
|
|
|
3637
3932
|
description: `Get all comments for a work item.
|
|
3638
3933
|
Returns all notes/comments on the work item in chronological order.`,
|
|
3639
3934
|
args: {
|
|
3640
|
-
project_id: z12.string().describe(
|
|
3641
|
-
work_item_id: z12.number().describe(
|
|
3935
|
+
project_id: z12.string().describe('The project ID or full path (e.g. "gitlab-org/gitlab")'),
|
|
3936
|
+
work_item_id: z12.number().describe(
|
|
3937
|
+
"The IID of the work item \u2014 the number visible in the GitLab URL (e.g. for https://gitlab.com/group/project/-/work_items/52, use 52). This is NOT the global database ID."
|
|
3938
|
+
)
|
|
3642
3939
|
},
|
|
3643
3940
|
execute: async (args, _ctx) => {
|
|
3644
3941
|
const client = getGitLabClient();
|
|
@@ -3673,8 +3970,10 @@ Work items are the new unified model for issues, epics, tasks, and other work tr
|
|
|
3673
3970
|
description: `Update an existing work item.
|
|
3674
3971
|
Can update title, description, state, labels, and assignees.`,
|
|
3675
3972
|
args: {
|
|
3676
|
-
project_id: z12.string().describe(
|
|
3677
|
-
work_item_id: z12.number().describe(
|
|
3973
|
+
project_id: z12.string().describe('The project ID or full path (e.g. "gitlab-org/gitlab")'),
|
|
3974
|
+
work_item_id: z12.number().describe(
|
|
3975
|
+
"The IID of the work item \u2014 the number visible in the GitLab URL (e.g. for https://gitlab.com/group/project/-/work_items/52, use 52). This is NOT the global database ID."
|
|
3976
|
+
),
|
|
3678
3977
|
title: z12.string().optional().describe("The new title"),
|
|
3679
3978
|
description: z12.string().optional().describe("The new description (supports Markdown)"),
|
|
3680
3979
|
state_event: z12.enum(["close", "reopen"]).optional().describe("Change the state (close or reopen)"),
|
|
@@ -3696,8 +3995,10 @@ Can update title, description, state, labels, and assignees.`,
|
|
|
3696
3995
|
gitlab_create_work_item_note: tool12({
|
|
3697
3996
|
description: `Create a comment on a work item.`,
|
|
3698
3997
|
args: {
|
|
3699
|
-
project_id: z12.string().describe(
|
|
3700
|
-
work_item_id: z12.number().describe(
|
|
3998
|
+
project_id: z12.string().describe('The project ID or full path (e.g. "gitlab-org/gitlab")'),
|
|
3999
|
+
work_item_id: z12.number().describe(
|
|
4000
|
+
"The IID of the work item \u2014 the number visible in the GitLab URL (e.g. for https://gitlab.com/group/project/-/work_items/52, use 52). This is NOT the global database ID."
|
|
4001
|
+
),
|
|
3701
4002
|
body: z12.string().describe("The content of the note/comment (supports Markdown)")
|
|
3702
4003
|
},
|
|
3703
4004
|
execute: async (args, _ctx) => {
|
|
Binary file
|
package/package.json
CHANGED