@desplega.ai/agent-swarm 1.102.0 → 1.103.0
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/{actions-j9399ktm.js → actions-7txktrdj.js} +6 -6
- package/dist/{app-tnq1pz27.js → app-xm3xsdye.js} +3 -3
- package/dist/{assistant-c7y92gkw.js → assistant-qpv63wk6.js} +9 -9
- package/dist/{boot-reembed-k7e6fc1p.js → boot-reembed-9cxqka3e.js} +3 -3
- package/dist/{boot-reembed-b97r699t.js → boot-reembed-chxhrwv8.js} +4 -4
- package/dist/{boot-scrub-logs-14kbc61y.js → boot-scrub-logs-8qtfkcz8.js} +2 -2
- package/dist/{claude-managed-adapter-g07dbz3b.js → claude-managed-adapter-z29hjgzz.js} +3 -3
- package/dist/{cli-tsz1q7gk.js → cli-2307phk1.js} +375 -23
- package/dist/{cli-g5px3d7x.js → cli-2957pqpj.js} +24 -1
- package/dist/{cli-9qascwj7.js → cli-2qynerth.js} +1 -1
- package/dist/{cli-k1ghyj8b.js → cli-4fnp2tc3.js} +1 -1
- package/dist/{cli-hc4rd6sv.js → cli-85pf4z38.js} +1 -1
- package/dist/{cli-zk4gn40w.js → cli-8hyv6c2v.js} +6 -14
- package/dist/{cli-k81y1cjb.js → cli-8w95v19d.js} +1 -1
- package/dist/{cli-7xdq3jg3.js → cli-92fqyjcv.js} +1 -1
- package/dist/{cli-zctkpdmd.js → cli-dz3d6zjg.js} +1 -1
- package/dist/{cli-d0t4854c.js → cli-fedn86nz.js} +213 -476
- package/dist/{cli-g861fwjp.js → cli-fwxdt7kt.js} +3 -3
- package/dist/{cli-2aaa9mqr.js → cli-fygaw191.js} +2 -2
- package/dist/{cli-qbc6mncp.js → cli-gzepjz54.js} +2 -2
- package/dist/{cli-r68m8arr.js → cli-jt9d9fjw.js} +1 -1
- package/dist/{cli-axtg1zaa.js → cli-khe4x17a.js} +1 -1
- package/dist/{cli-sygq3fhn.js → cli-kk51f3tf.js} +5 -5
- package/dist/{cli-dgab5x2h.js → cli-krvxq8bc.js} +1 -1
- package/dist/{cli-xde8vhhp.js → cli-ksq38x4n.js} +2 -2
- package/dist/{cli-stqqf5kh.js → cli-m8f6qzck.js} +1 -1
- package/dist/{cli-ap4md0gc.js → cli-ns0r7mkr.js} +30 -5
- package/dist/{cli-t2jk33ta.js → cli-rttgde5f.js} +18 -6
- package/dist/{cli-mhj07xbq.js → cli-rvae030h.js} +3 -3
- package/dist/{cli-q6jzg6wj.js → cli-s14sb64w.js} +4 -4
- package/dist/{cli-zmf7refz.js → cli-v9283nma.js} +1 -1
- package/dist/{cli-fjx4x7nn.js → cli-xmtsan9k.js} +1 -1
- package/dist/{cli-vgck9mqq.js → cli-yeemwevj.js} +155 -37
- package/dist/{cli-5bqa41fd.js → cli-yfwwjeft.js} +1 -1
- package/dist/{cli-s8jw5bmg.js → cli-yp2krx5r.js} +2 -2
- package/dist/cli.js +9 -9
- package/dist/{codex-adapter-wf119mnw.js → codex-adapter-w0xharsg.js} +3 -3
- package/dist/{codex-session-runner-1gknw7mh.js → codex-session-runner-kzbjcm2k.js} +3 -3
- package/dist/{commands-2wyn3swb.js → commands-aqn63mcw.js} +2 -2
- package/dist/{db-567ntpxv.js → db-azrvwsnj.js} +2 -2
- package/dist/{handlers-wvwpk2kj.js → handlers-hf61har3.js} +9 -9
- package/dist/{hook-fatkywc0.js → hook-306p3yz4.js} +2 -2
- package/dist/{http-eq6wxve6.js → http-zts4haq7.js} +81 -62
- package/dist/{index-400x6p3j.js → index-29vg51x6.js} +6 -6
- package/dist/{index-9wqh5352.js → index-3c651yfk.js} +10 -10
- package/dist/{index-6aj8966p.js → index-bfh9hgek.js} +5 -5
- package/dist/{index-d1rm4ea3.js → index-h2yqjyk0.js} +8 -8
- package/dist/{keepalive-6x9nx92g.js → keepalive-a0dg5pds.js} +4 -4
- package/dist/{lead-5fgqwe13.js → lead-7mcxedkc.js} +21 -21
- package/dist/{maintenance-eajx5k1k.js → maintenance-mrzqd53t.js} +4 -4
- package/dist/{onboard-jc1w1edg.js → onboard-4dkpv9wa.js} +2 -2
- package/dist/{otel-impl-8k375amf.js → otel-impl-jt7gpyp9.js} +1 -1
- package/dist/{pi-mono-adapter-hf8sw7hs.js → pi-mono-adapter-zf7dt1wg.js} +1 -1
- package/dist/{pricing-refresh-zed6916t.js → pricing-refresh-xqnzh8dt.js} +4 -4
- package/dist/{seed-pricing-5805qzkz.js → seed-pricing-56tjm1fj.js} +3 -3
- package/dist/{setup-wz05vxh0.js → setup-tbwk8j10.js} +2 -2
- package/dist/{worker-j359graf.js → worker-e03za92t.js} +21 -21
- package/openapi.json +70 -1
- package/package.json +1 -1
- package/src/be/db.ts +83 -13
- package/src/be/migrations/098_repo_hooks_config.sql +3 -0
- package/src/be/task-lifecycle-events.ts +42 -0
- package/src/commands/runner.ts +174 -25
- package/src/github/task-reactions.ts +21 -0
- package/src/hooks/tool-loop-detection.test.ts +40 -0
- package/src/hooks/tool-loop-detection.ts +37 -1
- package/src/http/agents.ts +7 -0
- package/src/http/index.ts +16 -2
- package/src/http/prompt-templates.ts +1 -1
- package/src/http/repos.ts +5 -1
- package/src/http/schedules.ts +1 -1
- package/src/http/session-data.ts +2 -0
- package/src/http/tasks.ts +2 -1
- package/src/http/workflows.ts +1 -0
- package/src/prompts/resolver.ts +1 -1
- package/src/scheduler/scheduler.ts +25 -2
- package/src/server-runtime-counters.ts +12 -0
- package/src/server-user.ts +1 -2
- package/src/server.ts +5 -0
- package/src/telemetry.ts +18 -1
- package/src/tests/http-api-integration.test.ts +4 -0
- package/src/tests/model-control.test.ts +6 -6
- package/src/tests/swarm-repos.test.ts +25 -2
- package/src/tests/task-lifecycle-events.test.ts +53 -0
- package/src/tests/task-lifecycle-telemetry.test.ts +37 -1
- package/src/tests/telemetry-init.test.ts +32 -0
- package/src/tools/prompt-templates/preview.ts +1 -1
- package/src/tools/repos/update-repo.ts +6 -1
- package/src/tools/schedules/create-schedule.ts +1 -1
- package/src/tools/schedules/update-schedule.ts +1 -1
- package/src/tools/send-task.ts +7 -2
- package/src/tools/task-action.ts +6 -2
- package/src/types.ts +155 -1
- package/src/utils/template.ts +127 -0
- package/src/workflows/engine.ts +7 -0
- package/src/workflows/executors/agent-task.ts +1 -2
- package/src/workflows/template.ts +12 -121
- package/src/workflows/triggers.ts +6 -2
- package/templates/community/code-health-reports/PLAYBOOK.md +355 -0
- package/templates/community/code-health-reports/README.md +38 -0
- package/templates/community/code-health-reports/lead-prompt.md +52 -0
- package/templates/community/code-health-reports/report.mjs +378 -0
- package/templates/community/code-health-reports/run.sh +143 -0
- package/templates/schedules/weekly-code-health-reports/config.json +13 -0
- package/templates/schedules/weekly-code-health-reports/content.md +60 -0
- package/src/model-tiers.ts +0 -140
- package/templates/community/.gitkeep +0 -0
|
@@ -13,13 +13,13 @@ import {
|
|
|
13
13
|
ensureTokenOrThrow,
|
|
14
14
|
getOAuthApp,
|
|
15
15
|
getOAuthTokens
|
|
16
|
-
} from "./cli-
|
|
16
|
+
} from "./cli-v9283nma.js";
|
|
17
17
|
import {
|
|
18
18
|
startPricingRefreshLoop
|
|
19
|
-
} from "./cli-
|
|
19
|
+
} from "./cli-ksq38x4n.js";
|
|
20
20
|
import {
|
|
21
21
|
seedPricingFromModelsDev
|
|
22
|
-
} from "./cli-
|
|
22
|
+
} from "./cli-m8f6qzck.js";
|
|
23
23
|
import {
|
|
24
24
|
createTrackerAgentMapping,
|
|
25
25
|
createTrackerSync,
|
|
@@ -27,13 +27,13 @@ import {
|
|
|
27
27
|
deleteTrackerSync,
|
|
28
28
|
getAllTrackerSyncs,
|
|
29
29
|
repointTrackerSyncBySwarmId
|
|
30
|
-
} from "./cli-
|
|
30
|
+
} from "./cli-4fnp2tc3.js";
|
|
31
31
|
import {
|
|
32
32
|
cancelWorkflowRun,
|
|
33
33
|
getExecutorRegistry,
|
|
34
34
|
retryFailedRun,
|
|
35
35
|
snapshotWorkflow
|
|
36
|
-
} from "./cli-
|
|
36
|
+
} from "./cli-8hyv6c2v.js";
|
|
37
37
|
import {
|
|
38
38
|
getApiKey
|
|
39
39
|
} from "./cli-f14fvzag.js";
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
getEmbeddingProvider,
|
|
48
48
|
getMemoryStore,
|
|
49
49
|
init_constants
|
|
50
|
-
} from "./cli-
|
|
50
|
+
} from "./cli-8w95v19d.js";
|
|
51
51
|
import {
|
|
52
52
|
ZodFirstPartyTypeKind,
|
|
53
53
|
objectType
|
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
ensure,
|
|
58
58
|
require_dist,
|
|
59
59
|
runScheduleNow
|
|
60
|
-
} from "./cli-
|
|
60
|
+
} from "./cli-ns0r7mkr.js";
|
|
61
61
|
import {
|
|
62
62
|
TriggerSchemaError,
|
|
63
63
|
applyDefinitionPatch,
|
|
@@ -65,13 +65,13 @@ import {
|
|
|
65
65
|
startWorkflowExecution,
|
|
66
66
|
validateDefinition,
|
|
67
67
|
validateJsonSchema
|
|
68
|
-
} from "./cli-
|
|
68
|
+
} from "./cli-rttgde5f.js";
|
|
69
69
|
import {
|
|
70
70
|
extractSlackMessageText
|
|
71
71
|
} from "./cli-2deg0cen.js";
|
|
72
72
|
import {
|
|
73
73
|
getSlackApp
|
|
74
|
-
} from "./cli-
|
|
74
|
+
} from "./cli-kk51f3tf.js";
|
|
75
75
|
import {
|
|
76
76
|
findUserByEmail,
|
|
77
77
|
findUserByExternalId,
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
linkIdentity,
|
|
81
81
|
recordIdentityEvent,
|
|
82
82
|
unlinkIdentity
|
|
83
|
-
} from "./cli-
|
|
83
|
+
} from "./cli-yfwwjeft.js";
|
|
84
84
|
import {
|
|
85
85
|
markdownToSlack
|
|
86
86
|
} from "./cli-z92pkwzn.js";
|
|
@@ -91,7 +91,7 @@ import {
|
|
|
91
91
|
} from "./cli-dh55d5fg.js";
|
|
92
92
|
import {
|
|
93
93
|
agentContextKey
|
|
94
|
-
} from "./cli-
|
|
94
|
+
} from "./cli-jt9d9fjw.js";
|
|
95
95
|
import {
|
|
96
96
|
AgentLogSchema,
|
|
97
97
|
AgentMemorySchema,
|
|
@@ -123,6 +123,7 @@ import {
|
|
|
123
123
|
PromptTemplateScopeSchema,
|
|
124
124
|
PromptTemplateStateSchema,
|
|
125
125
|
RepoGuidelinesSchema,
|
|
126
|
+
RepoHooksSchema,
|
|
126
127
|
ScriptRunStatusSchema,
|
|
127
128
|
ServiceSchema,
|
|
128
129
|
ServiceStatusSchema,
|
|
@@ -243,11 +244,11 @@ import {
|
|
|
243
244
|
initDb,
|
|
244
245
|
init_db,
|
|
245
246
|
init_defaults,
|
|
246
|
-
init_model_tiers,
|
|
247
247
|
init_registry,
|
|
248
248
|
init_request_auth_context,
|
|
249
249
|
init_resolver,
|
|
250
250
|
init_swarm_config_guard,
|
|
251
|
+
init_task_lifecycle_events,
|
|
251
252
|
init_template,
|
|
252
253
|
init_types,
|
|
253
254
|
insertTaskAttachment,
|
|
@@ -266,6 +267,7 @@ import {
|
|
|
266
267
|
maskSecrets,
|
|
267
268
|
moveTaskFromBacklog,
|
|
268
269
|
moveTaskToBacklog,
|
|
270
|
+
onTaskStarted,
|
|
269
271
|
postMessage,
|
|
270
272
|
reassociateSessionLogs,
|
|
271
273
|
recordBudgetRefusalNotification,
|
|
@@ -302,7 +304,7 @@ import {
|
|
|
302
304
|
upsertService,
|
|
303
305
|
upsertSwarmConfig,
|
|
304
306
|
validateConfigValue
|
|
305
|
-
} from "./cli-
|
|
307
|
+
} from "./cli-fedn86nz.js";
|
|
306
308
|
import {
|
|
307
309
|
init_zod
|
|
308
310
|
} from "./cli-q21d49ac.js";
|
|
@@ -346,7 +348,7 @@ import {
|
|
|
346
348
|
import {
|
|
347
349
|
init_package,
|
|
348
350
|
package_default
|
|
349
|
-
} from "./cli-
|
|
351
|
+
} from "./cli-85pf4z38.js";
|
|
350
352
|
import {
|
|
351
353
|
init_secret_scrubber,
|
|
352
354
|
registerVolatileSecret,
|
|
@@ -11208,6 +11210,356 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
11208
11210
|
init_package();
|
|
11209
11211
|
init_db();
|
|
11210
11212
|
|
|
11213
|
+
// src/github/task-reactions.ts
|
|
11214
|
+
init_task_lifecycle_events();
|
|
11215
|
+
|
|
11216
|
+
// src/github/app.ts
|
|
11217
|
+
var initialized = false;
|
|
11218
|
+
var webhookSecret = null;
|
|
11219
|
+
var appId = null;
|
|
11220
|
+
var privateKey = null;
|
|
11221
|
+
var tokenCache = new Map;
|
|
11222
|
+
function isGitHubEnabled() {
|
|
11223
|
+
const githubDisable = process.env.GITHUB_DISABLE;
|
|
11224
|
+
if (githubDisable === "true" || githubDisable === "1") {
|
|
11225
|
+
return false;
|
|
11226
|
+
}
|
|
11227
|
+
return !!process.env.GITHUB_WEBHOOK_SECRET;
|
|
11228
|
+
}
|
|
11229
|
+
function resetGitHub() {
|
|
11230
|
+
initialized = false;
|
|
11231
|
+
webhookSecret = null;
|
|
11232
|
+
appId = null;
|
|
11233
|
+
privateKey = null;
|
|
11234
|
+
tokenCache.clear();
|
|
11235
|
+
}
|
|
11236
|
+
function initGitHub() {
|
|
11237
|
+
if (initialized) {
|
|
11238
|
+
console.log("[GitHub] Already initialized, skipping");
|
|
11239
|
+
return isGitHubEnabled();
|
|
11240
|
+
}
|
|
11241
|
+
initialized = true;
|
|
11242
|
+
const githubDisable = process.env.GITHUB_DISABLE;
|
|
11243
|
+
if (githubDisable === "true" || githubDisable === "1") {
|
|
11244
|
+
console.log("[GitHub] Disabled via GITHUB_DISABLE");
|
|
11245
|
+
return false;
|
|
11246
|
+
}
|
|
11247
|
+
webhookSecret = process.env.GITHUB_WEBHOOK_SECRET ?? null;
|
|
11248
|
+
if (!webhookSecret) {
|
|
11249
|
+
console.log("[GitHub] Missing GITHUB_WEBHOOK_SECRET, GitHub integration disabled");
|
|
11250
|
+
return false;
|
|
11251
|
+
}
|
|
11252
|
+
appId = process.env.GITHUB_APP_ID ?? null;
|
|
11253
|
+
const rawPrivateKey = process.env.GITHUB_APP_PRIVATE_KEY ?? null;
|
|
11254
|
+
if (appId && rawPrivateKey) {
|
|
11255
|
+
if (rawPrivateKey.startsWith("-----BEGIN")) {
|
|
11256
|
+
privateKey = rawPrivateKey.replace(/\\n/g, `
|
|
11257
|
+
`);
|
|
11258
|
+
} else {
|
|
11259
|
+
privateKey = Buffer.from(rawPrivateKey, "base64").toString("utf-8");
|
|
11260
|
+
}
|
|
11261
|
+
console.log("[GitHub] App credentials loaded for bot reactions");
|
|
11262
|
+
} else {
|
|
11263
|
+
console.log("[GitHub] No App credentials, bot reactions disabled");
|
|
11264
|
+
}
|
|
11265
|
+
console.log("[GitHub] Webhook handler initialized");
|
|
11266
|
+
return true;
|
|
11267
|
+
}
|
|
11268
|
+
function isReactionsEnabled() {
|
|
11269
|
+
return !!(appId && privateKey);
|
|
11270
|
+
}
|
|
11271
|
+
async function verifyWebhookSignature(payload, signature) {
|
|
11272
|
+
if (!webhookSecret || !signature) {
|
|
11273
|
+
console.log(`[GitHub] Signature verification failed: webhookSecret=${!!webhookSecret}, signature=${!!signature}`);
|
|
11274
|
+
return false;
|
|
11275
|
+
}
|
|
11276
|
+
if (!signature.startsWith("sha256=")) {
|
|
11277
|
+
return false;
|
|
11278
|
+
}
|
|
11279
|
+
const expectedSig = signature.slice(7);
|
|
11280
|
+
const encoder = new TextEncoder;
|
|
11281
|
+
const key = await crypto.subtle.importKey("raw", encoder.encode(webhookSecret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
11282
|
+
const signatureBuffer = await crypto.subtle.sign("HMAC", key, encoder.encode(payload));
|
|
11283
|
+
const computedSig = Array.from(new Uint8Array(signatureBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
11284
|
+
if (computedSig.length !== expectedSig.length) {
|
|
11285
|
+
console.log(`[GitHub] Signature length mismatch: computed=${computedSig.length}, expected=${expectedSig.length}`);
|
|
11286
|
+
return false;
|
|
11287
|
+
}
|
|
11288
|
+
let result = 0;
|
|
11289
|
+
for (let i = 0;i < computedSig.length; i++) {
|
|
11290
|
+
result |= computedSig.charCodeAt(i) ^ expectedSig.charCodeAt(i);
|
|
11291
|
+
}
|
|
11292
|
+
const isValid = result === 0;
|
|
11293
|
+
if (!isValid) {
|
|
11294
|
+
console.log(`[GitHub] Signature mismatch:`);
|
|
11295
|
+
console.log(` Expected: ${expectedSig}`);
|
|
11296
|
+
console.log(` Computed: ${computedSig}`);
|
|
11297
|
+
}
|
|
11298
|
+
return isValid;
|
|
11299
|
+
}
|
|
11300
|
+
async function generateAppJWT() {
|
|
11301
|
+
if (!appId || !privateKey) {
|
|
11302
|
+
return null;
|
|
11303
|
+
}
|
|
11304
|
+
const now = Math.floor(Date.now() / 1000);
|
|
11305
|
+
const payload = {
|
|
11306
|
+
iat: now - 60,
|
|
11307
|
+
exp: now + 600,
|
|
11308
|
+
iss: appId
|
|
11309
|
+
};
|
|
11310
|
+
const base64url = (data) => {
|
|
11311
|
+
const base64 = Buffer.isBuffer(data) ? data.toString("base64") : Buffer.from(data).toString("base64");
|
|
11312
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
11313
|
+
};
|
|
11314
|
+
const header = { alg: "RS256", typ: "JWT" };
|
|
11315
|
+
const headerB64 = base64url(JSON.stringify(header));
|
|
11316
|
+
const payloadB64 = base64url(JSON.stringify(payload));
|
|
11317
|
+
const signingInput = `${headerB64}.${payloadB64}`;
|
|
11318
|
+
try {
|
|
11319
|
+
const crypto2 = await import("node:crypto");
|
|
11320
|
+
const sign = crypto2.createSign("RSA-SHA256");
|
|
11321
|
+
sign.update(signingInput);
|
|
11322
|
+
const signature = sign.sign(privateKey);
|
|
11323
|
+
const signatureB64 = base64url(signature);
|
|
11324
|
+
return `${signingInput}.${signatureB64}`;
|
|
11325
|
+
} catch (error) {
|
|
11326
|
+
console.error("[GitHub] Failed to generate JWT:", error);
|
|
11327
|
+
return null;
|
|
11328
|
+
}
|
|
11329
|
+
}
|
|
11330
|
+
async function getInstallationToken(installationId) {
|
|
11331
|
+
const cached = tokenCache.get(installationId);
|
|
11332
|
+
if (cached && cached.expiresAt > Date.now() + 60000) {
|
|
11333
|
+
return cached.token;
|
|
11334
|
+
}
|
|
11335
|
+
const jwt = await generateAppJWT();
|
|
11336
|
+
if (!jwt) {
|
|
11337
|
+
console.log("[GitHub] No JWT available, cannot get installation token");
|
|
11338
|
+
return null;
|
|
11339
|
+
}
|
|
11340
|
+
try {
|
|
11341
|
+
const response = await fetch(`https://api.github.com/app/installations/${installationId}/access_tokens`, {
|
|
11342
|
+
method: "POST",
|
|
11343
|
+
headers: {
|
|
11344
|
+
Accept: "application/vnd.github+json",
|
|
11345
|
+
Authorization: `Bearer ${jwt}`,
|
|
11346
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
11347
|
+
}
|
|
11348
|
+
});
|
|
11349
|
+
if (!response.ok) {
|
|
11350
|
+
const errorText = await response.text();
|
|
11351
|
+
console.error(`[GitHub] Failed to get installation token: ${response.status} ${errorText}`);
|
|
11352
|
+
return null;
|
|
11353
|
+
}
|
|
11354
|
+
const data = await response.json();
|
|
11355
|
+
const expiresAt = new Date(data.expires_at).getTime();
|
|
11356
|
+
tokenCache.set(installationId, { token: data.token, expiresAt });
|
|
11357
|
+
console.log(`[GitHub] Got installation token for ${installationId}, expires at ${data.expires_at}`);
|
|
11358
|
+
return data.token;
|
|
11359
|
+
} catch (error) {
|
|
11360
|
+
console.error("[GitHub] Error getting installation token:", error);
|
|
11361
|
+
return null;
|
|
11362
|
+
}
|
|
11363
|
+
}
|
|
11364
|
+
|
|
11365
|
+
// src/github/reactions.ts
|
|
11366
|
+
async function addReaction(repo, commentId, reaction, installationId) {
|
|
11367
|
+
if (!isReactionsEnabled()) {
|
|
11368
|
+
console.log("[GitHub] Reactions not enabled, skipping");
|
|
11369
|
+
return false;
|
|
11370
|
+
}
|
|
11371
|
+
const token = await getInstallationToken(installationId);
|
|
11372
|
+
if (!token) {
|
|
11373
|
+
console.log("[GitHub] No installation token, skipping reaction");
|
|
11374
|
+
return false;
|
|
11375
|
+
}
|
|
11376
|
+
try {
|
|
11377
|
+
const response = await fetch(`https://api.github.com/repos/${repo}/issues/comments/${commentId}/reactions`, {
|
|
11378
|
+
method: "POST",
|
|
11379
|
+
headers: {
|
|
11380
|
+
Accept: "application/vnd.github+json",
|
|
11381
|
+
Authorization: `Bearer ${token}`,
|
|
11382
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
11383
|
+
"Content-Type": "application/json"
|
|
11384
|
+
},
|
|
11385
|
+
body: JSON.stringify({ content: reaction })
|
|
11386
|
+
});
|
|
11387
|
+
if (!response.ok) {
|
|
11388
|
+
const errorText = await response.text();
|
|
11389
|
+
console.error(`[GitHub] Failed to add reaction: ${response.status} ${errorText}`);
|
|
11390
|
+
return false;
|
|
11391
|
+
}
|
|
11392
|
+
console.log(`[GitHub] Added ${reaction} reaction to comment ${commentId}`);
|
|
11393
|
+
return true;
|
|
11394
|
+
} catch (error) {
|
|
11395
|
+
console.error("[GitHub] Error adding reaction:", error);
|
|
11396
|
+
return false;
|
|
11397
|
+
}
|
|
11398
|
+
}
|
|
11399
|
+
async function addIssueReaction(repo, issueNumber, reaction, installationId) {
|
|
11400
|
+
if (!isReactionsEnabled()) {
|
|
11401
|
+
console.log("[GitHub] Reactions not enabled, skipping");
|
|
11402
|
+
return false;
|
|
11403
|
+
}
|
|
11404
|
+
const token = await getInstallationToken(installationId);
|
|
11405
|
+
if (!token) {
|
|
11406
|
+
console.log("[GitHub] No installation token, skipping reaction");
|
|
11407
|
+
return false;
|
|
11408
|
+
}
|
|
11409
|
+
try {
|
|
11410
|
+
const response = await fetch(`https://api.github.com/repos/${repo}/issues/${issueNumber}/reactions`, {
|
|
11411
|
+
method: "POST",
|
|
11412
|
+
headers: {
|
|
11413
|
+
Accept: "application/vnd.github+json",
|
|
11414
|
+
Authorization: `Bearer ${token}`,
|
|
11415
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
11416
|
+
"Content-Type": "application/json"
|
|
11417
|
+
},
|
|
11418
|
+
body: JSON.stringify({ content: reaction })
|
|
11419
|
+
});
|
|
11420
|
+
if (!response.ok) {
|
|
11421
|
+
const errorText = await response.text();
|
|
11422
|
+
console.error(`[GitHub] Failed to add issue reaction: ${response.status} ${errorText}`);
|
|
11423
|
+
return false;
|
|
11424
|
+
}
|
|
11425
|
+
console.log(`[GitHub] Added ${reaction} reaction to issue/PR #${issueNumber}`);
|
|
11426
|
+
return true;
|
|
11427
|
+
} catch (error) {
|
|
11428
|
+
console.error("[GitHub] Error adding issue reaction:", error);
|
|
11429
|
+
return false;
|
|
11430
|
+
}
|
|
11431
|
+
}
|
|
11432
|
+
async function addPullReviewCommentReaction(repo, commentId, reaction, installationId) {
|
|
11433
|
+
if (!isReactionsEnabled()) {
|
|
11434
|
+
console.log("[GitHub] Reactions not enabled, skipping");
|
|
11435
|
+
return false;
|
|
11436
|
+
}
|
|
11437
|
+
const token = await getInstallationToken(installationId);
|
|
11438
|
+
if (!token) {
|
|
11439
|
+
console.log("[GitHub] No installation token, skipping reaction");
|
|
11440
|
+
return false;
|
|
11441
|
+
}
|
|
11442
|
+
try {
|
|
11443
|
+
const response = await fetch(`https://api.github.com/repos/${repo}/pulls/comments/${commentId}/reactions`, {
|
|
11444
|
+
method: "POST",
|
|
11445
|
+
headers: {
|
|
11446
|
+
Accept: "application/vnd.github+json",
|
|
11447
|
+
Authorization: `Bearer ${token}`,
|
|
11448
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
11449
|
+
"Content-Type": "application/json"
|
|
11450
|
+
},
|
|
11451
|
+
body: JSON.stringify({ content: reaction })
|
|
11452
|
+
});
|
|
11453
|
+
if (!response.ok) {
|
|
11454
|
+
const errorText = await response.text();
|
|
11455
|
+
console.error(`[GitHub] Failed to add PR review comment reaction: ${response.status} ${errorText}`);
|
|
11456
|
+
return false;
|
|
11457
|
+
}
|
|
11458
|
+
console.log(`[GitHub] Added ${reaction} reaction to PR review comment ${commentId}`);
|
|
11459
|
+
return true;
|
|
11460
|
+
} catch (error) {
|
|
11461
|
+
console.error("[GitHub] Error adding PR review comment reaction:", error);
|
|
11462
|
+
return false;
|
|
11463
|
+
}
|
|
11464
|
+
}
|
|
11465
|
+
async function addGraphQLReaction(nodeId, reaction, installationId) {
|
|
11466
|
+
if (!isReactionsEnabled()) {
|
|
11467
|
+
console.log("[GitHub] Reactions not enabled, skipping");
|
|
11468
|
+
return false;
|
|
11469
|
+
}
|
|
11470
|
+
const token = await getInstallationToken(installationId);
|
|
11471
|
+
if (!token) {
|
|
11472
|
+
console.log("[GitHub] No installation token, skipping GraphQL reaction");
|
|
11473
|
+
return false;
|
|
11474
|
+
}
|
|
11475
|
+
try {
|
|
11476
|
+
const response = await fetch("https://api.github.com/graphql", {
|
|
11477
|
+
method: "POST",
|
|
11478
|
+
headers: {
|
|
11479
|
+
Authorization: `Bearer ${token}`,
|
|
11480
|
+
"Content-Type": "application/json"
|
|
11481
|
+
},
|
|
11482
|
+
body: JSON.stringify({
|
|
11483
|
+
query: `mutation AddReaction($input: AddReactionInput!) {
|
|
11484
|
+
addReaction(input: $input) {
|
|
11485
|
+
reaction { content }
|
|
11486
|
+
}
|
|
11487
|
+
}`,
|
|
11488
|
+
variables: {
|
|
11489
|
+
input: { subjectId: nodeId, content: reaction }
|
|
11490
|
+
}
|
|
11491
|
+
})
|
|
11492
|
+
});
|
|
11493
|
+
if (!response.ok) {
|
|
11494
|
+
const errorText = await response.text();
|
|
11495
|
+
console.error(`[GitHub] GraphQL reaction failed: ${response.status} ${errorText}`);
|
|
11496
|
+
return false;
|
|
11497
|
+
}
|
|
11498
|
+
const data = await response.json();
|
|
11499
|
+
if (data.errors?.length) {
|
|
11500
|
+
console.error(`[GitHub] GraphQL reaction errors: ${JSON.stringify(data.errors)}`);
|
|
11501
|
+
return false;
|
|
11502
|
+
}
|
|
11503
|
+
console.log(`[GitHub] Added ${reaction} GraphQL reaction to node ${nodeId}`);
|
|
11504
|
+
return true;
|
|
11505
|
+
} catch (error) {
|
|
11506
|
+
console.error("[GitHub] Error adding GraphQL reaction:", error);
|
|
11507
|
+
return false;
|
|
11508
|
+
}
|
|
11509
|
+
}
|
|
11510
|
+
|
|
11511
|
+
// src/github/task-reactions.ts
|
|
11512
|
+
async function addEyesReactionOnTaskStart(task) {
|
|
11513
|
+
if (task.source !== "github" || task.vcsProvider !== "github")
|
|
11514
|
+
return;
|
|
11515
|
+
if (!task.vcsInstallationId)
|
|
11516
|
+
return;
|
|
11517
|
+
const installationId = task.vcsInstallationId;
|
|
11518
|
+
const repo = task.vcsRepo;
|
|
11519
|
+
if (!repo)
|
|
11520
|
+
return;
|
|
11521
|
+
try {
|
|
11522
|
+
switch (task.vcsEventType) {
|
|
11523
|
+
case "issue_comment": {
|
|
11524
|
+
if (task.vcsCommentId) {
|
|
11525
|
+
await addReaction(repo, task.vcsCommentId, "eyes", installationId);
|
|
11526
|
+
}
|
|
11527
|
+
break;
|
|
11528
|
+
}
|
|
11529
|
+
case "pull_request_review_comment": {
|
|
11530
|
+
if (task.vcsCommentId) {
|
|
11531
|
+
await addPullReviewCommentReaction(repo, task.vcsCommentId, "eyes", installationId);
|
|
11532
|
+
}
|
|
11533
|
+
break;
|
|
11534
|
+
}
|
|
11535
|
+
case "pull_request_review": {
|
|
11536
|
+
if (task.vcsNodeId) {
|
|
11537
|
+
await addGraphQLReaction(task.vcsNodeId, "EYES", installationId);
|
|
11538
|
+
}
|
|
11539
|
+
break;
|
|
11540
|
+
}
|
|
11541
|
+
case "pull_request":
|
|
11542
|
+
case "issues": {
|
|
11543
|
+
if (task.vcsNumber) {
|
|
11544
|
+
await addIssueReaction(repo, task.vcsNumber, "eyes", installationId);
|
|
11545
|
+
}
|
|
11546
|
+
break;
|
|
11547
|
+
}
|
|
11548
|
+
}
|
|
11549
|
+
} catch (error) {
|
|
11550
|
+
console.error("[GitHub] Failed to add eyes reaction on task start:", error);
|
|
11551
|
+
}
|
|
11552
|
+
}
|
|
11553
|
+
var registered = false;
|
|
11554
|
+
function registerGithubTaskReactions() {
|
|
11555
|
+
if (registered)
|
|
11556
|
+
return;
|
|
11557
|
+
registered = true;
|
|
11558
|
+
onTaskStarted((task) => {
|
|
11559
|
+
addEyesReactionOnTaskStart(task).catch(() => {});
|
|
11560
|
+
});
|
|
11561
|
+
}
|
|
11562
|
+
|
|
11211
11563
|
// src/tools/cancel-task.ts
|
|
11212
11564
|
init_zod();
|
|
11213
11565
|
init_db();
|
|
@@ -11255,7 +11607,7 @@ var NOOP_SPAN = {
|
|
|
11255
11607
|
setStatus: () => NOOP_SPAN,
|
|
11256
11608
|
end: () => {}
|
|
11257
11609
|
};
|
|
11258
|
-
var
|
|
11610
|
+
var initialized2 = false;
|
|
11259
11611
|
var realWithSpan;
|
|
11260
11612
|
var realStartSpan;
|
|
11261
11613
|
var realWithRemoteContext;
|
|
@@ -11267,11 +11619,11 @@ function isPollTracingEnabled() {
|
|
|
11267
11619
|
return v === "1" || v === "true" || v === "yes" || v === "on";
|
|
11268
11620
|
}
|
|
11269
11621
|
async function initOtel(serviceRole = process.env.AGENT_ROLE || "api") {
|
|
11270
|
-
if (!enabled ||
|
|
11622
|
+
if (!enabled || initialized2)
|
|
11271
11623
|
return;
|
|
11272
|
-
|
|
11624
|
+
initialized2 = true;
|
|
11273
11625
|
try {
|
|
11274
|
-
const impl = await import("./otel-impl-
|
|
11626
|
+
const impl = await import("./otel-impl-jt7gpyp9.js");
|
|
11275
11627
|
await impl.boot(serviceRole);
|
|
11276
11628
|
realWithSpan = impl.withSpan;
|
|
11277
11629
|
realStartSpan = impl.startSpan;
|
|
@@ -16565,6 +16917,7 @@ var registerUpdateRepoTool = (server) => {
|
|
|
16565
16917
|
clonePath: string().optional().describe("New clone path."),
|
|
16566
16918
|
defaultBranch: string().optional().describe("New default branch."),
|
|
16567
16919
|
autoClone: boolean().optional().describe("Whether to auto-clone."),
|
|
16920
|
+
hooks: RepoHooksSchema.nullable().optional().describe("Repository hook install config. Set { enabled: true } to opt into best-effort worker hook installation, or null to disable."),
|
|
16568
16921
|
guidelines: RepoGuidelinesSchema.nullable().optional().describe("Repository guidelines: prChecks (commands before PR), mergeChecks (conditions before merge), allowMerge (default false), review (guidance for reviewers). Pass null to clear.")
|
|
16569
16922
|
}),
|
|
16570
16923
|
outputSchema: object({
|
|
@@ -16753,7 +17106,7 @@ function resolveHttpAuditUserId(req, callerAgentId) {
|
|
|
16753
17106
|
|
|
16754
17107
|
// src/tools/schedules/create-schedule.ts
|
|
16755
17108
|
init_db();
|
|
16756
|
-
|
|
17109
|
+
init_types();
|
|
16757
17110
|
var createScheduleInputSchema = object({
|
|
16758
17111
|
name: string().min(1).max(100).describe("Unique name for the schedule (e.g., 'daily-cleanup')"),
|
|
16759
17112
|
taskTemplate: string().min(1).describe("The task description that will be created each time"),
|
|
@@ -17327,7 +17680,7 @@ function validateRecurringTiming(merged) {
|
|
|
17327
17680
|
}
|
|
17328
17681
|
|
|
17329
17682
|
// src/tools/schedules/update-schedule.ts
|
|
17330
|
-
|
|
17683
|
+
init_types();
|
|
17331
17684
|
var updateScheduleInputSchema = object({
|
|
17332
17685
|
scheduleId: string().uuid().optional().describe("Schedule ID to update"),
|
|
17333
17686
|
name: string().optional().describe("Schedule name to update (alternative to ID)"),
|
|
@@ -17908,7 +18261,6 @@ function findDuplicateTask(opts) {
|
|
|
17908
18261
|
|
|
17909
18262
|
// src/tools/send-task.ts
|
|
17910
18263
|
init_types();
|
|
17911
|
-
init_model_tiers();
|
|
17912
18264
|
var sendTaskInputSchema = object({
|
|
17913
18265
|
agentId: uuid().optional().describe("The agent to assign/offer task to. Omit to create unassigned task for pool."),
|
|
17914
18266
|
task: string().min(1).describe("The task description to send."),
|
|
@@ -21673,7 +22025,6 @@ function emitBudgetRefusalSideEffects(ctx, inserted) {
|
|
|
21673
22025
|
// src/tools/task-action.ts
|
|
21674
22026
|
init_db();
|
|
21675
22027
|
init_types();
|
|
21676
|
-
init_model_tiers();
|
|
21677
22028
|
var TaskActionSchema = _enum([
|
|
21678
22029
|
"create",
|
|
21679
22030
|
"claim",
|
|
@@ -23586,6 +23937,7 @@ function createServer() {
|
|
|
23586
23937
|
initDb(process.env.DATABASE_PATH);
|
|
23587
23938
|
seedPricingFromModelsDev();
|
|
23588
23939
|
startPricingRefreshLoop();
|
|
23940
|
+
registerGithubTaskReactions();
|
|
23589
23941
|
const server = new McpServer({
|
|
23590
23942
|
name: package_default.name,
|
|
23591
23943
|
version: package_default.version,
|
|
@@ -23868,4 +24220,4 @@ function writeSkillsToFilesystem(entries, harnessType = "all", home) {
|
|
|
23868
24220
|
return { synced, removed, errors };
|
|
23869
24221
|
}
|
|
23870
24222
|
|
|
23871
|
-
export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, userCtx, isPollTracingEnabled, initOtel, withSpan, startSpan, withSpanContext, withRemoteContext, injectTraceContext, createToolRegistrar, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, setCorsHeaders, parseQueryParams, getPathSegments, safeRequestUrlForLog, agentWithCapacity, parseBody, BODY_TOO_LARGE, enforceContentLengthCap, json, jsonError, triggerSchemaErrorResponse, deriveApiBaseUrl, httpServerSemconvAttributes, routeRegistry, isPublicRoute, describeRequestRoute, route, assertSelectOnlyQuery, executeReadOnlyQuery, handleDbQuery, snapshotMetric, snapshotPage, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, recordRetrievals, rerank, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, resolveHttpAuditUserId, mergeScheduleTiming, validateRecurringTiming, sendTaskOutputSchema, sendTaskHandler, parseSkillContent, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, canClaim, emitBudgetRefusalSideEffects, taskActionInputSchema, taskActionOutputSchema, taskActionHandler, hasCapability, getEnabledCapabilities, createServer, writeSkillsToFilesystem };
|
|
24223
|
+
export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, resetGitHub, initGitHub, verifyWebhookSignature, getInstallationToken, addReaction, addIssueReaction, userCtx, isPollTracingEnabled, initOtel, withSpan, startSpan, withSpanContext, withRemoteContext, injectTraceContext, createToolRegistrar, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, setCorsHeaders, parseQueryParams, getPathSegments, safeRequestUrlForLog, agentWithCapacity, parseBody, BODY_TOO_LARGE, enforceContentLengthCap, json, jsonError, triggerSchemaErrorResponse, deriveApiBaseUrl, httpServerSemconvAttributes, routeRegistry, isPublicRoute, describeRequestRoute, route, assertSelectOnlyQuery, executeReadOnlyQuery, handleDbQuery, snapshotMetric, snapshotPage, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, recordRetrievals, rerank, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, resolveHttpAuditUserId, mergeScheduleTiming, validateRecurringTiming, sendTaskOutputSchema, sendTaskHandler, parseSkillContent, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, canClaim, emitBudgetRefusalSideEffects, taskActionInputSchema, taskActionOutputSchema, taskActionHandler, hasCapability, getEnabledCapabilities, createServer, writeSkillsToFilesystem };
|
|
@@ -3,6 +3,7 @@ var HISTORY_DIR = "/tmp/agent-swarm-tool-history";
|
|
|
3
3
|
var MAX_HISTORY = 30;
|
|
4
4
|
var REPEAT_WARNING_THRESHOLD = 8;
|
|
5
5
|
var REPEAT_CRITICAL_THRESHOLD = 15;
|
|
6
|
+
var LOW_CARDINALITY_FILE_CHANGE_CRITICAL_THRESHOLD = 24;
|
|
6
7
|
var PINGPONG_WARNING_THRESHOLD = 6;
|
|
7
8
|
var PINGPONG_CRITICAL_THRESHOLD = 12;
|
|
8
9
|
function hashArgs(args) {
|
|
@@ -15,6 +16,27 @@ function hashArgs(args) {
|
|
|
15
16
|
}
|
|
16
17
|
return hash.toString(36);
|
|
17
18
|
}
|
|
19
|
+
function isCodexFileChangeArgs(toolName, toolInput) {
|
|
20
|
+
if (toolName !== "Edit" && toolName !== "Write" && toolName !== "Delete") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const topLevelKeys = Object.keys(toolInput);
|
|
24
|
+
if (topLevelKeys.length !== 1 || topLevelKeys[0] !== "changes") {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const changes = toolInput.changes;
|
|
28
|
+
if (!Array.isArray(changes) || changes.length === 0) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return changes.every((change) => {
|
|
32
|
+
if (!change || typeof change !== "object" || Array.isArray(change)) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
const entry = change;
|
|
36
|
+
const keys = Object.keys(entry).sort();
|
|
37
|
+
return keys.length === 2 && keys[0] === "kind" && keys[1] === "path" && typeof entry.path === "string" && (entry.kind === "add" || entry.kind === "update" || entry.kind === "delete");
|
|
38
|
+
});
|
|
39
|
+
}
|
|
18
40
|
async function loadHistory(sessionKey) {
|
|
19
41
|
try {
|
|
20
42
|
const file = Bun.file(`${HISTORY_DIR}/${sessionKey}.json`);
|
|
@@ -39,13 +61,14 @@ async function checkToolLoop(sessionKey, toolName, toolInput) {
|
|
|
39
61
|
return { blocked: false };
|
|
40
62
|
}
|
|
41
63
|
const key = `${toolName}:${argsHash}`;
|
|
64
|
+
const repeatCriticalThreshold = isCodexFileChangeArgs(toolName, toolInput) ? LOW_CARDINALITY_FILE_CHANGE_CRITICAL_THRESHOLD : REPEAT_CRITICAL_THRESHOLD;
|
|
42
65
|
let repeatCount = 0;
|
|
43
66
|
for (const record of history) {
|
|
44
67
|
if (`${record.toolName}:${record.argsHash}` === key) {
|
|
45
68
|
repeatCount++;
|
|
46
69
|
}
|
|
47
70
|
}
|
|
48
|
-
if (repeatCount >=
|
|
71
|
+
if (repeatCount >= repeatCriticalThreshold) {
|
|
49
72
|
return {
|
|
50
73
|
blocked: true,
|
|
51
74
|
severity: "critical",
|
|
@@ -7,7 +7,7 @@ var package_default;
|
|
|
7
7
|
var init_package = __esm(() => {
|
|
8
8
|
package_default = {
|
|
9
9
|
name: "@desplega.ai/agent-swarm",
|
|
10
|
-
version: "1.
|
|
10
|
+
version: "1.103.0",
|
|
11
11
|
description: "Multi-agent orchestration for Claude Code, Codex, Gemini CLI, and other AI coding assistants",
|
|
12
12
|
license: "MIT",
|
|
13
13
|
author: "desplega.sh <contact@desplega.sh>",
|