glab-agent 0.2.12 → 0.2.14
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
|
@@ -36,6 +36,8 @@ export interface AgentNotifications {
|
|
|
36
36
|
feishu_app_secret_env?: string;
|
|
37
37
|
/** Email domain for mapping GitLab username → Feishu email (e.g. "taou.com" → "{username}@taou.com") */
|
|
38
38
|
feishu_email_domain?: string;
|
|
39
|
+
/** Feishu group chat_id — send updatable cards to team group instead of webhook */
|
|
40
|
+
feishu_group_chat_id?: string;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
export interface AgentLabelConfig {
|
|
@@ -135,6 +137,7 @@ function parseNotifications(raw: unknown): AgentNotifications {
|
|
|
135
137
|
feishu_app_id_env: typeof obj.feishu_app_id_env === "string" ? obj.feishu_app_id_env : undefined,
|
|
136
138
|
feishu_app_secret_env: typeof obj.feishu_app_secret_env === "string" ? obj.feishu_app_secret_env : undefined,
|
|
137
139
|
feishu_email_domain: typeof obj.feishu_email_domain === "string" ? obj.feishu_email_domain : undefined,
|
|
140
|
+
feishu_group_chat_id: typeof obj.feishu_group_chat_id === "string" ? obj.feishu_group_chat_id : undefined,
|
|
138
141
|
};
|
|
139
142
|
}
|
|
140
143
|
|
|
@@ -59,6 +59,7 @@ const spawnedRuns = new Map<number, { // keyed by issueIid
|
|
|
59
59
|
startedAt: string;
|
|
60
60
|
feishuMessageId?: string;
|
|
61
61
|
feishuOpenId?: string;
|
|
62
|
+
feishuGroupMessageId?: string;
|
|
62
63
|
progressLines?: string[];
|
|
63
64
|
}>();
|
|
64
65
|
|
|
@@ -81,6 +82,7 @@ export interface LocalAgentConfig {
|
|
|
81
82
|
feishuAppId?: string;
|
|
82
83
|
feishuAppSecret?: string;
|
|
83
84
|
feishuEmailDomain?: string;
|
|
85
|
+
feishuGroupChatId?: string;
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
export interface ConfigResolutionOptions {
|
|
@@ -396,6 +398,12 @@ export async function runWatcherCycle(
|
|
|
396
398
|
const logger = dependencies.logger ?? console;
|
|
397
399
|
const state = await dependencies.stateStore.load();
|
|
398
400
|
|
|
401
|
+
// Suppress group webhook when Feishu group card is configured (strict replacement).
|
|
402
|
+
// Personal cards alone don't suppress webhook — team still needs group visibility.
|
|
403
|
+
if (config.feishuGroupChatId && config.webhookUrl) {
|
|
404
|
+
config = { ...config, webhookUrl: undefined };
|
|
405
|
+
}
|
|
406
|
+
|
|
399
407
|
if (state.activeRun && isPidAlive(state.activeRun.pid) && state.activeRun.pid !== pid) {
|
|
400
408
|
logger.info(`Watcher is busy with issue #${state.activeRun.issueIid}.`);
|
|
401
409
|
await updateAgentUserStatus(dependencies, "busy", `#${state.activeRun.issueIid}`);
|
|
@@ -766,6 +774,11 @@ export async function runConcurrentWatcherCycle(
|
|
|
766
774
|
const state = await dependencies.stateStore.load();
|
|
767
775
|
const concurrency = config.agentDefinition?.concurrency ?? 1;
|
|
768
776
|
|
|
777
|
+
// Suppress group webhook when Feishu group card is configured (strict replacement)
|
|
778
|
+
if (config.feishuGroupChatId && config.webhookUrl) {
|
|
779
|
+
config = { ...config, webhookUrl: undefined };
|
|
780
|
+
}
|
|
781
|
+
|
|
769
782
|
// 1. Collect finished tasks
|
|
770
783
|
for (const [issueIid, spawned] of spawnedRuns) {
|
|
771
784
|
const result = await spawned.run.poll();
|
|
@@ -794,8 +807,8 @@ export async function runConcurrentWatcherCycle(
|
|
|
794
807
|
} catch (e) { logger.warn(`Post-run cleanup failed: ${String(e).slice(0, 100)}`); }
|
|
795
808
|
}
|
|
796
809
|
await notifyFailed(config.agentDefinition?.name ?? "agent", issueIid, spawned.issue.title, result.summary, config.webhookUrl);
|
|
797
|
-
// Feishu: update
|
|
798
|
-
if (dependencies.feishuClient
|
|
810
|
+
// Feishu: update cards to failed state
|
|
811
|
+
if (dependencies.feishuClient) {
|
|
799
812
|
const card = buildProgressCard({
|
|
800
813
|
agentName: config.agentDefinition?.name ?? "agent",
|
|
801
814
|
issueIid,
|
|
@@ -806,7 +819,8 @@ export async function runConcurrentWatcherCycle(
|
|
|
806
819
|
summary: result.summary.slice(0, 300),
|
|
807
820
|
duration: `${durationSec}s`,
|
|
808
821
|
});
|
|
809
|
-
dependencies.feishuClient.updateCard(spawned.feishuMessageId, card).catch(() => {});
|
|
822
|
+
if (spawned.feishuMessageId) dependencies.feishuClient.updateCard(spawned.feishuMessageId, card).catch(() => {});
|
|
823
|
+
if (spawned.feishuGroupMessageId) dependencies.feishuClient.updateCard(spawned.feishuGroupMessageId, card).catch(() => {});
|
|
810
824
|
}
|
|
811
825
|
await replaceReactionOnTodo(dependencies.gitlabClient, spawned.todo, "eyes", "x", logger);
|
|
812
826
|
await finalizeTodo(config, dependencies, state, spawned.todo, spawned.issue, {
|
|
@@ -817,8 +831,8 @@ export async function runConcurrentWatcherCycle(
|
|
|
817
831
|
logger.info(`Agent completed issue #${issueIid} in ${durationSec}s. Summary: ${result.summary.slice(0, 200)}`);
|
|
818
832
|
const mr = spawned.issue.projectId ? await dependencies.gitlabClient.findMergeRequestByBranch(spawned.issue.projectId, spawned.worktree.branch).catch(() => undefined) : undefined;
|
|
819
833
|
await notifyCompleted(config.agentDefinition?.name ?? "agent", issueIid, spawned.issue.title, mr?.webUrl || spawned.issue.webUrl || undefined, config.webhookUrl);
|
|
820
|
-
// Feishu: update
|
|
821
|
-
if (dependencies.feishuClient
|
|
834
|
+
// Feishu: update cards to completed state
|
|
835
|
+
if (dependencies.feishuClient) {
|
|
822
836
|
const card = buildProgressCard({
|
|
823
837
|
agentName: config.agentDefinition?.name ?? "agent",
|
|
824
838
|
issueIid,
|
|
@@ -830,7 +844,8 @@ export async function runConcurrentWatcherCycle(
|
|
|
830
844
|
summary: result.summary.slice(0, 300),
|
|
831
845
|
duration: `${durationSec}s`,
|
|
832
846
|
});
|
|
833
|
-
dependencies.feishuClient.updateCard(spawned.feishuMessageId, card).catch(() => {});
|
|
847
|
+
if (spawned.feishuMessageId) dependencies.feishuClient.updateCard(spawned.feishuMessageId, card).catch(() => {});
|
|
848
|
+
if (spawned.feishuGroupMessageId) dependencies.feishuClient.updateCard(spawned.feishuGroupMessageId, card).catch(() => {});
|
|
834
849
|
}
|
|
835
850
|
await replaceReactionOnTodo(dependencies.gitlabClient, spawned.todo, "eyes", "white_check_mark", logger);
|
|
836
851
|
await finalizeTodo(config, dependencies, state, spawned.todo, spawned.issue, {
|
|
@@ -965,7 +980,27 @@ export async function runConcurrentWatcherCycle(
|
|
|
965
980
|
}
|
|
966
981
|
}
|
|
967
982
|
|
|
968
|
-
//
|
|
983
|
+
// Feishu: send accepted card to group chat
|
|
984
|
+
if (dependencies.feishuClient && config.feishuGroupChatId) {
|
|
985
|
+
try {
|
|
986
|
+
const card = buildProgressCard({
|
|
987
|
+
agentName: config.agentDefinition?.name ?? "agent",
|
|
988
|
+
issueIid: issue.iid,
|
|
989
|
+
issueTitle: issue.title,
|
|
990
|
+
issueUrl: issue.webUrl || undefined,
|
|
991
|
+
status: "accepted",
|
|
992
|
+
});
|
|
993
|
+
const groupMsgId = await dependencies.feishuClient.sendCard(config.feishuGroupChatId, card);
|
|
994
|
+
const entry = spawnedRuns.get(issue.iid);
|
|
995
|
+
if (entry && groupMsgId) {
|
|
996
|
+
entry.feishuGroupMessageId = groupMsgId;
|
|
997
|
+
}
|
|
998
|
+
} catch (e) {
|
|
999
|
+
logger.info?.(`Feishu group card send skipped: ${String(e).slice(0, 100)}`);
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
// Set up progress callback for feishu card updates
|
|
969
1004
|
if (config.webhookUrl || dependencies.feishuClient) {
|
|
970
1005
|
const agentName = config.agentDefinition?.name ?? "agent";
|
|
971
1006
|
const issueRef = `#${issue.iid}`;
|
|
@@ -1024,14 +1059,13 @@ export async function runConcurrentWatcherCycle(
|
|
|
1024
1059
|
duration: `${elapsedSec}s`,
|
|
1025
1060
|
});
|
|
1026
1061
|
dependencies.feishuClient.updateCard(spawnedEntry.feishuMessageId, card).catch(() => {});
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
message,
|
|
1032
|
-
status: "accepted",
|
|
1033
|
-
}).catch(() => {});
|
|
1062
|
+
// Also update group card if present
|
|
1063
|
+
if (spawnedEntry.feishuGroupMessageId) {
|
|
1064
|
+
dependencies.feishuClient.updateCard(spawnedEntry.feishuGroupMessageId, card).catch(() => {});
|
|
1065
|
+
}
|
|
1034
1066
|
}
|
|
1067
|
+
// Webhook does NOT receive progress updates — only lifecycle events
|
|
1068
|
+
// (accepted/completed/failed) via notifyXxx functions. This prevents group flooding.
|
|
1035
1069
|
};
|
|
1036
1070
|
}
|
|
1037
1071
|
|
|
@@ -1741,6 +1775,7 @@ export function loadConfigFromAgentDefinition(
|
|
|
1741
1775
|
feishuAppId: def.notifications?.feishu_app_id_env ? env[def.notifications.feishu_app_id_env]?.trim() : undefined,
|
|
1742
1776
|
feishuAppSecret: def.notifications?.feishu_app_secret_env ? env[def.notifications.feishu_app_secret_env]?.trim() : undefined,
|
|
1743
1777
|
feishuEmailDomain: def.notifications?.feishu_email_domain,
|
|
1778
|
+
feishuGroupChatId: def.notifications?.feishu_group_chat_id,
|
|
1744
1779
|
};
|
|
1745
1780
|
}
|
|
1746
1781
|
|