glab-agent 0.2.3 → 0.2.5
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/package.json
CHANGED
|
@@ -91,10 +91,10 @@ export interface GitlabClient {
|
|
|
91
91
|
updateUserStatus(emoji: string, message: string, availability?: "busy" | "not_set"): Promise<void>;
|
|
92
92
|
updateUserBio(bio: string): Promise<void>;
|
|
93
93
|
listAllPendingTodos(): Promise<GitlabTodoItem[]>;
|
|
94
|
-
listWikiPages(projectId: number): Promise<WikiPage[]>;
|
|
95
|
-
getWikiPage(projectId: number, slug: string): Promise<WikiPage>;
|
|
96
|
-
createWikiPage(projectId: number, title: string, content: string): Promise<WikiPage>;
|
|
97
|
-
updateWikiPage(projectId: number, slug: string, title: string, content: string): Promise<WikiPage>;
|
|
94
|
+
listWikiPages(projectId: number | string): Promise<WikiPage[]>;
|
|
95
|
+
getWikiPage(projectId: number | string, slug: string): Promise<WikiPage>;
|
|
96
|
+
createWikiPage(projectId: number | string, title: string, content: string): Promise<WikiPage>;
|
|
97
|
+
updateWikiPage(projectId: number | string, slug: string, title: string, content: string): Promise<WikiPage>;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
interface GitlabGlabClientOptions {
|
|
@@ -632,7 +632,7 @@ export class GitlabGlabClient implements GitlabClient {
|
|
|
632
632
|
});
|
|
633
633
|
}
|
|
634
634
|
|
|
635
|
-
async listWikiPages(projectId: number): Promise<WikiPage[]> {
|
|
635
|
+
async listWikiPages(projectId: number | string): Promise<WikiPage[]> {
|
|
636
636
|
const endpoint = this.withQuery(`projects/${projectId}/wikis`, { with_content: "0" });
|
|
637
637
|
let payload: unknown;
|
|
638
638
|
try {
|
|
@@ -656,7 +656,7 @@ export class GitlabGlabClient implements GitlabClient {
|
|
|
656
656
|
.filter((w): w is WikiPage => w !== undefined);
|
|
657
657
|
}
|
|
658
658
|
|
|
659
|
-
async getWikiPage(projectId: number, slug: string): Promise<WikiPage> {
|
|
659
|
+
async getWikiPage(projectId: number | string, slug: string): Promise<WikiPage> {
|
|
660
660
|
const payload = await this.readJson(`projects/${projectId}/wikis/${encodeURIComponent(slug)}`);
|
|
661
661
|
const p = (payload ?? {}) as Payload;
|
|
662
662
|
return {
|
|
@@ -666,7 +666,7 @@ export class GitlabGlabClient implements GitlabClient {
|
|
|
666
666
|
};
|
|
667
667
|
}
|
|
668
668
|
|
|
669
|
-
async createWikiPage(projectId: number, title: string, content: string): Promise<WikiPage> {
|
|
669
|
+
async createWikiPage(projectId: number | string, title: string, content: string): Promise<WikiPage> {
|
|
670
670
|
const stdout = await this.request(`projects/${projectId}/wikis`, {
|
|
671
671
|
method: "POST",
|
|
672
672
|
fields: { title, content }
|
|
@@ -679,7 +679,7 @@ export class GitlabGlabClient implements GitlabClient {
|
|
|
679
679
|
};
|
|
680
680
|
}
|
|
681
681
|
|
|
682
|
-
async updateWikiPage(projectId: number, slug: string, title: string, content: string): Promise<WikiPage> {
|
|
682
|
+
async updateWikiPage(projectId: number | string, slug: string, title: string, content: string): Promise<WikiPage> {
|
|
683
683
|
// title must be passed to preserve directory prefix in slug (GitLab API quirk)
|
|
684
684
|
const stdout = await this.request(`projects/${projectId}/wikis/${encodeURIComponent(slug)}`, {
|
|
685
685
|
method: "PUT",
|
|
@@ -797,6 +797,91 @@ async function updateAgentUserBio(
|
|
|
797
797
|
}
|
|
798
798
|
}
|
|
799
799
|
|
|
800
|
+
async function publishAgentProfileWiki(
|
|
801
|
+
config: LocalAgentConfig,
|
|
802
|
+
dependencies: WatcherDependencies
|
|
803
|
+
): Promise<void> {
|
|
804
|
+
const logger = dependencies.logger ?? console;
|
|
805
|
+
const def = config.agentDefinition;
|
|
806
|
+
if (!def) return;
|
|
807
|
+
|
|
808
|
+
// Resolve project identifier: explicit/inferred ID, or encoded path from git remote
|
|
809
|
+
let projectRef: number | string | undefined = config.gitlabProjectId;
|
|
810
|
+
if (!projectRef) {
|
|
811
|
+
const remoteUrl = readOriginRemote(config.agentRepoPath, execFileSync);
|
|
812
|
+
const remote = remoteUrl ? parseGitRemoteUrl(remoteUrl) : undefined;
|
|
813
|
+
if (remote) {
|
|
814
|
+
// GitLab API accepts URL-encoded project path as project ID
|
|
815
|
+
const projectPath = remote.projectPath.startsWith("git/")
|
|
816
|
+
? remote.projectPath.replace(/^git\//, "")
|
|
817
|
+
: remote.projectPath;
|
|
818
|
+
projectRef = encodeURIComponent(projectPath);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (!projectRef) return;
|
|
822
|
+
|
|
823
|
+
const agentName = def.name;
|
|
824
|
+
const slug = `agents/${agentName}`;
|
|
825
|
+
|
|
826
|
+
// Build profile page content
|
|
827
|
+
const lines: string[] = [
|
|
828
|
+
`# ${def.display_name || agentName}`,
|
|
829
|
+
"",
|
|
830
|
+
];
|
|
831
|
+
|
|
832
|
+
if (def.description) {
|
|
833
|
+
lines.push(def.description, "");
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
// Skills section — skill_refs are the string names from YAML; fall back to parsed skill objects
|
|
837
|
+
const skillNames = def.skill_refs.length > 0
|
|
838
|
+
? def.skill_refs
|
|
839
|
+
: def.skills.map(s => s.name);
|
|
840
|
+
if (skillNames.length > 0) {
|
|
841
|
+
lines.push("## Skills", "", ...skillNames.map(s => `- ${s}`), "");
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// Triggers section
|
|
845
|
+
const triggers = def.triggers;
|
|
846
|
+
if (triggers.labels.length > 0) {
|
|
847
|
+
lines.push("## Trigger Labels", "", ...triggers.labels.map(l => `- \`${l}\``), "");
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// Instructions preview (from preamble)
|
|
851
|
+
if (def.prompt.preamble) {
|
|
852
|
+
lines.push("## Instructions", "", def.prompt.preamble.trim(), "");
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// How to use section
|
|
856
|
+
const botMention = config.botUsername ? `@${config.botUsername}` : `@${agentName}`;
|
|
857
|
+
lines.push(
|
|
858
|
+
"## How to Use",
|
|
859
|
+
"",
|
|
860
|
+
`在 GitLab issue 或 MR 中评论 \`${botMention} <你的需求>\`,agent 会自动接单处理。`,
|
|
861
|
+
"",
|
|
862
|
+
"## Status",
|
|
863
|
+
"",
|
|
864
|
+
`> Provider: \`${def.provider}\` | Poll interval: ${def.poll_interval_seconds ?? 30}s`,
|
|
865
|
+
`>`,
|
|
866
|
+
`> *Auto-updated by glab-agent on ${new Date().toISOString().slice(0, 16).replace("T", " ")}*`,
|
|
867
|
+
);
|
|
868
|
+
|
|
869
|
+
const content = lines.join("\n");
|
|
870
|
+
|
|
871
|
+
try {
|
|
872
|
+
const pages = await dependencies.gitlabClient.listWikiPages(projectRef);
|
|
873
|
+
const existing = pages.find(p => p.slug === slug || p.slug === `agents-${agentName}`);
|
|
874
|
+
if (existing) {
|
|
875
|
+
await dependencies.gitlabClient.updateWikiPage(projectRef, existing.slug, slug, content);
|
|
876
|
+
} else {
|
|
877
|
+
await dependencies.gitlabClient.createWikiPage(projectRef, slug, content);
|
|
878
|
+
}
|
|
879
|
+
logger.info(`Wiki profile published: agents/${agentName}`);
|
|
880
|
+
} catch (error) {
|
|
881
|
+
logger.info?.(`Wiki profile update skipped: ${String(error).slice(0, 100)}`);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
|
|
800
885
|
export async function markAgentOffline(
|
|
801
886
|
_config: LocalAgentConfig,
|
|
802
887
|
gitlabClient: GitlabClient,
|
|
@@ -1178,6 +1263,7 @@ export async function main(argv: string[] = process.argv.slice(2)): Promise<void
|
|
|
1178
1263
|
|
|
1179
1264
|
// Update GitLab user bio with agent profile (P1: Agent = 员工)
|
|
1180
1265
|
await updateAgentUserBio(config, dependencies);
|
|
1266
|
+
await publishAgentProfileWiki(config, dependencies);
|
|
1181
1267
|
await updateAgentUserStatus(dependencies, "idle", undefined, config);
|
|
1182
1268
|
} catch (error) {
|
|
1183
1269
|
logger.error(`Token validation failed for agent "${agentName}": ${String(error)}`);
|