@desplega.ai/agent-swarm 1.101.1 → 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.
Files changed (124) hide show
  1. package/dist/{actions-3bnwa1ep.js → actions-7txktrdj.js} +6 -6
  2. package/dist/{app-5efpcda0.js → app-xm3xsdye.js} +3 -3
  3. package/dist/{assistant-rgfbyp46.js → assistant-qpv63wk6.js} +9 -9
  4. package/dist/{boot-reembed-j3gp6x92.js → boot-reembed-9cxqka3e.js} +3 -3
  5. package/dist/{boot-reembed-8428r5df.js → boot-reembed-chxhrwv8.js} +4 -4
  6. package/dist/{boot-scrub-logs-ax5e0nrw.js → boot-scrub-logs-8qtfkcz8.js} +2 -2
  7. package/dist/{claude-managed-adapter-g07dbz3b.js → claude-managed-adapter-z29hjgzz.js} +3 -3
  8. package/dist/{cli-qsy1aedt.js → cli-2307phk1.js} +435 -35
  9. package/dist/{cli-g5px3d7x.js → cli-2957pqpj.js} +24 -1
  10. package/dist/{cli-b2k39ff6.js → cli-2qynerth.js} +1 -1
  11. package/dist/{cli-42f5hj29.js → cli-4fnp2tc3.js} +1 -1
  12. package/dist/{cli-7fzbt4p5.js → cli-85pf4z38.js} +1 -1
  13. package/dist/{cli-gwp428sg.js → cli-8hyv6c2v.js} +6 -14
  14. package/dist/{cli-qr8ky518.js → cli-8w95v19d.js} +1 -1
  15. package/dist/{cli-7xdq3jg3.js → cli-92fqyjcv.js} +1 -1
  16. package/dist/{cli-dg9tkgx0.js → cli-dz3d6zjg.js} +1 -1
  17. package/dist/{cli-53w8f9q9.js → cli-fedn86nz.js} +238 -484
  18. package/dist/{cli-zwc67pz4.js → cli-fwxdt7kt.js} +3 -3
  19. package/dist/{cli-53jkzjwm.js → cli-fygaw191.js} +2 -2
  20. package/dist/{cli-rdhzpm5x.js → cli-gzepjz54.js} +10 -9
  21. package/dist/{cli-n2xem10h.js → cli-jt9d9fjw.js} +1 -1
  22. package/dist/{cli-axtg1zaa.js → cli-khe4x17a.js} +1 -1
  23. package/dist/{cli-3a5wne6a.js → cli-kk51f3tf.js} +5 -5
  24. package/dist/{cli-12mrw9t3.js → cli-krvxq8bc.js} +1 -1
  25. package/dist/{cli-ft42ja8t.js → cli-ksq38x4n.js} +2 -2
  26. package/dist/{cli-z5gm760z.js → cli-m8f6qzck.js} +1 -1
  27. package/dist/{cli-p3mgqhjg.js → cli-ns0r7mkr.js} +30 -5
  28. package/dist/{cli-0v0nmmx1.js → cli-rttgde5f.js} +18 -6
  29. package/dist/{cli-8ayape3v.js → cli-rvae030h.js} +3 -3
  30. package/dist/{cli-6w7kg2y6.js → cli-s14sb64w.js} +4 -4
  31. package/dist/{cli-yg15ef2d.js → cli-v9283nma.js} +1 -1
  32. package/dist/{cli-kdhqhhrt.js → cli-xmtsan9k.js} +1 -1
  33. package/dist/{cli-5mt46cfa.js → cli-yeemwevj.js} +155 -37
  34. package/dist/{cli-54wmx6d9.js → cli-yfwwjeft.js} +1 -1
  35. package/dist/{cli-s8jw5bmg.js → cli-yp2krx5r.js} +2 -2
  36. package/dist/cli.js +9 -9
  37. package/dist/{codex-adapter-wf119mnw.js → codex-adapter-w0xharsg.js} +3 -3
  38. package/dist/{codex-session-runner-1gknw7mh.js → codex-session-runner-kzbjcm2k.js} +3 -3
  39. package/dist/{commands-ne6wm294.js → commands-aqn63mcw.js} +2 -2
  40. package/dist/{db-4bssa9fd.js → db-azrvwsnj.js} +2 -2
  41. package/dist/{handlers-b1xzrzd8.js → handlers-hf61har3.js} +9 -9
  42. package/dist/{hook-ghkvmqhb.js → hook-306p3yz4.js} +2 -2
  43. package/dist/{http-3d87gpq5.js → http-zts4haq7.js} +106 -69
  44. package/dist/{index-zc2ryfs3.js → index-29vg51x6.js} +163 -26
  45. package/dist/{index-vfxc8p1h.js → index-3c651yfk.js} +10 -10
  46. package/dist/{index-g2dtq2m4.js → index-bfh9hgek.js} +5 -5
  47. package/dist/{index-7eqxb7sq.js → index-h2yqjyk0.js} +8 -8
  48. package/dist/{keepalive-mdrtpw97.js → keepalive-a0dg5pds.js} +4 -4
  49. package/dist/{lead-k05m28c2.js → lead-7mcxedkc.js} +21 -21
  50. package/dist/{maintenance-3qnntmp1.js → maintenance-mrzqd53t.js} +4 -4
  51. package/dist/{onboard-kch4svdx.js → onboard-4dkpv9wa.js} +2 -2
  52. package/dist/{otel-impl-7c00xnhe.js → otel-impl-jt7gpyp9.js} +1 -1
  53. package/dist/{pi-mono-adapter-hf8sw7hs.js → pi-mono-adapter-zf7dt1wg.js} +1 -1
  54. package/dist/{pricing-refresh-6038eg1z.js → pricing-refresh-xqnzh8dt.js} +4 -4
  55. package/dist/{seed-pricing-75b6h84n.js → seed-pricing-56tjm1fj.js} +3 -3
  56. package/dist/{setup-jrqcgbdc.js → setup-tbwk8j10.js} +2 -2
  57. package/dist/{worker-0p9zfby6.js → worker-e03za92t.js} +21 -21
  58. package/openapi.json +70 -1
  59. package/package.json +1 -1
  60. package/src/be/audit-user.ts +49 -0
  61. package/src/be/db.ts +114 -17
  62. package/src/be/migrations/098_repo_hooks_config.sql +3 -0
  63. package/src/be/scripts/db.ts +25 -5
  64. package/src/be/seed-skills/index.ts +7 -0
  65. package/src/be/task-lifecycle-events.ts +42 -0
  66. package/src/commands/runner.ts +174 -25
  67. package/src/github/task-reactions.ts +21 -0
  68. package/src/hooks/tool-loop-detection.test.ts +40 -0
  69. package/src/hooks/tool-loop-detection.ts +37 -1
  70. package/src/http/agents.ts +7 -0
  71. package/src/http/index.ts +16 -2
  72. package/src/http/prompt-templates.ts +1 -1
  73. package/src/http/repos.ts +5 -1
  74. package/src/http/schedules.ts +6 -2
  75. package/src/http/scripts.ts +4 -0
  76. package/src/http/session-data.ts +2 -0
  77. package/src/http/tasks.ts +2 -1
  78. package/src/http/workflows.ts +14 -1
  79. package/src/prompts/resolver.ts +1 -1
  80. package/src/scheduler/scheduler.ts +25 -2
  81. package/src/server-runtime-counters.ts +12 -0
  82. package/src/server-user.ts +1 -2
  83. package/src/server.ts +5 -0
  84. package/src/telemetry.ts +18 -1
  85. package/src/tests/audit-updated-by.test.ts +636 -0
  86. package/src/tests/audit-user.test.ts +156 -0
  87. package/src/tests/http-api-integration.test.ts +4 -0
  88. package/src/tests/model-control.test.ts +6 -6
  89. package/src/tests/swarm-repos.test.ts +25 -2
  90. package/src/tests/system-default-skills.test.ts +14 -1
  91. package/src/tests/task-lifecycle-events.test.ts +53 -0
  92. package/src/tests/task-lifecycle-telemetry.test.ts +37 -1
  93. package/src/tests/telemetry-init.test.ts +32 -0
  94. package/src/tools/prompt-templates/preview.ts +1 -1
  95. package/src/tools/repos/update-repo.ts +6 -1
  96. package/src/tools/schedules/create-schedule.ts +6 -1
  97. package/src/tools/schedules/update-schedule.ts +5 -2
  98. package/src/tools/script-common.ts +9 -5
  99. package/src/tools/send-task.ts +7 -2
  100. package/src/tools/task-action.ts +6 -2
  101. package/src/tools/workflows/create-workflow.ts +5 -0
  102. package/src/tools/workflows/patch-workflow-node.ts +10 -1
  103. package/src/tools/workflows/patch-workflow.ts +6 -0
  104. package/src/tools/workflows/update-workflow.ts +4 -0
  105. package/src/types.ts +159 -1
  106. package/src/utils/template.ts +127 -0
  107. package/src/workflows/engine.ts +7 -0
  108. package/src/workflows/executors/agent-task.ts +1 -2
  109. package/src/workflows/template.ts +12 -121
  110. package/src/workflows/triggers.ts +6 -2
  111. package/templates/community/code-health-reports/PLAYBOOK.md +355 -0
  112. package/templates/community/code-health-reports/README.md +38 -0
  113. package/templates/community/code-health-reports/lead-prompt.md +52 -0
  114. package/templates/community/code-health-reports/report.mjs +378 -0
  115. package/templates/community/code-health-reports/run.sh +143 -0
  116. package/templates/schedules/weekly-code-health-reports/config.json +13 -0
  117. package/templates/schedules/weekly-code-health-reports/content.md +60 -0
  118. package/templates/skills/TASTE-SKILL-LICENSE +21 -0
  119. package/templates/skills/pages/config.json +4 -3
  120. package/templates/skills/pages/content.md +39 -12
  121. package/templates/skills/taste-minimalist-skill/config.json +19 -0
  122. package/templates/skills/taste-minimalist-skill/content.md +83 -0
  123. package/src/model-tiers.ts +0 -140
  124. package/templates/community/.gitkeep +0 -0
@@ -13,13 +13,13 @@ import {
13
13
  ensureTokenOrThrow,
14
14
  getOAuthApp,
15
15
  getOAuthTokens
16
- } from "./cli-yg15ef2d.js";
16
+ } from "./cli-v9283nma.js";
17
17
  import {
18
18
  startPricingRefreshLoop
19
- } from "./cli-ft42ja8t.js";
19
+ } from "./cli-ksq38x4n.js";
20
20
  import {
21
21
  seedPricingFromModelsDev
22
- } from "./cli-z5gm760z.js";
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-42f5hj29.js";
30
+ } from "./cli-4fnp2tc3.js";
31
31
  import {
32
32
  cancelWorkflowRun,
33
33
  getExecutorRegistry,
34
34
  retryFailedRun,
35
35
  snapshotWorkflow
36
- } from "./cli-gwp428sg.js";
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-qr8ky518.js";
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-p3mgqhjg.js";
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-0v0nmmx1.js";
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-3a5wne6a.js";
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-54wmx6d9.js";
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-n2xem10h.js";
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,
@@ -213,6 +214,7 @@ import {
213
214
  getPromptTemplateById,
214
215
  getPromptTemplateHistory,
215
216
  getPromptTemplates,
217
+ getRequestAuth,
216
218
  getResolvedConfig,
217
219
  getScheduledTaskById,
218
220
  getScheduledTaskByName,
@@ -242,10 +244,11 @@ import {
242
244
  initDb,
243
245
  init_db,
244
246
  init_defaults,
245
- init_model_tiers,
246
247
  init_registry,
248
+ init_request_auth_context,
247
249
  init_resolver,
248
250
  init_swarm_config_guard,
251
+ init_task_lifecycle_events,
249
252
  init_template,
250
253
  init_types,
251
254
  insertTaskAttachment,
@@ -264,6 +267,7 @@ import {
264
267
  maskSecrets,
265
268
  moveTaskFromBacklog,
266
269
  moveTaskToBacklog,
270
+ onTaskStarted,
267
271
  postMessage,
268
272
  reassociateSessionLogs,
269
273
  recordBudgetRefusalNotification,
@@ -300,7 +304,7 @@ import {
300
304
  upsertService,
301
305
  upsertSwarmConfig,
302
306
  validateConfigValue
303
- } from "./cli-53w8f9q9.js";
307
+ } from "./cli-fedn86nz.js";
304
308
  import {
305
309
  init_zod
306
310
  } from "./cli-q21d49ac.js";
@@ -344,7 +348,7 @@ import {
344
348
  import {
345
349
  init_package,
346
350
  package_default
347
- } from "./cli-7fzbt4p5.js";
351
+ } from "./cli-85pf4z38.js";
348
352
  import {
349
353
  init_secret_scrubber,
350
354
  registerVolatileSecret,
@@ -11206,6 +11210,356 @@ var EMPTY_COMPLETION_RESULT = {
11206
11210
  init_package();
11207
11211
  init_db();
11208
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
+
11209
11563
  // src/tools/cancel-task.ts
11210
11564
  init_zod();
11211
11565
  init_db();
@@ -11253,7 +11607,7 @@ var NOOP_SPAN = {
11253
11607
  setStatus: () => NOOP_SPAN,
11254
11608
  end: () => {}
11255
11609
  };
11256
- var initialized = false;
11610
+ var initialized2 = false;
11257
11611
  var realWithSpan;
11258
11612
  var realStartSpan;
11259
11613
  var realWithRemoteContext;
@@ -11265,11 +11619,11 @@ function isPollTracingEnabled() {
11265
11619
  return v === "1" || v === "true" || v === "yes" || v === "on";
11266
11620
  }
11267
11621
  async function initOtel(serviceRole = process.env.AGENT_ROLE || "api") {
11268
- if (!enabled || initialized)
11622
+ if (!enabled || initialized2)
11269
11623
  return;
11270
- initialized = true;
11624
+ initialized2 = true;
11271
11625
  try {
11272
- const impl = await import("./otel-impl-7c00xnhe.js");
11626
+ const impl = await import("./otel-impl-jt7gpyp9.js");
11273
11627
  await impl.boot(serviceRole);
11274
11628
  realWithSpan = impl.withSpan;
11275
11629
  realStartSpan = impl.startSpan;
@@ -16563,6 +16917,7 @@ var registerUpdateRepoTool = (server) => {
16563
16917
  clonePath: string().optional().describe("New clone path."),
16564
16918
  defaultBranch: string().optional().describe("New default branch."),
16565
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."),
16566
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.")
16567
16922
  }),
16568
16923
  outputSchema: object({
@@ -16725,9 +17080,33 @@ var registerResolveUserTool = (server) => {
16725
17080
 
16726
17081
  // src/tools/schedules/create-schedule.ts
16727
17082
  init_zod();
16728
- init_db();
16729
17083
  var import_cron_parser = __toESM(require_dist(), 1);
16730
- init_model_tiers();
17084
+
17085
+ // src/be/audit-user.ts
17086
+ init_request_auth_context();
17087
+ init_db();
17088
+ function resolveTaskAuditUserId(sourceTaskId, callerAgentId) {
17089
+ if (!sourceTaskId || !callerAgentId)
17090
+ return null;
17091
+ const task = getTaskById(sourceTaskId);
17092
+ if (!task)
17093
+ return null;
17094
+ if (task.agentId !== callerAgentId)
17095
+ return null;
17096
+ return task.requestedByUserId ?? null;
17097
+ }
17098
+ function resolveHttpAuditUserId(req, callerAgentId) {
17099
+ const auth = getRequestAuth(req);
17100
+ if (auth?.kind === "user")
17101
+ return auth.userId;
17102
+ const header = req.headers["x-source-task-id"];
17103
+ const sourceTaskId = Array.isArray(header) ? header[0] : header;
17104
+ return resolveTaskAuditUserId(sourceTaskId, callerAgentId);
17105
+ }
17106
+
17107
+ // src/tools/schedules/create-schedule.ts
17108
+ init_db();
17109
+ init_types();
16731
17110
  var createScheduleInputSchema = object({
16732
17111
  name: string().min(1).max(100).describe("Unique name for the schedule (e.g., 'daily-cleanup')"),
16733
17112
  taskTemplate: string().min(1).describe("The task description that will be created each time"),
@@ -16937,6 +17316,7 @@ var registerCreateScheduleTool = (server) => {
16937
17316
  };
16938
17317
  nextRunAt = calculateNextRun(tempSchedule, new Date);
16939
17318
  }
17319
+ const createdBy = resolveTaskAuditUserId(requestInfo.sourceTaskId, requestInfo.agentId) ?? undefined;
16940
17320
  const schedule = createScheduledTask({
16941
17321
  name,
16942
17322
  taskTemplate,
@@ -16953,7 +17333,8 @@ var registerCreateScheduleTool = (server) => {
16953
17333
  createdByAgentId: requestInfo.agentId,
16954
17334
  model: normalizedModel.model,
16955
17335
  modelTier: normalizedModel.modelTier,
16956
- scheduleType: scheduleType ?? "recurring"
17336
+ scheduleType: scheduleType ?? "recurring",
17337
+ createdBy
16957
17338
  });
16958
17339
  const scheduleDesc = isOneTime ? `one-time at ${schedule.nextRunAt}` : cronExpression || `every ${intervalMs}ms`;
16959
17340
  return {
@@ -17281,8 +17662,8 @@ var registerRunScheduleNowTool = (server) => {
17281
17662
  };
17282
17663
  // src/tools/schedules/update-schedule.ts
17283
17664
  init_zod();
17284
- init_db();
17285
17665
  var import_cron_parser2 = __toESM(require_dist(), 1);
17666
+ init_db();
17286
17667
 
17287
17668
  // src/be/schedules/validate.ts
17288
17669
  function mergeScheduleTiming(existing, patch) {
@@ -17299,7 +17680,7 @@ function validateRecurringTiming(merged) {
17299
17680
  }
17300
17681
 
17301
17682
  // src/tools/schedules/update-schedule.ts
17302
- init_model_tiers();
17683
+ init_types();
17303
17684
  var updateScheduleInputSchema = object({
17304
17685
  scheduleId: string().uuid().optional().describe("Schedule ID to update"),
17305
17686
  name: string().optional().describe("Schedule name to update (alternative to ID)"),
@@ -17520,7 +17901,8 @@ var registerUpdateScheduleTool = (server) => {
17520
17901
  updateData.nextRunAt = undefined;
17521
17902
  }
17522
17903
  }
17523
- const updated = updateScheduledTask(schedule.id, updateData);
17904
+ const updatedBy = resolveTaskAuditUserId(requestInfo.sourceTaskId, requestInfo.agentId) ?? undefined;
17905
+ const updated = updateScheduledTask(schedule.id, { ...updateData, updatedBy });
17524
17906
  if (!updated) {
17525
17907
  return {
17526
17908
  content: [{ type: "text", text: "Failed to update schedule." }],
@@ -17590,13 +17972,17 @@ async function proxyScriptsApi(args) {
17590
17972
  if (!args.requestInfo.agentId)
17591
17973
  return toolError(SCRIPT_TRANSPORT_ERROR);
17592
17974
  const apiKey = getApiKey();
17975
+ const headers = {
17976
+ Authorization: `Bearer ${apiKey}`,
17977
+ "X-Agent-ID": args.requestInfo.agentId,
17978
+ "Content-Type": "application/json"
17979
+ };
17980
+ if (args.requestInfo.sourceTaskId) {
17981
+ headers["X-Source-Task-Id"] = args.requestInfo.sourceTaskId;
17982
+ }
17593
17983
  const res = await fetch(`${apiBaseUrl()}${args.path}`, {
17594
17984
  method: args.method,
17595
- headers: {
17596
- Authorization: `Bearer ${apiKey}`,
17597
- "X-Agent-ID": args.requestInfo.agentId,
17598
- "Content-Type": "application/json"
17599
- },
17985
+ headers,
17600
17986
  body: args.body === undefined ? undefined : JSON.stringify(args.body)
17601
17987
  });
17602
17988
  const text = await res.text();
@@ -17875,7 +18261,6 @@ function findDuplicateTask(opts) {
17875
18261
 
17876
18262
  // src/tools/send-task.ts
17877
18263
  init_types();
17878
- init_model_tiers();
17879
18264
  var sendTaskInputSchema = object({
17880
18265
  agentId: uuid().optional().describe("The agent to assign/offer task to. Omit to create unassigned task for pool."),
17881
18266
  task: string().min(1).describe("The task description to send."),
@@ -21640,7 +22025,6 @@ function emitBudgetRefusalSideEffects(ctx, inserted) {
21640
22025
  // src/tools/task-action.ts
21641
22026
  init_db();
21642
22027
  init_types();
21643
- init_model_tiers();
21644
22028
  var TaskActionSchema = _enum([
21645
22029
  "create",
21646
22030
  "claim",
@@ -22859,6 +23243,7 @@ var registerCreateWorkflowTool = (server) => {
22859
23243
  }
22860
23244
  };
22861
23245
  }
23246
+ const createdBy = resolveTaskAuditUserId(requestInfo.sourceTaskId, requestInfo.agentId) ?? undefined;
22862
23247
  const workflow = createWorkflow({
22863
23248
  name,
22864
23249
  description,
@@ -22869,7 +23254,8 @@ var registerCreateWorkflowTool = (server) => {
22869
23254
  dir,
22870
23255
  vcsRepo,
22871
23256
  triggerSchema,
22872
- createdByAgentId: requestInfo.agentId
23257
+ createdByAgentId: requestInfo.agentId,
23258
+ createdBy
22873
23259
  });
22874
23260
  return {
22875
23261
  content: [
@@ -23170,12 +23556,16 @@ var registerPatchWorkflowTool = (server) => {
23170
23556
  };
23171
23557
  }
23172
23558
  const version = snapshotWorkflow(id, requestInfo.agentId);
23559
+ const updatedBy = resolveTaskAuditUserId(requestInfo.sourceTaskId, requestInfo.agentId) ?? undefined;
23173
23560
  const updateArgs = {
23174
23561
  definition: patchResult.definition
23175
23562
  };
23176
23563
  if (triggerSchema !== undefined) {
23177
23564
  updateArgs.triggerSchema = triggerSchema;
23178
23565
  }
23566
+ if (updatedBy !== undefined) {
23567
+ updateArgs.updatedBy = updatedBy;
23568
+ }
23179
23569
  const workflow = updateWorkflow(id, updateArgs);
23180
23570
  if (!workflow) {
23181
23571
  return {
@@ -23256,7 +23646,14 @@ var registerPatchWorkflowNodeTool = (server) => {
23256
23646
  };
23257
23647
  }
23258
23648
  const version = snapshotWorkflow(id, requestInfo.agentId);
23259
- const workflow = updateWorkflow(id, { definition: patchResult.definition });
23649
+ const updatedBy = resolveTaskAuditUserId(requestInfo.sourceTaskId, requestInfo.agentId) ?? undefined;
23650
+ const updateArgs = {
23651
+ definition: patchResult.definition
23652
+ };
23653
+ if (updatedBy !== undefined) {
23654
+ updateArgs.updatedBy = updatedBy;
23655
+ }
23656
+ const workflow = updateWorkflow(id, updateArgs);
23260
23657
  if (!workflow) {
23261
23658
  return {
23262
23659
  content: [{ type: "text", text: `Workflow not found: ${id}` }],
@@ -23485,6 +23882,7 @@ var registerUpdateWorkflowTool = (server) => {
23485
23882
  }
23486
23883
  }
23487
23884
  const version = snapshotWorkflow(id, requestInfo.agentId);
23885
+ const updatedBy = resolveTaskAuditUserId(requestInfo.sourceTaskId, requestInfo.agentId) ?? undefined;
23488
23886
  const workflow = updateWorkflow(id, {
23489
23887
  name,
23490
23888
  description,
@@ -23495,7 +23893,8 @@ var registerUpdateWorkflowTool = (server) => {
23495
23893
  dir: dir === null ? null : dir,
23496
23894
  vcsRepo: vcsRepo === null ? null : vcsRepo,
23497
23895
  enabled: enabled2,
23498
- triggerSchema: triggerSchema === null ? null : triggerSchema
23896
+ triggerSchema: triggerSchema === null ? null : triggerSchema,
23897
+ updatedBy
23499
23898
  });
23500
23899
  if (!workflow) {
23501
23900
  return {
@@ -23538,6 +23937,7 @@ function createServer() {
23538
23937
  initDb(process.env.DATABASE_PATH);
23539
23938
  seedPricingFromModelsDev();
23540
23939
  startPricingRefreshLoop();
23940
+ registerGithubTaskReactions();
23541
23941
  const server = new McpServer({
23542
23942
  name: package_default.name,
23543
23943
  version: package_default.version,
@@ -23820,4 +24220,4 @@ function writeSkillsToFilesystem(entries, harnessType = "all", home) {
23820
24220
  return { synced, removed, errors };
23821
24221
  }
23822
24222
 
23823
- 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, 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 };