@desplega.ai/agent-swarm 1.112.0 → 1.113.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-eckb4g8r.js → actions-q4n7cz6e.js} +6 -6
- package/dist/{app-b05sgm02.js → app-es4nzc71.js} +3 -3
- package/dist/{assistant-7255sbyw.js → assistant-0x8ey0vs.js} +9 -9
- package/dist/{boot-reembed-y1bt3ttn.js → boot-reembed-69agkhv6.js} +4 -4
- package/dist/{boot-reembed-yv7awg4y.js → boot-reembed-p0ny05t8.js} +3 -3
- package/dist/{boot-scrub-logs-ddyaeqar.js → boot-scrub-logs-yybrkmvr.js} +2 -2
- package/dist/{cli-s9pj3c7z.js → cli-30bbaveh.js} +2 -2
- package/dist/{cli-r1btc895.js → cli-36ymmpmp.js} +2 -2
- package/dist/{cli-15598a4k.js → cli-4xyj9jtq.js} +1215 -235
- package/dist/{cli-52tbq17n.js → cli-bgef578c.js} +1 -1
- package/dist/{cli-76d1vtvq.js → cli-bgvskydy.js} +1 -1
- package/dist/{cli-pt7c7qxz.js → cli-bnzbn8j8.js} +3 -3
- package/dist/{cli-8f0dwca2.js → cli-c3frqf65.js} +4 -3
- package/dist/{cli-9p0qhead.js → cli-c9mtm09b.js} +1 -1
- package/dist/{cli-709t753c.js → cli-f3qa069v.js} +2 -2
- package/dist/{cli-94vzr3nq.js → cli-gtkqc144.js} +4 -4
- package/dist/{cli-7xkwgkrs.js → cli-h3k622d0.js} +1 -1
- package/dist/{cli-h9jx5mag.js → cli-hjhvekf4.js} +4 -4
- package/dist/{cli-tp7e60s3.js → cli-hsetkkd3.js} +2 -2
- package/dist/{cli-tch0ypp6.js → cli-mq580e06.js} +4 -4
- package/dist/{cli-951w7c79.js → cli-ncfgsqbd.js} +63 -7
- package/dist/{cli-30d2ct3k.js → cli-pwc5e83c.js} +3 -3
- package/dist/{cli-3r5y6ayj.js → cli-qwgtacd6.js} +2 -2
- package/dist/{cli-56s4ehzw.js → cli-r5g6ngtn.js} +1 -1
- package/dist/{cli-rp8pca98.js → cli-tbw13sx8.js} +1 -1
- package/dist/{cli-hm27prrc.js → cli-trmapn9k.js} +5 -5
- package/dist/{cli-0c3n0eba.js → cli-y4ycrnjc.js} +1 -1
- package/dist/{cli-a5e8n5hg.js → cli-y6mrptcn.js} +1 -1
- package/dist/{cli-tg0f2wmz.js → cli-z46pnksz.js} +5 -5
- package/dist/cli.js +11 -10
- package/dist/{commands-14g7taf4.js → commands-z5dbwta3.js} +2 -2
- package/dist/{db-3tge4jrn.js → db-bbgahh4z.js} +2 -2
- package/dist/{handlers-sy64egg6.js → handlers-6b44317z.js} +9 -9
- package/dist/{hook-rnkzw8vp.js → hook-sbp5fmps.js} +1 -1
- package/dist/{http-xx9xptcs.js → http-2xz43gz3.js} +354 -94
- package/dist/{index-zfx5p959.js → index-0gzmqj4k.js} +8 -8
- package/dist/{index-3wr6v2mm.js → index-5ghxn8s6.js} +7 -7
- package/dist/{index-brma88d4.js → index-nhat35em.js} +9 -9
- package/dist/{index-ha8e9xn2.js → index-vfedgdw6.js} +26 -15
- package/dist/{keepalive-rbz05zad.js → keepalive-62gfj91d.js} +4 -4
- package/dist/{lead-s790v7r0.js → lead-ag0akn0v.js} +17 -17
- package/dist/{maintenance-420rmadb.js → maintenance-xxrrzk5x.js} +4 -4
- package/dist/{onboard-jgqamqnw.js → onboard-64zyfcbs.js} +2 -2
- package/dist/{otel-impl-ch3n3783.js → otel-impl-b86qseaa.js} +1 -1
- package/dist/{pricing-refresh-rmtrby6h.js → pricing-refresh-cgtkffpa.js} +4 -4
- package/dist/{seed-pricing-1szjzfj1.js → seed-pricing-1r1y1xkq.js} +3 -3
- package/dist/{setup-8jfzkyzv.js → setup-mkcgkjf7.js} +2 -2
- package/dist/{worker-40vq0pm8.js → worker-351sze63.js} +17 -17
- package/openapi.json +314 -3
- package/package.json +4 -3
- package/src/be/db.ts +43 -3
- package/src/be/memory/providers/sqlite-store.ts +5 -1
- package/src/be/migrations/108_rbac_permission_audit.sql +26 -0
- package/src/be/rbac-audit.ts +218 -0
- package/src/http/all-routes.ts +58 -0
- package/src/http/config.ts +55 -0
- package/src/http/favorites.ts +5 -0
- package/src/http/fs.ts +27 -7
- package/src/http/index.ts +26 -0
- package/src/http/kv.ts +21 -4
- package/src/http/route-def.ts +9 -0
- package/src/http/schedules.ts +56 -22
- package/src/http/scripts.ts +33 -0
- package/src/http/workflows.ts +13 -2
- package/src/prompts/base-prompt.ts +7 -6
- package/src/prompts/session-templates.ts +38 -11
- package/src/rbac/can.ts +44 -0
- package/src/rbac/index.ts +13 -0
- package/src/rbac/legacy-policy.ts +185 -0
- package/src/rbac/permissions.ts +182 -0
- package/src/rbac/types.ts +45 -0
- package/src/scripts-runtime/sdk-allowlist.ts +1 -0
- package/src/scripts-runtime/swarm-sdk.ts +81 -0
- package/src/scripts-runtime/types/stdlib.d.ts +18 -2
- package/src/scripts-runtime/types/swarm-sdk.d.ts +18 -2
- package/src/server.ts +2 -0
- package/src/stdio.ts +43 -0
- package/src/tests/base-prompt.test.ts +7 -4
- package/src/tests/harness-provider-resolution.test.ts +5 -0
- package/src/tests/http-api-integration.test.ts +8 -1
- package/src/tests/prompt-template-session.test.ts +21 -8
- package/src/tests/rbac-audit.test.ts +345 -0
- package/src/tests/rbac-charact-http.test.ts +272 -0
- package/src/tests/rbac-charact-misc-tools.test.ts +428 -0
- package/src/tests/rbac-charact-skills.test.ts +492 -0
- package/src/tests/rbac-charact-slack.test.ts +283 -0
- package/src/tests/rbac-e2e-helpers.ts +305 -0
- package/src/tests/rbac-engine.test.ts +433 -0
- package/src/tests/rbac-lifecycle-e2e.test.ts +262 -0
- package/src/tests/rbac-wire-e2e.test.ts +574 -0
- package/src/tests/schedule-http-triage-tools.test.ts +121 -0
- package/src/tests/scheduled-tasks.test.ts +34 -0
- package/src/tests/scripts-http.test.ts +56 -7
- package/src/tests/swarm-config-reserved-keys.test.ts +17 -0
- package/src/tests/tool-annotations.test.ts +1 -0
- package/src/tests/update-schedule-mcp-tool.test.ts +57 -0
- package/src/tests/workflow-http-v2.test.ts +80 -0
- package/src/tools/cancel-task.ts +13 -3
- package/src/tools/context-diff.ts +12 -1
- package/src/tools/context-history.ts +12 -1
- package/src/tools/credential-bindings/tool.ts +12 -1
- package/src/tools/delete-channel.ts +12 -1
- package/src/tools/get-task-details.ts +1 -1
- package/src/tools/inject-learning.ts +12 -1
- package/src/tools/kv/kv-delete.ts +3 -18
- package/src/tools/kv/kv-incr.ts +3 -18
- package/src/tools/kv/kv-set.ts +3 -20
- package/src/tools/kv/kv-write-auth.ts +40 -0
- package/src/tools/manage-user.ts +12 -1
- package/src/tools/mcp-servers/mcp-server-create.ts +12 -1
- package/src/tools/mcp-servers/mcp-server-delete.ts +12 -1
- package/src/tools/mcp-servers/mcp-server-install.ts +12 -1
- package/src/tools/mcp-servers/mcp-server-uninstall.ts +12 -1
- package/src/tools/mcp-servers/mcp-server-update.ts +12 -1
- package/src/tools/memory-delete.ts +12 -4
- package/src/tools/register-kapso-number.ts +23 -2
- package/src/tools/schedules/create-schedule.ts +4 -3
- package/src/tools/schedules/index.ts +1 -0
- package/src/tools/schedules/list-schedules.ts +36 -2
- package/src/tools/schedules/patch-schedule.ts +405 -0
- package/src/tools/schedules/update-schedule.ts +2 -2
- package/src/tools/script-connections/tool.ts +12 -1
- package/src/tools/skills/skill-create.ts +12 -1
- package/src/tools/skills/skill-delete.ts +12 -1
- package/src/tools/skills/skill-install-remote.ts +12 -1
- package/src/tools/skills/skill-install.ts +12 -1
- package/src/tools/skills/skill-uninstall.ts +12 -1
- package/src/tools/skills/skill-update.ts +25 -2
- package/src/tools/slack-delete.ts +8 -1
- package/src/tools/slack-post.ts +8 -1
- package/src/tools/slack-read.ts +8 -1
- package/src/tools/slack-start-thread.ts +8 -1
- package/src/tools/slack-update.ts +8 -1
- package/src/tools/slack-upload-file.ts +8 -1
- package/src/tools/swarm-config/delete-config.ts +28 -1
- package/src/tools/swarm-config/get-config.ts +32 -5
- package/src/tools/swarm-config/list-config.ts +31 -5
- package/src/tools/swarm-config/set-config.ts +38 -1
- package/src/tools/task-action.ts +1 -1
- package/src/tools/task-tool-ctx.ts +19 -3
- package/src/tools/tool-config.ts +2 -1
- package/src/tools/update-profile.ts +8 -1
- package/src/tools/workflows/list-workflows.ts +14 -2
- package/templates/skills/swarm-scripts/SKILL.md +4 -9
- package/templates/skills/swarm-scripts/content.md +20 -9
|
@@ -14,13 +14,13 @@ import {
|
|
|
14
14
|
getOAuthApp,
|
|
15
15
|
getOAuthTokens,
|
|
16
16
|
upsertOAuthApp
|
|
17
|
-
} from "./cli-
|
|
17
|
+
} from "./cli-bgef578c.js";
|
|
18
18
|
import {
|
|
19
19
|
startPricingRefreshLoop
|
|
20
|
-
} from "./cli-
|
|
20
|
+
} from "./cli-36ymmpmp.js";
|
|
21
21
|
import {
|
|
22
22
|
seedPricingFromModelsDev
|
|
23
|
-
} from "./cli-
|
|
23
|
+
} from "./cli-tbw13sx8.js";
|
|
24
24
|
import {
|
|
25
25
|
createTrackerAgentMapping,
|
|
26
26
|
createTrackerSync,
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
repointTrackerSyncBySwarmId,
|
|
36
36
|
updateTrackerSync,
|
|
37
37
|
updateTrackerSyncSwarmId
|
|
38
|
-
} from "./cli-
|
|
38
|
+
} from "./cli-r5g6ngtn.js";
|
|
39
39
|
import {
|
|
40
40
|
ZodFirstPartyTypeKind,
|
|
41
41
|
objectType
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
ensure,
|
|
46
46
|
require_dist,
|
|
47
47
|
runScheduleNow
|
|
48
|
-
} from "./cli-
|
|
48
|
+
} from "./cli-gtkqc144.js";
|
|
49
49
|
import {
|
|
50
50
|
TriggerSchemaError,
|
|
51
51
|
applyDefinitionPatch,
|
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
startWorkflowExecution,
|
|
58
58
|
validateDefinition,
|
|
59
59
|
validateJsonSchema
|
|
60
|
-
} from "./cli-
|
|
60
|
+
} from "./cli-z46pnksz.js";
|
|
61
61
|
import {
|
|
62
62
|
getApiKey
|
|
63
63
|
} from "./cli-f14fvzag.js";
|
|
@@ -73,7 +73,7 @@ import {
|
|
|
73
73
|
setScriptConnectionEnabled,
|
|
74
74
|
upsertCredentialBinding,
|
|
75
75
|
upsertScriptConnection
|
|
76
|
-
} from "./cli-
|
|
76
|
+
} from "./cli-qwgtacd6.js";
|
|
77
77
|
import {
|
|
78
78
|
CANDIDATE_SET_MULTIPLIER,
|
|
79
79
|
computeScore,
|
|
@@ -85,17 +85,17 @@ import {
|
|
|
85
85
|
isGraphExpansionEnabled,
|
|
86
86
|
rerank,
|
|
87
87
|
rowToCandidate
|
|
88
|
-
} from "./cli-
|
|
88
|
+
} from "./cli-f3qa069v.js";
|
|
89
89
|
import {
|
|
90
90
|
createAdditiveBuffer,
|
|
91
91
|
extractSlackMessageText,
|
|
92
92
|
parseSlackTs
|
|
93
|
-
} from "./cli-
|
|
93
|
+
} from "./cli-bgvskydy.js";
|
|
94
94
|
import {
|
|
95
95
|
getSlackApp,
|
|
96
96
|
startSlackApp,
|
|
97
97
|
stopSlackApp
|
|
98
|
-
} from "./cli-
|
|
98
|
+
} from "./cli-trmapn9k.js";
|
|
99
99
|
import {
|
|
100
100
|
findOrCreateUserByEmail,
|
|
101
101
|
findUserByEmail,
|
|
@@ -107,7 +107,7 @@ import {
|
|
|
107
107
|
recordIdentityEvent,
|
|
108
108
|
resolveUserByToken,
|
|
109
109
|
unlinkIdentity
|
|
110
|
-
} from "./cli-
|
|
110
|
+
} from "./cli-h3k622d0.js";
|
|
111
111
|
import {
|
|
112
112
|
markdownToSlack
|
|
113
113
|
} from "./cli-6xd0bvf8.js";
|
|
@@ -118,7 +118,7 @@ import {
|
|
|
118
118
|
createTaskWithSiblingAwareness,
|
|
119
119
|
githubContextKey,
|
|
120
120
|
linearContextKey
|
|
121
|
-
} from "./cli-
|
|
121
|
+
} from "./cli-y4ycrnjc.js";
|
|
122
122
|
import {
|
|
123
123
|
getAppUrl,
|
|
124
124
|
getMcpBaseUrl,
|
|
@@ -347,7 +347,7 @@ import {
|
|
|
347
347
|
upsertService,
|
|
348
348
|
upsertSwarmConfig,
|
|
349
349
|
validateConfigValue
|
|
350
|
-
} from "./cli-
|
|
350
|
+
} from "./cli-ncfgsqbd.js";
|
|
351
351
|
import {
|
|
352
352
|
init_zod
|
|
353
353
|
} from "./cli-q21d49ac.js";
|
|
@@ -391,7 +391,7 @@ import {
|
|
|
391
391
|
import {
|
|
392
392
|
init_package,
|
|
393
393
|
package_default
|
|
394
|
-
} from "./cli-
|
|
394
|
+
} from "./cli-c3frqf65.js";
|
|
395
395
|
import {
|
|
396
396
|
init_secret_scrubber,
|
|
397
397
|
refreshSecretScrubberCache,
|
|
@@ -19613,6 +19613,300 @@ function registerGithubTaskReactions() {
|
|
|
19613
19613
|
init_zod();
|
|
19614
19614
|
init_db();
|
|
19615
19615
|
|
|
19616
|
+
// src/rbac/legacy-policy.ts
|
|
19617
|
+
var leadOnly = {
|
|
19618
|
+
name: "lead-only",
|
|
19619
|
+
denyReason: "requires lead agent",
|
|
19620
|
+
evaluate: (principal) => principal.kind === "agent" && principal.isLead
|
|
19621
|
+
};
|
|
19622
|
+
var leadOrTaskCreator = {
|
|
19623
|
+
name: "lead-or-task-creator",
|
|
19624
|
+
denyReason: "requires lead agent or task creator",
|
|
19625
|
+
evaluate: (principal, resource) => {
|
|
19626
|
+
if (principal.kind !== "agent")
|
|
19627
|
+
return false;
|
|
19628
|
+
if (principal.isLead)
|
|
19629
|
+
return true;
|
|
19630
|
+
return resource?.kind === "task" && resource.creatorAgentId != null && resource.creatorAgentId === principal.agentId;
|
|
19631
|
+
}
|
|
19632
|
+
};
|
|
19633
|
+
var leadOrResourceOwner = {
|
|
19634
|
+
name: "lead-or-resource-owner",
|
|
19635
|
+
denyReason: "requires lead agent or resource owner",
|
|
19636
|
+
evaluate: (principal, resource) => {
|
|
19637
|
+
if (principal.kind !== "agent")
|
|
19638
|
+
return false;
|
|
19639
|
+
if (principal.isLead)
|
|
19640
|
+
return true;
|
|
19641
|
+
return resource?.kind === "owned" && resource.ownerAgentId != null && resource.ownerAgentId === principal.agentId;
|
|
19642
|
+
}
|
|
19643
|
+
};
|
|
19644
|
+
var leadOrOwnNamespace = {
|
|
19645
|
+
name: "lead-or-own-namespace",
|
|
19646
|
+
denyReason: "requires lead agent or your own task:agent: namespace",
|
|
19647
|
+
evaluate: (principal, resource) => {
|
|
19648
|
+
if (principal.kind !== "agent")
|
|
19649
|
+
return false;
|
|
19650
|
+
if (principal.isLead)
|
|
19651
|
+
return true;
|
|
19652
|
+
return principal.agentId !== "" && resource?.kind === "kv-namespace" && resource.namespace === `task:agent:${principal.agentId}`;
|
|
19653
|
+
}
|
|
19654
|
+
};
|
|
19655
|
+
var requesterOwnsTask = {
|
|
19656
|
+
name: "requester-owns-task",
|
|
19657
|
+
denyReason: "not the task requester",
|
|
19658
|
+
evaluate: (principal, resource) => {
|
|
19659
|
+
if (principal.kind !== "user")
|
|
19660
|
+
return true;
|
|
19661
|
+
return resource?.kind === "task" && resource.requestedByUserId === principal.userId;
|
|
19662
|
+
}
|
|
19663
|
+
};
|
|
19664
|
+
var memoryOwnerOrLeadSwarm = {
|
|
19665
|
+
name: "memory-owner-or-lead-swarm",
|
|
19666
|
+
denyReason: "requires memory owner, or lead agent for swarm-scoped memories",
|
|
19667
|
+
evaluate: (principal, resource) => {
|
|
19668
|
+
if (principal.kind !== "agent" || resource?.kind !== "owned")
|
|
19669
|
+
return false;
|
|
19670
|
+
if (resource.ownerAgentId != null && resource.ownerAgentId === principal.agentId)
|
|
19671
|
+
return true;
|
|
19672
|
+
return principal.isLead && resource.scope === "swarm";
|
|
19673
|
+
}
|
|
19674
|
+
};
|
|
19675
|
+
var taskFsMutate = {
|
|
19676
|
+
name: "operator-or-user-or-lead-or-task-owner",
|
|
19677
|
+
denyReason: "requires operator, user, lead agent, task assignee, or task creator",
|
|
19678
|
+
evaluate: (principal, resource) => {
|
|
19679
|
+
if (principal.kind === "operator" || principal.kind === "user")
|
|
19680
|
+
return true;
|
|
19681
|
+
if (principal.isLead)
|
|
19682
|
+
return true;
|
|
19683
|
+
if (resource?.kind !== "task")
|
|
19684
|
+
return false;
|
|
19685
|
+
return resource.agentId != null && resource.agentId === principal.agentId || resource.creatorAgentId != null && resource.creatorAgentId === principal.agentId;
|
|
19686
|
+
}
|
|
19687
|
+
};
|
|
19688
|
+
var LEGACY_POLICY = {
|
|
19689
|
+
"user.manage": leadOnly,
|
|
19690
|
+
"agent.profile.update.any": leadOnly,
|
|
19691
|
+
"agent.context.read.any": leadOnly,
|
|
19692
|
+
"task.cancel.any": leadOrTaskCreator,
|
|
19693
|
+
"task.read.own": requesterOwnsTask,
|
|
19694
|
+
"task.cancel.own": requesterOwnsTask,
|
|
19695
|
+
"task.action.own": requesterOwnsTask,
|
|
19696
|
+
"task.fs.mutate": taskFsMutate,
|
|
19697
|
+
"memory.learning.inject": leadOnly,
|
|
19698
|
+
"memory.delete.any": memoryOwnerOrLeadSwarm,
|
|
19699
|
+
"channel.delete": leadOnly,
|
|
19700
|
+
"integration.kapso.manage": leadOnly,
|
|
19701
|
+
"integration.slack.post": leadOnly,
|
|
19702
|
+
"integration.slack.read": leadOnly,
|
|
19703
|
+
"integration.slack.thread.start": leadOnly,
|
|
19704
|
+
"integration.slack.upload": leadOnly,
|
|
19705
|
+
"integration.slack.delete": leadOnly,
|
|
19706
|
+
"integration.slack.update": leadOnly,
|
|
19707
|
+
"credential-binding.manage": leadOnly,
|
|
19708
|
+
"script-connection.manage": leadOnly,
|
|
19709
|
+
"config.credential-bindings.write": leadOnly,
|
|
19710
|
+
"config.write.any": leadOnly,
|
|
19711
|
+
"config.delete.any": leadOnly,
|
|
19712
|
+
"config.read.secrets": leadOnly,
|
|
19713
|
+
"skill.create.swarm": leadOnly,
|
|
19714
|
+
"skill.install.any": leadOnly,
|
|
19715
|
+
"skill.install.global": leadOnly,
|
|
19716
|
+
"skill.uninstall.any": leadOnly,
|
|
19717
|
+
"skill.update.any": leadOrResourceOwner,
|
|
19718
|
+
"skill.promote.swarm": leadOnly,
|
|
19719
|
+
"skill.delete.any": leadOrResourceOwner,
|
|
19720
|
+
"mcp-server.create.swarm": leadOnly,
|
|
19721
|
+
"mcp-server.install.any": leadOnly,
|
|
19722
|
+
"mcp-server.uninstall.any": leadOnly,
|
|
19723
|
+
"mcp-server.delete.any": leadOrResourceOwner,
|
|
19724
|
+
"mcp-server.update.any": leadOrResourceOwner,
|
|
19725
|
+
"kv.write.any": leadOrOwnNamespace,
|
|
19726
|
+
"script.global.write": leadOnly,
|
|
19727
|
+
"script.global.delete": leadOnly
|
|
19728
|
+
};
|
|
19729
|
+
|
|
19730
|
+
// src/rbac/can.ts
|
|
19731
|
+
var auditSink = null;
|
|
19732
|
+
function setAuditSink(fn) {
|
|
19733
|
+
auditSink = fn;
|
|
19734
|
+
}
|
|
19735
|
+
function clearAuditSink() {
|
|
19736
|
+
auditSink = null;
|
|
19737
|
+
}
|
|
19738
|
+
function can(check) {
|
|
19739
|
+
const rule = LEGACY_POLICY[check.verb];
|
|
19740
|
+
const decision = rule.evaluate(check.principal, check.resource) ? { allow: true } : { allow: false, reason: rule.denyReason, missing: check.verb };
|
|
19741
|
+
if (auditSink) {
|
|
19742
|
+
try {
|
|
19743
|
+
auditSink(check, decision);
|
|
19744
|
+
} catch {}
|
|
19745
|
+
}
|
|
19746
|
+
return decision;
|
|
19747
|
+
}
|
|
19748
|
+
// src/rbac/permissions.ts
|
|
19749
|
+
init_zod();
|
|
19750
|
+
var PERMISSIONS = {
|
|
19751
|
+
"user.manage": {
|
|
19752
|
+
description: "Create, update, or deactivate user profiles.",
|
|
19753
|
+
namespace: "user"
|
|
19754
|
+
},
|
|
19755
|
+
"agent.profile.update.any": {
|
|
19756
|
+
description: "Update another agent's profile.",
|
|
19757
|
+
namespace: "agent"
|
|
19758
|
+
},
|
|
19759
|
+
"agent.context.read.any": {
|
|
19760
|
+
description: "View or diff another agent's context history.",
|
|
19761
|
+
namespace: "agent"
|
|
19762
|
+
},
|
|
19763
|
+
"task.cancel.any": {
|
|
19764
|
+
description: "Cancel any task (beyond tasks the caller created).",
|
|
19765
|
+
namespace: "task"
|
|
19766
|
+
},
|
|
19767
|
+
"task.read.own": {
|
|
19768
|
+
description: "Read details of a task the principal requested.",
|
|
19769
|
+
namespace: "task"
|
|
19770
|
+
},
|
|
19771
|
+
"task.cancel.own": {
|
|
19772
|
+
description: "Cancel a task the principal requested.",
|
|
19773
|
+
namespace: "task"
|
|
19774
|
+
},
|
|
19775
|
+
"task.action.own": {
|
|
19776
|
+
description: "Run actions (follow-up, retry, ...) on a task the principal requested.",
|
|
19777
|
+
namespace: "task"
|
|
19778
|
+
},
|
|
19779
|
+
"task.fs.mutate": {
|
|
19780
|
+
description: "Mutate a task's filesystem artifacts and attachments.",
|
|
19781
|
+
namespace: "task"
|
|
19782
|
+
},
|
|
19783
|
+
"memory.learning.inject": {
|
|
19784
|
+
description: "Inject a learning into another agent's memory.",
|
|
19785
|
+
namespace: "memory"
|
|
19786
|
+
},
|
|
19787
|
+
"memory.delete.any": {
|
|
19788
|
+
description: "Delete a memory entry (own entries, or swarm-scoped entries as lead).",
|
|
19789
|
+
namespace: "memory"
|
|
19790
|
+
},
|
|
19791
|
+
"channel.delete": {
|
|
19792
|
+
description: "Delete a Slack channel.",
|
|
19793
|
+
namespace: "channel"
|
|
19794
|
+
},
|
|
19795
|
+
"integration.kapso.manage": {
|
|
19796
|
+
description: "Register or unregister a Kapso inbound number.",
|
|
19797
|
+
namespace: "integration"
|
|
19798
|
+
},
|
|
19799
|
+
"integration.slack.post": {
|
|
19800
|
+
description: "Post to a direct Slack channel.",
|
|
19801
|
+
namespace: "integration"
|
|
19802
|
+
},
|
|
19803
|
+
"integration.slack.read": {
|
|
19804
|
+
description: "Read a direct Slack channel.",
|
|
19805
|
+
namespace: "integration"
|
|
19806
|
+
},
|
|
19807
|
+
"integration.slack.thread.start": {
|
|
19808
|
+
description: "Start a thread in a direct Slack channel.",
|
|
19809
|
+
namespace: "integration"
|
|
19810
|
+
},
|
|
19811
|
+
"integration.slack.upload": {
|
|
19812
|
+
description: "Upload a file to a direct Slack channel.",
|
|
19813
|
+
namespace: "integration"
|
|
19814
|
+
},
|
|
19815
|
+
"integration.slack.delete": {
|
|
19816
|
+
description: "Delete a Slack message.",
|
|
19817
|
+
namespace: "integration"
|
|
19818
|
+
},
|
|
19819
|
+
"integration.slack.update": {
|
|
19820
|
+
description: "Update (edit) a Slack message.",
|
|
19821
|
+
namespace: "integration"
|
|
19822
|
+
},
|
|
19823
|
+
"credential-binding.manage": {
|
|
19824
|
+
description: "Manage script credential bindings.",
|
|
19825
|
+
namespace: "credential-binding"
|
|
19826
|
+
},
|
|
19827
|
+
"script-connection.manage": {
|
|
19828
|
+
description: "Manage script connections.",
|
|
19829
|
+
namespace: "script-connection"
|
|
19830
|
+
},
|
|
19831
|
+
"config.credential-bindings.write": {
|
|
19832
|
+
description: "Write the SCRIPT_CREDENTIAL_BINDINGS swarm-config key.",
|
|
19833
|
+
namespace: "config"
|
|
19834
|
+
},
|
|
19835
|
+
"config.write.any": {
|
|
19836
|
+
description: "Write any swarm-config key.",
|
|
19837
|
+
namespace: "config"
|
|
19838
|
+
},
|
|
19839
|
+
"config.delete.any": {
|
|
19840
|
+
description: "Delete any swarm-config entry.",
|
|
19841
|
+
namespace: "config"
|
|
19842
|
+
},
|
|
19843
|
+
"config.read.secrets": {
|
|
19844
|
+
description: "Read unmasked secret config values.",
|
|
19845
|
+
namespace: "config"
|
|
19846
|
+
},
|
|
19847
|
+
"skill.create.swarm": {
|
|
19848
|
+
description: "Create a swarm-scoped skill.",
|
|
19849
|
+
namespace: "skill"
|
|
19850
|
+
},
|
|
19851
|
+
"skill.install.any": {
|
|
19852
|
+
description: "Install a skill for another agent.",
|
|
19853
|
+
namespace: "skill"
|
|
19854
|
+
},
|
|
19855
|
+
"skill.install.global": {
|
|
19856
|
+
description: "Install a remote/global skill.",
|
|
19857
|
+
namespace: "skill"
|
|
19858
|
+
},
|
|
19859
|
+
"skill.uninstall.any": {
|
|
19860
|
+
description: "Uninstall a skill for another agent.",
|
|
19861
|
+
namespace: "skill"
|
|
19862
|
+
},
|
|
19863
|
+
"skill.update.any": {
|
|
19864
|
+
description: "Update a skill the caller does not own.",
|
|
19865
|
+
namespace: "skill"
|
|
19866
|
+
},
|
|
19867
|
+
"skill.promote.swarm": {
|
|
19868
|
+
description: "Promote a skill to swarm scope (skill-approval path).",
|
|
19869
|
+
namespace: "skill"
|
|
19870
|
+
},
|
|
19871
|
+
"skill.delete.any": {
|
|
19872
|
+
description: "Delete a skill the caller does not own.",
|
|
19873
|
+
namespace: "skill"
|
|
19874
|
+
},
|
|
19875
|
+
"mcp-server.create.swarm": {
|
|
19876
|
+
description: "Create a swarm- or global-scoped MCP server.",
|
|
19877
|
+
namespace: "mcp-server"
|
|
19878
|
+
},
|
|
19879
|
+
"mcp-server.install.any": {
|
|
19880
|
+
description: "Install an MCP server for another agent.",
|
|
19881
|
+
namespace: "mcp-server"
|
|
19882
|
+
},
|
|
19883
|
+
"mcp-server.uninstall.any": {
|
|
19884
|
+
description: "Uninstall an MCP server for another agent.",
|
|
19885
|
+
namespace: "mcp-server"
|
|
19886
|
+
},
|
|
19887
|
+
"mcp-server.delete.any": {
|
|
19888
|
+
description: "Delete an MCP server the caller does not own.",
|
|
19889
|
+
namespace: "mcp-server"
|
|
19890
|
+
},
|
|
19891
|
+
"mcp-server.update.any": {
|
|
19892
|
+
description: "Update an MCP server the caller does not own.",
|
|
19893
|
+
namespace: "mcp-server"
|
|
19894
|
+
},
|
|
19895
|
+
"kv.write.any": {
|
|
19896
|
+
description: "Write another agent's task:agent: KV namespace.",
|
|
19897
|
+
namespace: "kv"
|
|
19898
|
+
},
|
|
19899
|
+
"script.global.write": {
|
|
19900
|
+
description: "Create or update a global-scope script.",
|
|
19901
|
+
namespace: "script"
|
|
19902
|
+
},
|
|
19903
|
+
"script.global.delete": {
|
|
19904
|
+
description: "Delete a global-scope script.",
|
|
19905
|
+
namespace: "script"
|
|
19906
|
+
}
|
|
19907
|
+
};
|
|
19908
|
+
var PERMISSION_VERBS = Object.keys(PERMISSIONS);
|
|
19909
|
+
var PermissionVerbSchema = _enum(PERMISSION_VERBS);
|
|
19616
19910
|
// src/tools/task-tool-ctx.ts
|
|
19617
19911
|
function ownerCtx(info) {
|
|
19618
19912
|
return {
|
|
@@ -19630,8 +19924,14 @@ function userCtx(user, sessionId) {
|
|
|
19630
19924
|
sessionId
|
|
19631
19925
|
};
|
|
19632
19926
|
}
|
|
19633
|
-
function assertOwnsTask(ctx, task) {
|
|
19634
|
-
|
|
19927
|
+
function assertOwnsTask(ctx, task, verb = "task.read.own") {
|
|
19928
|
+
const decision = can({
|
|
19929
|
+
principal: ctx.kind === "owner" ? ctx.agentId ? { kind: "agent", agentId: ctx.agentId, isLead: false } : { kind: "operator" } : { kind: "user", userId: ctx.userId },
|
|
19930
|
+
verb,
|
|
19931
|
+
resource: { kind: "task", taskId: task.id, requestedByUserId: task.requestedByUserId },
|
|
19932
|
+
source: "mcp"
|
|
19933
|
+
});
|
|
19934
|
+
if (decision.allow) {
|
|
19635
19935
|
return null;
|
|
19636
19936
|
}
|
|
19637
19937
|
const message = `Forbidden: this task is not yours (task ${task.id}).`;
|
|
@@ -19673,7 +19973,7 @@ async function initOtel(serviceRole = process.env.AGENT_ROLE || "api") {
|
|
|
19673
19973
|
return;
|
|
19674
19974
|
initialized2 = true;
|
|
19675
19975
|
try {
|
|
19676
|
-
const impl = await import("./otel-impl-
|
|
19976
|
+
const impl = await import("./otel-impl-b86qseaa.js");
|
|
19677
19977
|
await impl.boot(serviceRole);
|
|
19678
19978
|
realWithSpan = impl.withSpan;
|
|
19679
19979
|
realStartSpan = impl.startSpan;
|
|
@@ -19853,8 +20153,17 @@ async function cancelTaskHandler(ctx, { taskId, reason }) {
|
|
|
19853
20153
|
message: `Task "${taskId}" not found.`
|
|
19854
20154
|
};
|
|
19855
20155
|
}
|
|
19856
|
-
const
|
|
19857
|
-
|
|
20156
|
+
const decision = can({
|
|
20157
|
+
principal: { kind: "agent", agentId: callerAgent.id, isLead: callerAgent.isLead },
|
|
20158
|
+
verb: "task.cancel.any",
|
|
20159
|
+
resource: {
|
|
20160
|
+
kind: "task",
|
|
20161
|
+
taskId: existingTask2.id,
|
|
20162
|
+
creatorAgentId: existingTask2.creatorAgentId
|
|
20163
|
+
},
|
|
20164
|
+
source: "mcp"
|
|
20165
|
+
});
|
|
20166
|
+
if (!decision.allow) {
|
|
19858
20167
|
return {
|
|
19859
20168
|
success: false,
|
|
19860
20169
|
message: "Only the lead or task creator can cancel tasks."
|
|
@@ -19883,7 +20192,7 @@ async function cancelTaskHandler(ctx, { taskId, reason }) {
|
|
|
19883
20192
|
message: `Task "${taskId}" not found.`
|
|
19884
20193
|
};
|
|
19885
20194
|
}
|
|
19886
|
-
const ownershipError = assertOwnsTask(ctx, existingTask);
|
|
20195
|
+
const ownershipError = assertOwnsTask(ctx, existingTask, "task.cancel.own");
|
|
19887
20196
|
if (ownershipError)
|
|
19888
20197
|
return ownershipError;
|
|
19889
20198
|
const cancelled = cancelTask(taskId, reason);
|
|
@@ -20000,7 +20309,17 @@ var registerContextDiffTool = (server) => {
|
|
|
20000
20309
|
}
|
|
20001
20310
|
if (version.agentId !== requestInfo.agentId) {
|
|
20002
20311
|
const callerAgent = getAgentById(requestInfo.agentId);
|
|
20003
|
-
|
|
20312
|
+
const decision = can({
|
|
20313
|
+
principal: {
|
|
20314
|
+
kind: "agent",
|
|
20315
|
+
agentId: requestInfo.agentId,
|
|
20316
|
+
isLead: callerAgent?.isLead ?? false
|
|
20317
|
+
},
|
|
20318
|
+
verb: "agent.context.read.any",
|
|
20319
|
+
resource: { kind: "agent", agentId: version.agentId },
|
|
20320
|
+
source: "mcp"
|
|
20321
|
+
});
|
|
20322
|
+
if (!decision.allow) {
|
|
20004
20323
|
return {
|
|
20005
20324
|
content: [
|
|
20006
20325
|
{
|
|
@@ -20126,7 +20445,17 @@ var registerContextHistoryTool = (server) => {
|
|
|
20126
20445
|
}
|
|
20127
20446
|
if (targetAgentId !== requestInfo.agentId) {
|
|
20128
20447
|
const callerAgent = getAgentById(requestInfo.agentId);
|
|
20129
|
-
|
|
20448
|
+
const decision = can({
|
|
20449
|
+
principal: {
|
|
20450
|
+
kind: "agent",
|
|
20451
|
+
agentId: requestInfo.agentId,
|
|
20452
|
+
isLead: callerAgent?.isLead ?? false
|
|
20453
|
+
},
|
|
20454
|
+
verb: "agent.context.read.any",
|
|
20455
|
+
resource: { kind: "agent", agentId: targetAgentId },
|
|
20456
|
+
source: "mcp"
|
|
20457
|
+
});
|
|
20458
|
+
if (!decision.allow) {
|
|
20130
20459
|
return {
|
|
20131
20460
|
content: [
|
|
20132
20461
|
{
|
|
@@ -20954,7 +21283,17 @@ var registerCredentialBindingsTool = (server) => {
|
|
|
20954
21283
|
};
|
|
20955
21284
|
}
|
|
20956
21285
|
const agent = getAgentById(requestInfo.agentId);
|
|
20957
|
-
|
|
21286
|
+
const decision = can({
|
|
21287
|
+
principal: {
|
|
21288
|
+
kind: "agent",
|
|
21289
|
+
agentId: requestInfo.agentId,
|
|
21290
|
+
isLead: agent?.isLead ?? false
|
|
21291
|
+
},
|
|
21292
|
+
verb: "credential-binding.manage",
|
|
21293
|
+
resource: { kind: "none" },
|
|
21294
|
+
source: "mcp"
|
|
21295
|
+
});
|
|
21296
|
+
if (!decision.allow) {
|
|
20958
21297
|
return {
|
|
20959
21298
|
content: [{ type: "text", text: "Only the lead can manage credential bindings." }],
|
|
20960
21299
|
structuredContent: {
|
|
@@ -21211,7 +21550,17 @@ var registerDeleteChannelTool = (server) => {
|
|
|
21211
21550
|
};
|
|
21212
21551
|
}
|
|
21213
21552
|
const callingAgent = getAgentById(requestInfo.agentId);
|
|
21214
|
-
|
|
21553
|
+
const decision = can({
|
|
21554
|
+
principal: {
|
|
21555
|
+
kind: "agent",
|
|
21556
|
+
agentId: requestInfo.agentId,
|
|
21557
|
+
isLead: callingAgent?.isLead ?? false
|
|
21558
|
+
},
|
|
21559
|
+
verb: "channel.delete",
|
|
21560
|
+
resource: { kind: "none" },
|
|
21561
|
+
source: "mcp"
|
|
21562
|
+
});
|
|
21563
|
+
if (!decision.allow) {
|
|
21215
21564
|
return {
|
|
21216
21565
|
content: [
|
|
21217
21566
|
{ type: "text", text: "Not authorized. Only the lead agent can delete channels." }
|
|
@@ -21390,7 +21739,7 @@ async function getTaskDetailsHandler(ctx, { taskId }) {
|
|
|
21390
21739
|
}
|
|
21391
21740
|
};
|
|
21392
21741
|
}
|
|
21393
|
-
const ownershipError = assertOwnsTask(ctx, task);
|
|
21742
|
+
const ownershipError = assertOwnsTask(ctx, task, "task.read.own");
|
|
21394
21743
|
if (ownershipError)
|
|
21395
21744
|
return ownershipError;
|
|
21396
21745
|
const logs = getLogsByTaskIdChronological(taskId);
|
|
@@ -21593,7 +21942,17 @@ var registerInjectLearningTool = (server) => {
|
|
|
21593
21942
|
};
|
|
21594
21943
|
}
|
|
21595
21944
|
const callerAgent = getAgentById(requestInfo.agentId);
|
|
21596
|
-
|
|
21945
|
+
const decision = can({
|
|
21946
|
+
principal: {
|
|
21947
|
+
kind: "agent",
|
|
21948
|
+
agentId: requestInfo.agentId,
|
|
21949
|
+
isLead: callerAgent?.isLead ?? false
|
|
21950
|
+
},
|
|
21951
|
+
verb: "memory.learning.inject",
|
|
21952
|
+
resource: { kind: "agent", agentId: targetAgentId },
|
|
21953
|
+
source: "mcp"
|
|
21954
|
+
});
|
|
21955
|
+
if (!decision.allow) {
|
|
21597
21956
|
return {
|
|
21598
21957
|
content: [{ type: "text", text: "Only the lead agent can inject learnings." }],
|
|
21599
21958
|
structuredContent: {
|
|
@@ -21772,6 +22131,28 @@ init_zod();
|
|
|
21772
22131
|
init_db();
|
|
21773
22132
|
init_types();
|
|
21774
22133
|
|
|
22134
|
+
// src/tools/kv/kv-write-auth.ts
|
|
22135
|
+
init_db();
|
|
22136
|
+
function kvWriteAuthError(namespace, info) {
|
|
22137
|
+
if (namespace.startsWith("task:page:")) {
|
|
22138
|
+
return "task:page:* writes require a page-proxy request, not an MCP call";
|
|
22139
|
+
}
|
|
22140
|
+
if (namespace.startsWith("task:agent:")) {
|
|
22141
|
+
const ownNamespace = info.agentId != null && namespace === `task:agent:${info.agentId}`;
|
|
22142
|
+
const agent = !ownNamespace && info.agentId ? getAgentById(info.agentId) : null;
|
|
22143
|
+
const allowed = info.agentId != null && can({
|
|
22144
|
+
principal: { kind: "agent", agentId: info.agentId, isLead: agent?.isLead ?? false },
|
|
22145
|
+
verb: "kv.write.any",
|
|
22146
|
+
resource: { kind: "kv-namespace", namespace },
|
|
22147
|
+
source: "mcp"
|
|
22148
|
+
}).allow;
|
|
22149
|
+
if (!allowed) {
|
|
22150
|
+
return "writes to another agent's namespace require lead";
|
|
22151
|
+
}
|
|
22152
|
+
}
|
|
22153
|
+
return null;
|
|
22154
|
+
}
|
|
22155
|
+
|
|
21775
22156
|
// src/tools/kv/resolve-namespace.ts
|
|
21776
22157
|
init_db();
|
|
21777
22158
|
function resolveNamespace(explicit, info) {
|
|
@@ -21800,23 +22181,6 @@ function resolveNamespace(explicit, info) {
|
|
|
21800
22181
|
}
|
|
21801
22182
|
|
|
21802
22183
|
// src/tools/kv/kv-delete.ts
|
|
21803
|
-
function authError(namespace, info) {
|
|
21804
|
-
if (namespace.startsWith("task:page:")) {
|
|
21805
|
-
return "task:page:* writes require a page-proxy request, not an MCP call";
|
|
21806
|
-
}
|
|
21807
|
-
if (namespace.startsWith("task:agent:")) {
|
|
21808
|
-
const target = namespace.slice("task:agent:".length);
|
|
21809
|
-
if (info.agentId && target === info.agentId)
|
|
21810
|
-
return null;
|
|
21811
|
-
if (info.agentId) {
|
|
21812
|
-
const agent = getAgentById(info.agentId);
|
|
21813
|
-
if (agent?.isLead)
|
|
21814
|
-
return null;
|
|
21815
|
-
}
|
|
21816
|
-
return "writes to another agent's namespace require lead";
|
|
21817
|
-
}
|
|
21818
|
-
return null;
|
|
21819
|
-
}
|
|
21820
22184
|
var registerKvDeleteTool = (server) => {
|
|
21821
22185
|
createToolRegistrar(server)("kv-delete", {
|
|
21822
22186
|
title: "KV Delete",
|
|
@@ -21845,7 +22209,7 @@ var registerKvDeleteTool = (server) => {
|
|
|
21845
22209
|
}
|
|
21846
22210
|
};
|
|
21847
22211
|
}
|
|
21848
|
-
const authErr =
|
|
22212
|
+
const authErr = kvWriteAuthError(resolved.namespace, { agentId: requestInfo.agentId });
|
|
21849
22213
|
if (authErr) {
|
|
21850
22214
|
return {
|
|
21851
22215
|
content: [{ type: "text", text: authErr }],
|
|
@@ -21929,23 +22293,6 @@ var registerKvGetTool = (server) => {
|
|
|
21929
22293
|
init_zod();
|
|
21930
22294
|
init_db();
|
|
21931
22295
|
init_types();
|
|
21932
|
-
function authError2(namespace, info) {
|
|
21933
|
-
if (namespace.startsWith("task:page:")) {
|
|
21934
|
-
return "task:page:* writes require a page-proxy request, not an MCP call";
|
|
21935
|
-
}
|
|
21936
|
-
if (namespace.startsWith("task:agent:")) {
|
|
21937
|
-
const target = namespace.slice("task:agent:".length);
|
|
21938
|
-
if (info.agentId && target === info.agentId)
|
|
21939
|
-
return null;
|
|
21940
|
-
if (info.agentId) {
|
|
21941
|
-
const agent = getAgentById(info.agentId);
|
|
21942
|
-
if (agent?.isLead)
|
|
21943
|
-
return null;
|
|
21944
|
-
}
|
|
21945
|
-
return "writes to another agent's namespace require lead";
|
|
21946
|
-
}
|
|
21947
|
-
return null;
|
|
21948
|
-
}
|
|
21949
22296
|
var registerKvIncrTool = (server) => {
|
|
21950
22297
|
createToolRegistrar(server)("kv-incr", {
|
|
21951
22298
|
title: "KV Incr",
|
|
@@ -21975,7 +22322,7 @@ var registerKvIncrTool = (server) => {
|
|
|
21975
22322
|
}
|
|
21976
22323
|
};
|
|
21977
22324
|
}
|
|
21978
|
-
const authErr =
|
|
22325
|
+
const authErr = kvWriteAuthError(resolved.namespace, { agentId: requestInfo.agentId });
|
|
21979
22326
|
if (authErr) {
|
|
21980
22327
|
return {
|
|
21981
22328
|
content: [{ type: "text", text: authErr }],
|
|
@@ -22096,23 +22443,6 @@ init_zod();
|
|
|
22096
22443
|
init_db();
|
|
22097
22444
|
init_types();
|
|
22098
22445
|
var MAX_KV_BODY_BYTES = 2 * 1024 * 1024;
|
|
22099
|
-
function authError3(namespace, info) {
|
|
22100
|
-
if (namespace.startsWith("task:page:")) {
|
|
22101
|
-
return "task:page:* writes require a page-proxy request, not an MCP call";
|
|
22102
|
-
}
|
|
22103
|
-
if (namespace.startsWith("task:agent:")) {
|
|
22104
|
-
const target = namespace.slice("task:agent:".length);
|
|
22105
|
-
if (info.agentId && target === info.agentId)
|
|
22106
|
-
return null;
|
|
22107
|
-
if (info.agentId) {
|
|
22108
|
-
const agent = getAgentById(info.agentId);
|
|
22109
|
-
if (agent?.isLead)
|
|
22110
|
-
return null;
|
|
22111
|
-
}
|
|
22112
|
-
return "writes to another agent's namespace require lead";
|
|
22113
|
-
}
|
|
22114
|
-
return null;
|
|
22115
|
-
}
|
|
22116
22446
|
var registerKvSetTool = (server) => {
|
|
22117
22447
|
createToolRegistrar(server)("kv-set", {
|
|
22118
22448
|
title: "KV Set",
|
|
@@ -22144,7 +22474,7 @@ var registerKvSetTool = (server) => {
|
|
|
22144
22474
|
}
|
|
22145
22475
|
};
|
|
22146
22476
|
}
|
|
22147
|
-
const authErr =
|
|
22477
|
+
const authErr = kvWriteAuthError(resolved.namespace, { agentId: requestInfo.agentId });
|
|
22148
22478
|
if (authErr) {
|
|
22149
22479
|
return {
|
|
22150
22480
|
content: [{ type: "text", text: authErr }],
|
|
@@ -22413,7 +22743,17 @@ var registerManageUserTool = (server) => {
|
|
|
22413
22743
|
inputSchema: InputSchema
|
|
22414
22744
|
}, async (input, requestInfo) => {
|
|
22415
22745
|
const callerAgent = requestInfo.agentId ? getAgentById(requestInfo.agentId) : null;
|
|
22416
|
-
|
|
22746
|
+
const decision = can({
|
|
22747
|
+
principal: {
|
|
22748
|
+
kind: "agent",
|
|
22749
|
+
agentId: requestInfo.agentId ?? "",
|
|
22750
|
+
isLead: callerAgent?.isLead ?? false
|
|
22751
|
+
},
|
|
22752
|
+
verb: "user.manage",
|
|
22753
|
+
resource: { kind: "none" },
|
|
22754
|
+
source: "mcp"
|
|
22755
|
+
});
|
|
22756
|
+
if (!decision.allow || !callerAgent) {
|
|
22417
22757
|
return {
|
|
22418
22758
|
content: [
|
|
22419
22759
|
{ type: "text", text: "Only the lead agent can manage user profiles." }
|
|
@@ -22635,7 +22975,17 @@ var registerMcpServerCreateTool = (server) => {
|
|
|
22635
22975
|
const scope = args.scope ?? "agent";
|
|
22636
22976
|
if (scope === "swarm" || scope === "global") {
|
|
22637
22977
|
const agent = getAgentById(requestInfo.agentId);
|
|
22638
|
-
|
|
22978
|
+
const decision = can({
|
|
22979
|
+
principal: {
|
|
22980
|
+
kind: "agent",
|
|
22981
|
+
agentId: requestInfo.agentId,
|
|
22982
|
+
isLead: agent?.isLead ?? false
|
|
22983
|
+
},
|
|
22984
|
+
verb: "mcp-server.create.swarm",
|
|
22985
|
+
resource: { kind: "none" },
|
|
22986
|
+
source: "mcp"
|
|
22987
|
+
});
|
|
22988
|
+
if (!decision.allow) {
|
|
22639
22989
|
return {
|
|
22640
22990
|
content: [
|
|
22641
22991
|
{
|
|
@@ -22723,7 +23073,17 @@ var registerMcpServerDeleteTool = (server) => {
|
|
|
22723
23073
|
};
|
|
22724
23074
|
}
|
|
22725
23075
|
const agent = getAgentById(requestInfo.agentId);
|
|
22726
|
-
|
|
23076
|
+
const decision = can({
|
|
23077
|
+
principal: {
|
|
23078
|
+
kind: "agent",
|
|
23079
|
+
agentId: requestInfo.agentId,
|
|
23080
|
+
isLead: agent?.isLead ?? false
|
|
23081
|
+
},
|
|
23082
|
+
verb: "mcp-server.delete.any",
|
|
23083
|
+
resource: { kind: "owned", ownerAgentId: existing.ownerAgentId },
|
|
23084
|
+
source: "mcp"
|
|
23085
|
+
});
|
|
23086
|
+
if (!decision.allow) {
|
|
22727
23087
|
return {
|
|
22728
23088
|
content: [
|
|
22729
23089
|
{ type: "text", text: "Only the owning agent or lead can delete this MCP server." }
|
|
@@ -22842,7 +23202,17 @@ var registerMcpServerInstallTool = (server) => {
|
|
|
22842
23202
|
const targetAgentId = args.agentId ?? requestInfo.agentId;
|
|
22843
23203
|
if (targetAgentId !== requestInfo.agentId) {
|
|
22844
23204
|
const agent = getAgentById(requestInfo.agentId);
|
|
22845
|
-
|
|
23205
|
+
const decision = can({
|
|
23206
|
+
principal: {
|
|
23207
|
+
kind: "agent",
|
|
23208
|
+
agentId: requestInfo.agentId,
|
|
23209
|
+
isLead: agent?.isLead ?? false
|
|
23210
|
+
},
|
|
23211
|
+
verb: "mcp-server.install.any",
|
|
23212
|
+
resource: { kind: "agent", agentId: targetAgentId },
|
|
23213
|
+
source: "mcp"
|
|
23214
|
+
});
|
|
23215
|
+
if (!decision.allow) {
|
|
22846
23216
|
return {
|
|
22847
23217
|
content: [
|
|
22848
23218
|
{
|
|
@@ -22988,7 +23358,17 @@ var registerMcpServerUninstallTool = (server) => {
|
|
|
22988
23358
|
const targetAgentId = args.agentId ?? requestInfo.agentId;
|
|
22989
23359
|
if (targetAgentId !== requestInfo.agentId) {
|
|
22990
23360
|
const agent = getAgentById(requestInfo.agentId);
|
|
22991
|
-
|
|
23361
|
+
const decision = can({
|
|
23362
|
+
principal: {
|
|
23363
|
+
kind: "agent",
|
|
23364
|
+
agentId: requestInfo.agentId,
|
|
23365
|
+
isLead: agent?.isLead ?? false
|
|
23366
|
+
},
|
|
23367
|
+
verb: "mcp-server.uninstall.any",
|
|
23368
|
+
resource: { kind: "agent", agentId: targetAgentId },
|
|
23369
|
+
source: "mcp"
|
|
23370
|
+
});
|
|
23371
|
+
if (!decision.allow) {
|
|
22992
23372
|
return {
|
|
22993
23373
|
content: [
|
|
22994
23374
|
{
|
|
@@ -23068,7 +23448,17 @@ var registerMcpServerUpdateTool = (server) => {
|
|
|
23068
23448
|
};
|
|
23069
23449
|
}
|
|
23070
23450
|
const agent = getAgentById(requestInfo.agentId);
|
|
23071
|
-
|
|
23451
|
+
const decision = can({
|
|
23452
|
+
principal: {
|
|
23453
|
+
kind: "agent",
|
|
23454
|
+
agentId: requestInfo.agentId,
|
|
23455
|
+
isLead: agent?.isLead ?? false
|
|
23456
|
+
},
|
|
23457
|
+
verb: "mcp-server.update.any",
|
|
23458
|
+
resource: { kind: "owned", ownerAgentId: existing.ownerAgentId },
|
|
23459
|
+
source: "mcp"
|
|
23460
|
+
});
|
|
23461
|
+
if (!decision.allow) {
|
|
23072
23462
|
return {
|
|
23073
23463
|
content: [
|
|
23074
23464
|
{ type: "text", text: "Only the owning agent or lead can update this MCP server." }
|
|
@@ -23180,10 +23570,18 @@ var registerMemoryDeleteTool = (server) => {
|
|
|
23180
23570
|
}
|
|
23181
23571
|
};
|
|
23182
23572
|
}
|
|
23183
|
-
const isOwner = memory.agentId === requestInfo.agentId;
|
|
23184
23573
|
const agent = getAgentById(requestInfo.agentId);
|
|
23185
|
-
const
|
|
23186
|
-
|
|
23574
|
+
const decision = can({
|
|
23575
|
+
principal: {
|
|
23576
|
+
kind: "agent",
|
|
23577
|
+
agentId: requestInfo.agentId,
|
|
23578
|
+
isLead: agent?.isLead ?? false
|
|
23579
|
+
},
|
|
23580
|
+
verb: "memory.delete.any",
|
|
23581
|
+
resource: { kind: "owned", ownerAgentId: memory.agentId, scope: memory.scope },
|
|
23582
|
+
source: "mcp"
|
|
23583
|
+
});
|
|
23584
|
+
if (!decision.allow) {
|
|
23187
23585
|
return {
|
|
23188
23586
|
content: [{ type: "text", text: "You don't have permission to delete this memory." }],
|
|
23189
23587
|
structuredContent: {
|
|
@@ -25412,7 +25810,17 @@ var registerRegisterKapsoNumberTool = (server) => {
|
|
|
25412
25810
|
}, async ({ phoneNumberId, agentId, workflowId, name }, requestInfo) => {
|
|
25413
25811
|
try {
|
|
25414
25812
|
const callerAgent = requestInfo.agentId ? getAgentById(requestInfo.agentId) : null;
|
|
25415
|
-
|
|
25813
|
+
const decision = can({
|
|
25814
|
+
principal: {
|
|
25815
|
+
kind: "agent",
|
|
25816
|
+
agentId: requestInfo.agentId ?? "",
|
|
25817
|
+
isLead: callerAgent?.isLead ?? false
|
|
25818
|
+
},
|
|
25819
|
+
verb: "integration.kapso.manage",
|
|
25820
|
+
resource: { kind: "none" },
|
|
25821
|
+
source: "mcp"
|
|
25822
|
+
});
|
|
25823
|
+
if (!decision.allow) {
|
|
25416
25824
|
const msg = "Permission denied. Only the lead can register a Kapso number.";
|
|
25417
25825
|
return {
|
|
25418
25826
|
content: [{ type: "text", text: msg }],
|
|
@@ -25490,7 +25898,17 @@ var registerUnregisterKapsoNumberTool = (server) => {
|
|
|
25490
25898
|
}, async ({ phoneNumberId }, requestInfo) => {
|
|
25491
25899
|
try {
|
|
25492
25900
|
const callerAgent = requestInfo.agentId ? getAgentById(requestInfo.agentId) : null;
|
|
25493
|
-
|
|
25901
|
+
const decision = can({
|
|
25902
|
+
principal: {
|
|
25903
|
+
kind: "agent",
|
|
25904
|
+
agentId: requestInfo.agentId ?? "",
|
|
25905
|
+
isLead: callerAgent?.isLead ?? false
|
|
25906
|
+
},
|
|
25907
|
+
verb: "integration.kapso.manage",
|
|
25908
|
+
resource: { kind: "none" },
|
|
25909
|
+
source: "mcp"
|
|
25910
|
+
});
|
|
25911
|
+
if (!decision.allow) {
|
|
25494
25912
|
const msg = "Permission denied. Only the lead can unregister a Kapso number.";
|
|
25495
25913
|
return {
|
|
25496
25914
|
content: [{ type: "text", text: msg }],
|
|
@@ -25918,7 +26336,7 @@ init_types();
|
|
|
25918
26336
|
var createScheduleInputSchema = object({
|
|
25919
26337
|
name: string().min(1).max(100).describe("Unique name for the schedule (e.g., 'daily-cleanup')"),
|
|
25920
26338
|
taskTemplate: string().min(1).optional().describe("The task description that will be created each time. Required when targetType is 'agent-task' (the default)."),
|
|
25921
|
-
targetType: ScheduledTaskTargetTypeSchema.default("agent-task").optional().describe("Execution target
|
|
26339
|
+
targetType: ScheduledTaskTargetTypeSchema.default("agent-task").optional().describe("Execution target. Use 'workflow' + workflowId when the schedule only starts a workflow; " + "use 'script' + scriptName/scriptArgs when it only runs a catalog script; " + "use 'agent-task' only when a reasoning agent genuinely needs to be in the loop. " + "Do not create an agent-task whose taskTemplate just tells an agent to trigger a workflow or script."),
|
|
25922
26340
|
workflowId: string().uuid().optional().describe("Workflow ID to trigger. Required when targetType is 'workflow'."),
|
|
25923
26341
|
scriptName: string().optional().describe("Catalog script name (global scope). Required when targetType is 'script'."),
|
|
25924
26342
|
scriptArgs: record(string(), unknown()).optional().describe("JSON args passed to the script. Used when targetType is 'script'."),
|
|
@@ -26494,6 +26912,8 @@ var registerListSchedulesTool = (server) => {
|
|
|
26494
26912
|
name: string().optional().describe("Filter by name (partial match)"),
|
|
26495
26913
|
scheduleType: _enum(["recurring", "one_time"]).optional().describe("Filter by schedule type"),
|
|
26496
26914
|
hideCompleted: boolean().default(true).optional().describe("Hide completed one-time schedules (default: true)"),
|
|
26915
|
+
consecutiveErrorsMin: number().int().min(0).optional().describe("Only return schedules with at least this many consecutive errors."),
|
|
26916
|
+
lastRunStatus: _enum(["failed", "succeeded"]).optional().describe("Filter by derived last run status. `failed` means consecutiveErrors > 0; `succeeded` means lastRunAt is set and consecutiveErrors is 0."),
|
|
26497
26917
|
includeFull: boolean().optional().describe("Return the full `taskTemplate` instead of a short `taskTemplatePreview`. Default false.")
|
|
26498
26918
|
}),
|
|
26499
26919
|
outputSchema: object({
|
|
@@ -26517,13 +26937,24 @@ var registerListSchedulesTool = (server) => {
|
|
|
26517
26937
|
nextRunAt: string().optional(),
|
|
26518
26938
|
createdByAgentId: string().optional(),
|
|
26519
26939
|
timezone: string(),
|
|
26940
|
+
consecutiveErrors: number().optional(),
|
|
26941
|
+
lastErrorAt: string().optional(),
|
|
26942
|
+
lastErrorMessage: string().optional(),
|
|
26520
26943
|
scheduleType: string(),
|
|
26521
26944
|
createdAt: string(),
|
|
26522
26945
|
lastUpdatedAt: string()
|
|
26523
26946
|
})),
|
|
26524
26947
|
count: number()
|
|
26525
26948
|
})
|
|
26526
|
-
}, async ({
|
|
26949
|
+
}, async ({
|
|
26950
|
+
enabled: enabled2,
|
|
26951
|
+
name,
|
|
26952
|
+
scheduleType,
|
|
26953
|
+
hideCompleted,
|
|
26954
|
+
consecutiveErrorsMin,
|
|
26955
|
+
lastRunStatus,
|
|
26956
|
+
includeFull
|
|
26957
|
+
}, requestInfo, _meta) => {
|
|
26527
26958
|
if (!requestInfo.agentId) {
|
|
26528
26959
|
return {
|
|
26529
26960
|
content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
|
|
@@ -26536,7 +26967,14 @@ var registerListSchedulesTool = (server) => {
|
|
|
26536
26967
|
};
|
|
26537
26968
|
}
|
|
26538
26969
|
try {
|
|
26539
|
-
const filters = {
|
|
26970
|
+
const filters = {
|
|
26971
|
+
enabled: enabled2,
|
|
26972
|
+
name,
|
|
26973
|
+
scheduleType,
|
|
26974
|
+
hideCompleted,
|
|
26975
|
+
consecutiveErrorsMin,
|
|
26976
|
+
lastRunStatus
|
|
26977
|
+
};
|
|
26540
26978
|
const schedules = includeFull ? getScheduledTasks(filters) : getScheduledTasks(filters, { slim: true });
|
|
26541
26979
|
const count = schedules.length;
|
|
26542
26980
|
const statusSummary = count === 0 ? "No schedules found." : `Found ${count} schedule${count === 1 ? "" : "s"}.`;
|
|
@@ -26580,106 +27018,7 @@ ${scheduleList}`
|
|
|
26580
27018
|
}
|
|
26581
27019
|
});
|
|
26582
27020
|
};
|
|
26583
|
-
// src/tools/schedules/
|
|
26584
|
-
init_zod();
|
|
26585
|
-
init_db();
|
|
26586
|
-
var registerRunScheduleNowTool = (server) => {
|
|
26587
|
-
createToolRegistrar(server)("run-schedule-now", {
|
|
26588
|
-
title: "Run Schedule Now",
|
|
26589
|
-
annotations: { destructiveHint: false },
|
|
26590
|
-
description: "Immediately execute a scheduled task, creating a task right away. Does not affect the regular schedule timing.",
|
|
26591
|
-
inputSchema: object({
|
|
26592
|
-
scheduleId: string().uuid().optional().describe("Schedule ID to run"),
|
|
26593
|
-
name: string().optional().describe("Schedule name to run (alternative to ID)")
|
|
26594
|
-
}),
|
|
26595
|
-
outputSchema: object({
|
|
26596
|
-
yourAgentId: string().uuid().optional(),
|
|
26597
|
-
success: boolean(),
|
|
26598
|
-
message: string(),
|
|
26599
|
-
schedule: object({
|
|
26600
|
-
id: string(),
|
|
26601
|
-
name: string(),
|
|
26602
|
-
nextRunAt: string().optional()
|
|
26603
|
-
}).optional()
|
|
26604
|
-
})
|
|
26605
|
-
}, async ({ scheduleId, name }, requestInfo, _meta) => {
|
|
26606
|
-
if (!requestInfo.agentId) {
|
|
26607
|
-
return {
|
|
26608
|
-
content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
|
|
26609
|
-
structuredContent: {
|
|
26610
|
-
success: false,
|
|
26611
|
-
message: 'Agent ID not found. Set the "X-Agent-ID" header.'
|
|
26612
|
-
}
|
|
26613
|
-
};
|
|
26614
|
-
}
|
|
26615
|
-
if (!scheduleId && !name) {
|
|
26616
|
-
return {
|
|
26617
|
-
content: [{ type: "text", text: "Either scheduleId or name must be provided." }],
|
|
26618
|
-
structuredContent: {
|
|
26619
|
-
success: false,
|
|
26620
|
-
message: "Either scheduleId or name must be provided."
|
|
26621
|
-
}
|
|
26622
|
-
};
|
|
26623
|
-
}
|
|
26624
|
-
const schedule = scheduleId ? getScheduledTaskById(scheduleId) : name ? getScheduledTaskByName(name) : null;
|
|
26625
|
-
if (!schedule) {
|
|
26626
|
-
return {
|
|
26627
|
-
content: [{ type: "text", text: "Schedule not found." }],
|
|
26628
|
-
structuredContent: {
|
|
26629
|
-
success: false,
|
|
26630
|
-
message: "Schedule not found."
|
|
26631
|
-
}
|
|
26632
|
-
};
|
|
26633
|
-
}
|
|
26634
|
-
if (!schedule.enabled) {
|
|
26635
|
-
return {
|
|
26636
|
-
content: [
|
|
26637
|
-
{
|
|
26638
|
-
type: "text",
|
|
26639
|
-
text: `Schedule "${schedule.name}" is disabled. Enable it first or use it as a template.`
|
|
26640
|
-
}
|
|
26641
|
-
],
|
|
26642
|
-
structuredContent: {
|
|
26643
|
-
success: false,
|
|
26644
|
-
message: `Schedule "${schedule.name}" is disabled.`
|
|
26645
|
-
}
|
|
26646
|
-
};
|
|
26647
|
-
}
|
|
26648
|
-
try {
|
|
26649
|
-
await runScheduleNow(schedule.id);
|
|
26650
|
-
const updated = getScheduledTaskById(schedule.id);
|
|
26651
|
-
return {
|
|
26652
|
-
content: [
|
|
26653
|
-
{
|
|
26654
|
-
type: "text",
|
|
26655
|
-
text: `Executed schedule "${schedule.name}". Task created. Next regular run: ${updated?.nextRunAt || "not scheduled"}`
|
|
26656
|
-
}
|
|
26657
|
-
],
|
|
26658
|
-
structuredContent: {
|
|
26659
|
-
yourAgentId: requestInfo.agentId,
|
|
26660
|
-
success: true,
|
|
26661
|
-
message: `Executed schedule "${schedule.name}".`,
|
|
26662
|
-
schedule: updated ? {
|
|
26663
|
-
id: updated.id,
|
|
26664
|
-
name: updated.name,
|
|
26665
|
-
nextRunAt: updated.nextRunAt
|
|
26666
|
-
} : undefined
|
|
26667
|
-
}
|
|
26668
|
-
};
|
|
26669
|
-
} catch (error) {
|
|
26670
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
26671
|
-
return {
|
|
26672
|
-
content: [{ type: "text", text: `Failed to run schedule: ${message}` }],
|
|
26673
|
-
structuredContent: {
|
|
26674
|
-
yourAgentId: requestInfo.agentId,
|
|
26675
|
-
success: false,
|
|
26676
|
-
message: `Failed to run schedule: ${message}`
|
|
26677
|
-
}
|
|
26678
|
-
};
|
|
26679
|
-
}
|
|
26680
|
-
});
|
|
26681
|
-
};
|
|
26682
|
-
// src/tools/schedules/update-schedule.ts
|
|
27021
|
+
// src/tools/schedules/patch-schedule.ts
|
|
26683
27022
|
init_zod();
|
|
26684
27023
|
var import_cron_parser2 = __toESM(require_dist(), 1);
|
|
26685
27024
|
init_db();
|
|
@@ -26698,11 +27037,11 @@ function validateRecurringTiming(merged) {
|
|
|
26698
27037
|
return null;
|
|
26699
27038
|
}
|
|
26700
27039
|
|
|
26701
|
-
// src/tools/schedules/
|
|
27040
|
+
// src/tools/schedules/patch-schedule.ts
|
|
26702
27041
|
init_types();
|
|
26703
|
-
var
|
|
26704
|
-
scheduleId: string().uuid().optional().describe("Schedule ID to
|
|
26705
|
-
name: string().optional().describe("Schedule name to
|
|
27042
|
+
var patchScheduleInputSchema = object({
|
|
27043
|
+
scheduleId: string().uuid().optional().describe("Schedule ID to patch"),
|
|
27044
|
+
name: string().optional().describe("Schedule name to patch (alternative to ID)"),
|
|
26706
27045
|
newName: string().min(1).max(100).optional().describe("New name for the schedule"),
|
|
26707
27046
|
taskTemplate: string().min(1).optional().describe("New task template"),
|
|
26708
27047
|
targetType: ScheduledTaskTargetTypeSchema.optional().describe("Change the execution target: 'agent-task', 'workflow', or 'script'."),
|
|
@@ -26721,12 +27060,12 @@ var updateScheduleInputSchema = object({
|
|
|
26721
27060
|
model: string().trim().min(1).nullable().optional().describe("Concrete model override for tasks created by this schedule. Set to null to clear."),
|
|
26722
27061
|
modelTier: ModelTierSchema.nullable().optional().describe("Portable model tier for tasks created by this schedule. Set to null to clear.")
|
|
26723
27062
|
});
|
|
26724
|
-
var
|
|
26725
|
-
createToolRegistrar(server)("
|
|
26726
|
-
title: "
|
|
27063
|
+
var registerPatchScheduleTool = (server) => {
|
|
27064
|
+
createToolRegistrar(server)("patch-schedule", {
|
|
27065
|
+
title: "Patch Scheduled Task",
|
|
26727
27066
|
annotations: { idempotentHint: true },
|
|
26728
|
-
description: "
|
|
26729
|
-
inputSchema:
|
|
27067
|
+
description: "Patch an existing scheduled task by shallow-merging provided fields over the current row. Any registered agent can patch schedules.",
|
|
27068
|
+
inputSchema: patchScheduleInputSchema,
|
|
26730
27069
|
outputSchema: object({
|
|
26731
27070
|
yourAgentId: string().uuid().optional(),
|
|
26732
27071
|
success: boolean(),
|
|
@@ -26838,6 +27177,429 @@ var registerUpdateScheduleTool = (server) => {
|
|
|
26838
27177
|
};
|
|
26839
27178
|
}
|
|
26840
27179
|
}
|
|
27180
|
+
if (targetAgentId) {
|
|
27181
|
+
const agent = getAgentById(targetAgentId);
|
|
27182
|
+
if (!agent) {
|
|
27183
|
+
return {
|
|
27184
|
+
content: [{ type: "text", text: `Target agent not found: ${targetAgentId}` }],
|
|
27185
|
+
structuredContent: {
|
|
27186
|
+
success: false,
|
|
27187
|
+
message: `Target agent not found: ${targetAgentId}`
|
|
27188
|
+
}
|
|
27189
|
+
};
|
|
27190
|
+
}
|
|
27191
|
+
}
|
|
27192
|
+
if (newName && newName !== schedule.name) {
|
|
27193
|
+
const existing = getScheduledTaskByName(newName);
|
|
27194
|
+
if (existing) {
|
|
27195
|
+
return {
|
|
27196
|
+
content: [{ type: "text", text: `Schedule with name "${newName}" already exists.` }],
|
|
27197
|
+
structuredContent: {
|
|
27198
|
+
success: false,
|
|
27199
|
+
message: `Schedule with name "${newName}" already exists.`
|
|
27200
|
+
}
|
|
27201
|
+
};
|
|
27202
|
+
}
|
|
27203
|
+
}
|
|
27204
|
+
const mergedTargetType = targetType ?? schedule.targetType;
|
|
27205
|
+
const mergedTaskTemplate = taskTemplate !== undefined ? taskTemplate : schedule.taskTemplate;
|
|
27206
|
+
const mergedWorkflowId = workflowId !== undefined ? workflowId : schedule.workflowId;
|
|
27207
|
+
const mergedScriptName = scriptName !== undefined ? scriptName : schedule.scriptName;
|
|
27208
|
+
if (mergedTargetType === "agent-task" && !mergedTaskTemplate) {
|
|
27209
|
+
const message = "taskTemplate is required when targetType is 'agent-task'.";
|
|
27210
|
+
return {
|
|
27211
|
+
content: [{ type: "text", text: message }],
|
|
27212
|
+
structuredContent: { success: false, message }
|
|
27213
|
+
};
|
|
27214
|
+
}
|
|
27215
|
+
if (mergedTargetType === "workflow") {
|
|
27216
|
+
if (!mergedWorkflowId) {
|
|
27217
|
+
const message = "workflowId is required when targetType is 'workflow'.";
|
|
27218
|
+
return {
|
|
27219
|
+
content: [{ type: "text", text: message }],
|
|
27220
|
+
structuredContent: { success: false, message }
|
|
27221
|
+
};
|
|
27222
|
+
}
|
|
27223
|
+
if (!getWorkflow(mergedWorkflowId)) {
|
|
27224
|
+
const message = `Workflow not found: ${mergedWorkflowId}`;
|
|
27225
|
+
return {
|
|
27226
|
+
content: [{ type: "text", text: message }],
|
|
27227
|
+
structuredContent: { success: false, message }
|
|
27228
|
+
};
|
|
27229
|
+
}
|
|
27230
|
+
}
|
|
27231
|
+
if (mergedTargetType === "script") {
|
|
27232
|
+
if (!mergedScriptName) {
|
|
27233
|
+
const message = "scriptName is required when targetType is 'script'.";
|
|
27234
|
+
return {
|
|
27235
|
+
content: [{ type: "text", text: message }],
|
|
27236
|
+
structuredContent: { success: false, message }
|
|
27237
|
+
};
|
|
27238
|
+
}
|
|
27239
|
+
if (!getScript({ name: mergedScriptName, scope: "global" })) {
|
|
27240
|
+
const message = `Script not found: ${mergedScriptName}`;
|
|
27241
|
+
return {
|
|
27242
|
+
content: [{ type: "text", text: message }],
|
|
27243
|
+
structuredContent: { success: false, message }
|
|
27244
|
+
};
|
|
27245
|
+
}
|
|
27246
|
+
}
|
|
27247
|
+
try {
|
|
27248
|
+
const updateData = {};
|
|
27249
|
+
if (newName !== undefined)
|
|
27250
|
+
updateData.name = newName;
|
|
27251
|
+
if (taskTemplate !== undefined)
|
|
27252
|
+
updateData.taskTemplate = taskTemplate;
|
|
27253
|
+
if (targetType !== undefined)
|
|
27254
|
+
updateData.targetType = targetType;
|
|
27255
|
+
if (workflowId !== undefined)
|
|
27256
|
+
updateData.workflowId = workflowId;
|
|
27257
|
+
if (scriptName !== undefined)
|
|
27258
|
+
updateData.scriptName = scriptName;
|
|
27259
|
+
if (scriptArgs !== undefined)
|
|
27260
|
+
updateData.scriptArgs = scriptArgs;
|
|
27261
|
+
if (cronExpression !== undefined)
|
|
27262
|
+
updateData.cronExpression = cronExpression;
|
|
27263
|
+
if (intervalMs !== undefined)
|
|
27264
|
+
updateData.intervalMs = intervalMs;
|
|
27265
|
+
if (description !== undefined)
|
|
27266
|
+
updateData.description = description;
|
|
27267
|
+
if (taskType !== undefined)
|
|
27268
|
+
updateData.taskType = taskType;
|
|
27269
|
+
if (tags !== undefined)
|
|
27270
|
+
updateData.tags = tags;
|
|
27271
|
+
if (priority !== undefined)
|
|
27272
|
+
updateData.priority = priority;
|
|
27273
|
+
if (targetAgentId !== undefined)
|
|
27274
|
+
updateData.targetAgentId = targetAgentId;
|
|
27275
|
+
if (timezone !== undefined)
|
|
27276
|
+
updateData.timezone = timezone;
|
|
27277
|
+
if (enabled2 !== undefined)
|
|
27278
|
+
updateData.enabled = enabled2;
|
|
27279
|
+
if (model !== undefined || modelTier !== undefined) {
|
|
27280
|
+
const normalizedModel = splitLegacyModelAlias({ model, modelTier });
|
|
27281
|
+
if (model !== undefined)
|
|
27282
|
+
updateData.model = normalizedModel.model ?? null;
|
|
27283
|
+
if (modelTier !== undefined || normalizedModel.modelTier) {
|
|
27284
|
+
updateData.modelTier = normalizedModel.modelTier ?? null;
|
|
27285
|
+
}
|
|
27286
|
+
}
|
|
27287
|
+
if (schedule.scheduleType === "one_time") {
|
|
27288
|
+
if (enabled2 === false) {
|
|
27289
|
+
updateData.nextRunAt = null;
|
|
27290
|
+
}
|
|
27291
|
+
} else {
|
|
27292
|
+
const timing = mergeScheduleTiming({
|
|
27293
|
+
cronExpression: schedule.cronExpression ?? null,
|
|
27294
|
+
intervalMs: schedule.intervalMs ?? null
|
|
27295
|
+
}, { cronExpression, intervalMs });
|
|
27296
|
+
const timingError = validateRecurringTiming(timing);
|
|
27297
|
+
if (timingError) {
|
|
27298
|
+
return {
|
|
27299
|
+
content: [
|
|
27300
|
+
{
|
|
27301
|
+
type: "text",
|
|
27302
|
+
text: "At least one of intervalMs or cronExpression must be set for recurring schedules."
|
|
27303
|
+
}
|
|
27304
|
+
],
|
|
27305
|
+
structuredContent: {
|
|
27306
|
+
success: false,
|
|
27307
|
+
message: "At least one of intervalMs or cronExpression must be set for recurring schedules."
|
|
27308
|
+
}
|
|
27309
|
+
};
|
|
27310
|
+
}
|
|
27311
|
+
const needsNextRunRecalc = cronExpression !== undefined || intervalMs !== undefined || timezone !== undefined || enabled2 === true && !schedule.enabled;
|
|
27312
|
+
if (needsNextRunRecalc && enabled2 !== false) {
|
|
27313
|
+
const mergedTimezone = timezone !== undefined ? timezone : schedule.timezone;
|
|
27314
|
+
updateData.nextRunAt = calculateNextRun({
|
|
27315
|
+
cronExpression: timing.mergedCron,
|
|
27316
|
+
intervalMs: timing.mergedInterval,
|
|
27317
|
+
timezone: mergedTimezone
|
|
27318
|
+
}, new Date);
|
|
27319
|
+
} else if (enabled2 === false) {
|
|
27320
|
+
updateData.nextRunAt = null;
|
|
27321
|
+
}
|
|
27322
|
+
}
|
|
27323
|
+
const updatedBy = resolveTaskAuditUserId(requestInfo.sourceTaskId, requestInfo.agentId) ?? undefined;
|
|
27324
|
+
const updated = updateScheduledTask(schedule.id, { ...updateData, updatedBy });
|
|
27325
|
+
if (!updated) {
|
|
27326
|
+
return {
|
|
27327
|
+
content: [{ type: "text", text: "Failed to update schedule." }],
|
|
27328
|
+
structuredContent: {
|
|
27329
|
+
success: false,
|
|
27330
|
+
message: "Failed to update schedule."
|
|
27331
|
+
}
|
|
27332
|
+
};
|
|
27333
|
+
}
|
|
27334
|
+
return {
|
|
27335
|
+
content: [
|
|
27336
|
+
{
|
|
27337
|
+
type: "text",
|
|
27338
|
+
text: `Patched schedule "${updated.name}". Next run: ${updated.nextRunAt || "disabled"}`
|
|
27339
|
+
}
|
|
27340
|
+
],
|
|
27341
|
+
structuredContent: {
|
|
27342
|
+
yourAgentId: requestInfo.agentId,
|
|
27343
|
+
success: true,
|
|
27344
|
+
message: `Patched schedule "${updated.name}".`,
|
|
27345
|
+
schedule: updated
|
|
27346
|
+
}
|
|
27347
|
+
};
|
|
27348
|
+
} catch (error) {
|
|
27349
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
27350
|
+
return {
|
|
27351
|
+
content: [{ type: "text", text: `Failed to update schedule: ${message}` }],
|
|
27352
|
+
structuredContent: {
|
|
27353
|
+
yourAgentId: requestInfo.agentId,
|
|
27354
|
+
success: false,
|
|
27355
|
+
message: `Failed to update schedule: ${message}`
|
|
27356
|
+
}
|
|
27357
|
+
};
|
|
27358
|
+
}
|
|
27359
|
+
});
|
|
27360
|
+
};
|
|
27361
|
+
// src/tools/schedules/run-schedule-now.ts
|
|
27362
|
+
init_zod();
|
|
27363
|
+
init_db();
|
|
27364
|
+
var registerRunScheduleNowTool = (server) => {
|
|
27365
|
+
createToolRegistrar(server)("run-schedule-now", {
|
|
27366
|
+
title: "Run Schedule Now",
|
|
27367
|
+
annotations: { destructiveHint: false },
|
|
27368
|
+
description: "Immediately execute a scheduled task, creating a task right away. Does not affect the regular schedule timing.",
|
|
27369
|
+
inputSchema: object({
|
|
27370
|
+
scheduleId: string().uuid().optional().describe("Schedule ID to run"),
|
|
27371
|
+
name: string().optional().describe("Schedule name to run (alternative to ID)")
|
|
27372
|
+
}),
|
|
27373
|
+
outputSchema: object({
|
|
27374
|
+
yourAgentId: string().uuid().optional(),
|
|
27375
|
+
success: boolean(),
|
|
27376
|
+
message: string(),
|
|
27377
|
+
schedule: object({
|
|
27378
|
+
id: string(),
|
|
27379
|
+
name: string(),
|
|
27380
|
+
nextRunAt: string().optional()
|
|
27381
|
+
}).optional()
|
|
27382
|
+
})
|
|
27383
|
+
}, async ({ scheduleId, name }, requestInfo, _meta) => {
|
|
27384
|
+
if (!requestInfo.agentId) {
|
|
27385
|
+
return {
|
|
27386
|
+
content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
|
|
27387
|
+
structuredContent: {
|
|
27388
|
+
success: false,
|
|
27389
|
+
message: 'Agent ID not found. Set the "X-Agent-ID" header.'
|
|
27390
|
+
}
|
|
27391
|
+
};
|
|
27392
|
+
}
|
|
27393
|
+
if (!scheduleId && !name) {
|
|
27394
|
+
return {
|
|
27395
|
+
content: [{ type: "text", text: "Either scheduleId or name must be provided." }],
|
|
27396
|
+
structuredContent: {
|
|
27397
|
+
success: false,
|
|
27398
|
+
message: "Either scheduleId or name must be provided."
|
|
27399
|
+
}
|
|
27400
|
+
};
|
|
27401
|
+
}
|
|
27402
|
+
const schedule = scheduleId ? getScheduledTaskById(scheduleId) : name ? getScheduledTaskByName(name) : null;
|
|
27403
|
+
if (!schedule) {
|
|
27404
|
+
return {
|
|
27405
|
+
content: [{ type: "text", text: "Schedule not found." }],
|
|
27406
|
+
structuredContent: {
|
|
27407
|
+
success: false,
|
|
27408
|
+
message: "Schedule not found."
|
|
27409
|
+
}
|
|
27410
|
+
};
|
|
27411
|
+
}
|
|
27412
|
+
if (!schedule.enabled) {
|
|
27413
|
+
return {
|
|
27414
|
+
content: [
|
|
27415
|
+
{
|
|
27416
|
+
type: "text",
|
|
27417
|
+
text: `Schedule "${schedule.name}" is disabled. Enable it first or use it as a template.`
|
|
27418
|
+
}
|
|
27419
|
+
],
|
|
27420
|
+
structuredContent: {
|
|
27421
|
+
success: false,
|
|
27422
|
+
message: `Schedule "${schedule.name}" is disabled.`
|
|
27423
|
+
}
|
|
27424
|
+
};
|
|
27425
|
+
}
|
|
27426
|
+
try {
|
|
27427
|
+
await runScheduleNow(schedule.id);
|
|
27428
|
+
const updated = getScheduledTaskById(schedule.id);
|
|
27429
|
+
return {
|
|
27430
|
+
content: [
|
|
27431
|
+
{
|
|
27432
|
+
type: "text",
|
|
27433
|
+
text: `Executed schedule "${schedule.name}". Task created. Next regular run: ${updated?.nextRunAt || "not scheduled"}`
|
|
27434
|
+
}
|
|
27435
|
+
],
|
|
27436
|
+
structuredContent: {
|
|
27437
|
+
yourAgentId: requestInfo.agentId,
|
|
27438
|
+
success: true,
|
|
27439
|
+
message: `Executed schedule "${schedule.name}".`,
|
|
27440
|
+
schedule: updated ? {
|
|
27441
|
+
id: updated.id,
|
|
27442
|
+
name: updated.name,
|
|
27443
|
+
nextRunAt: updated.nextRunAt
|
|
27444
|
+
} : undefined
|
|
27445
|
+
}
|
|
27446
|
+
};
|
|
27447
|
+
} catch (error) {
|
|
27448
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
27449
|
+
return {
|
|
27450
|
+
content: [{ type: "text", text: `Failed to run schedule: ${message}` }],
|
|
27451
|
+
structuredContent: {
|
|
27452
|
+
yourAgentId: requestInfo.agentId,
|
|
27453
|
+
success: false,
|
|
27454
|
+
message: `Failed to run schedule: ${message}`
|
|
27455
|
+
}
|
|
27456
|
+
};
|
|
27457
|
+
}
|
|
27458
|
+
});
|
|
27459
|
+
};
|
|
27460
|
+
// src/tools/schedules/update-schedule.ts
|
|
27461
|
+
init_zod();
|
|
27462
|
+
var import_cron_parser3 = __toESM(require_dist(), 1);
|
|
27463
|
+
init_db();
|
|
27464
|
+
init_types();
|
|
27465
|
+
var updateScheduleInputSchema = object({
|
|
27466
|
+
scheduleId: string().uuid().optional().describe("Schedule ID to update"),
|
|
27467
|
+
name: string().optional().describe("Schedule name to update (alternative to ID)"),
|
|
27468
|
+
newName: string().min(1).max(100).optional().describe("New name for the schedule"),
|
|
27469
|
+
taskTemplate: string().min(1).optional().describe("New task template"),
|
|
27470
|
+
targetType: ScheduledTaskTargetTypeSchema.optional().describe("Change the execution target: 'agent-task', 'workflow', or 'script'."),
|
|
27471
|
+
workflowId: string().uuid().nullable().optional().describe("New workflow ID (required when targetType is 'workflow'; null to clear)"),
|
|
27472
|
+
scriptName: string().nullable().optional().describe("New catalog script name (required when targetType is 'script'; null to clear)"),
|
|
27473
|
+
scriptArgs: record(string(), unknown()).nullable().optional().describe("New JSON args for the script target (null to clear)"),
|
|
27474
|
+
cronExpression: string().nullable().optional().describe("New cron expression (null to clear)"),
|
|
27475
|
+
intervalMs: number().int().positive().nullable().optional().describe("New interval in milliseconds (null to clear)"),
|
|
27476
|
+
description: string().optional().describe("New description"),
|
|
27477
|
+
taskType: string().max(50).optional().describe("New task type"),
|
|
27478
|
+
tags: array(string()).optional().describe("New tags"),
|
|
27479
|
+
priority: number().int().min(0).max(100).optional().describe("New priority"),
|
|
27480
|
+
targetAgentId: string().uuid().nullable().optional().describe("New target agent ID"),
|
|
27481
|
+
timezone: string().optional().describe("New timezone"),
|
|
27482
|
+
enabled: boolean().optional().describe("Enable or disable the schedule"),
|
|
27483
|
+
model: string().trim().min(1).nullable().optional().describe("Concrete model override for tasks created by this schedule. Set to null to clear."),
|
|
27484
|
+
modelTier: ModelTierSchema.nullable().optional().describe("Portable model tier for tasks created by this schedule. Set to null to clear.")
|
|
27485
|
+
});
|
|
27486
|
+
var registerUpdateScheduleTool = (server) => {
|
|
27487
|
+
createToolRegistrar(server)("update-schedule", {
|
|
27488
|
+
title: "Update Scheduled Task",
|
|
27489
|
+
annotations: { idempotentHint: true },
|
|
27490
|
+
description: "Update an existing scheduled task. Any registered agent can update schedules.",
|
|
27491
|
+
inputSchema: updateScheduleInputSchema,
|
|
27492
|
+
outputSchema: object({
|
|
27493
|
+
yourAgentId: string().uuid().optional(),
|
|
27494
|
+
success: boolean(),
|
|
27495
|
+
message: string(),
|
|
27496
|
+
schedule: object({
|
|
27497
|
+
id: string(),
|
|
27498
|
+
name: string(),
|
|
27499
|
+
description: string().optional(),
|
|
27500
|
+
cronExpression: string().optional(),
|
|
27501
|
+
intervalMs: number().optional(),
|
|
27502
|
+
taskTemplate: string().optional(),
|
|
27503
|
+
taskType: string().optional(),
|
|
27504
|
+
tags: array(string()),
|
|
27505
|
+
priority: number(),
|
|
27506
|
+
targetAgentId: string().optional(),
|
|
27507
|
+
enabled: boolean(),
|
|
27508
|
+
lastRunAt: string().optional(),
|
|
27509
|
+
nextRunAt: string().optional(),
|
|
27510
|
+
createdByAgentId: string().optional(),
|
|
27511
|
+
timezone: string(),
|
|
27512
|
+
model: string().optional(),
|
|
27513
|
+
modelTier: ModelTierSchema.optional(),
|
|
27514
|
+
scheduleType: string(),
|
|
27515
|
+
targetType: ScheduledTaskTargetTypeSchema.optional(),
|
|
27516
|
+
workflowId: string().optional(),
|
|
27517
|
+
scriptName: string().optional(),
|
|
27518
|
+
scriptArgs: record(string(), unknown()).optional(),
|
|
27519
|
+
createdAt: string(),
|
|
27520
|
+
lastUpdatedAt: string()
|
|
27521
|
+
}).optional()
|
|
27522
|
+
})
|
|
27523
|
+
}, async ({
|
|
27524
|
+
scheduleId,
|
|
27525
|
+
name,
|
|
27526
|
+
newName,
|
|
27527
|
+
taskTemplate,
|
|
27528
|
+
targetType,
|
|
27529
|
+
workflowId,
|
|
27530
|
+
scriptName,
|
|
27531
|
+
scriptArgs,
|
|
27532
|
+
cronExpression,
|
|
27533
|
+
intervalMs,
|
|
27534
|
+
description,
|
|
27535
|
+
taskType,
|
|
27536
|
+
tags,
|
|
27537
|
+
priority,
|
|
27538
|
+
targetAgentId,
|
|
27539
|
+
timezone,
|
|
27540
|
+
enabled: enabled2,
|
|
27541
|
+
model,
|
|
27542
|
+
modelTier
|
|
27543
|
+
}, requestInfo, _meta) => {
|
|
27544
|
+
if (!requestInfo.agentId) {
|
|
27545
|
+
return {
|
|
27546
|
+
content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
|
|
27547
|
+
structuredContent: {
|
|
27548
|
+
success: false,
|
|
27549
|
+
message: 'Agent ID not found. Set the "X-Agent-ID" header.'
|
|
27550
|
+
}
|
|
27551
|
+
};
|
|
27552
|
+
}
|
|
27553
|
+
const schedule = scheduleId ? getScheduledTaskById(scheduleId) : name ? getScheduledTaskByName(name) : null;
|
|
27554
|
+
if (!schedule) {
|
|
27555
|
+
return {
|
|
27556
|
+
content: [{ type: "text", text: "Schedule not found." }],
|
|
27557
|
+
structuredContent: {
|
|
27558
|
+
success: false,
|
|
27559
|
+
message: "Schedule not found."
|
|
27560
|
+
}
|
|
27561
|
+
};
|
|
27562
|
+
}
|
|
27563
|
+
const caller = getAgentById(requestInfo.agentId);
|
|
27564
|
+
if (!caller) {
|
|
27565
|
+
return {
|
|
27566
|
+
content: [{ type: "text", text: "Agent not found." }],
|
|
27567
|
+
structuredContent: {
|
|
27568
|
+
success: false,
|
|
27569
|
+
message: "Agent not found."
|
|
27570
|
+
}
|
|
27571
|
+
};
|
|
27572
|
+
}
|
|
27573
|
+
if (schedule.scheduleType === "one_time" && !schedule.enabled && schedule.lastRunAt) {
|
|
27574
|
+
return {
|
|
27575
|
+
content: [
|
|
27576
|
+
{
|
|
27577
|
+
type: "text",
|
|
27578
|
+
text: `One-time schedule "${schedule.name}" has already executed. Create a new one instead.`
|
|
27579
|
+
}
|
|
27580
|
+
],
|
|
27581
|
+
structuredContent: {
|
|
27582
|
+
success: false,
|
|
27583
|
+
message: `One-time schedule "${schedule.name}" has already executed. Create a new one instead.`
|
|
27584
|
+
}
|
|
27585
|
+
};
|
|
27586
|
+
}
|
|
27587
|
+
if (cronExpression) {
|
|
27588
|
+
try {
|
|
27589
|
+
import_cron_parser3.CronExpressionParser.parse(cronExpression, {
|
|
27590
|
+
tz: timezone || schedule.timezone || "UTC"
|
|
27591
|
+
});
|
|
27592
|
+
} catch (err) {
|
|
27593
|
+
const message = err instanceof Error ? err.message : "Invalid cron expression";
|
|
27594
|
+
return {
|
|
27595
|
+
content: [{ type: "text", text: `Invalid cron expression: ${message}` }],
|
|
27596
|
+
structuredContent: {
|
|
27597
|
+
success: false,
|
|
27598
|
+
message: `Invalid cron expression: ${message}`
|
|
27599
|
+
}
|
|
27600
|
+
};
|
|
27601
|
+
}
|
|
27602
|
+
}
|
|
26841
27603
|
if (targetAgentId && targetAgentId !== null) {
|
|
26842
27604
|
const agent = getAgentById(targetAgentId);
|
|
26843
27605
|
if (!agent) {
|
|
@@ -26947,7 +27709,7 @@ var registerUpdateScheduleTool = (server) => {
|
|
|
26947
27709
|
}
|
|
26948
27710
|
if (schedule.scheduleType === "one_time") {
|
|
26949
27711
|
if (enabled2 === false) {
|
|
26950
|
-
updateData.nextRunAt =
|
|
27712
|
+
updateData.nextRunAt = null;
|
|
26951
27713
|
}
|
|
26952
27714
|
} else {
|
|
26953
27715
|
const timing = mergeScheduleTiming({
|
|
@@ -26978,7 +27740,7 @@ var registerUpdateScheduleTool = (server) => {
|
|
|
26978
27740
|
timezone: mergedTimezone
|
|
26979
27741
|
}, new Date);
|
|
26980
27742
|
} else if (enabled2 === false) {
|
|
26981
|
-
updateData.nextRunAt =
|
|
27743
|
+
updateData.nextRunAt = null;
|
|
26982
27744
|
}
|
|
26983
27745
|
}
|
|
26984
27746
|
const updatedBy = resolveTaskAuditUserId(requestInfo.sourceTaskId, requestInfo.agentId) ?? undefined;
|
|
@@ -27257,7 +28019,17 @@ var registerScriptConnectionsTool = (server) => {
|
|
|
27257
28019
|
};
|
|
27258
28020
|
}
|
|
27259
28021
|
const agent = getAgentById(requestInfo.agentId);
|
|
27260
|
-
|
|
28022
|
+
const decision = can({
|
|
28023
|
+
principal: {
|
|
28024
|
+
kind: "agent",
|
|
28025
|
+
agentId: requestInfo.agentId,
|
|
28026
|
+
isLead: agent?.isLead ?? false
|
|
28027
|
+
},
|
|
28028
|
+
verb: "script-connection.manage",
|
|
28029
|
+
resource: { kind: "none" },
|
|
28030
|
+
source: "mcp"
|
|
28031
|
+
});
|
|
28032
|
+
if (!decision.allow) {
|
|
27261
28033
|
return {
|
|
27262
28034
|
content: [{ type: "text", text: "Only the lead can manage script connections." }],
|
|
27263
28035
|
structuredContent: {
|
|
@@ -27983,7 +28755,17 @@ var registerSkillCreateTool = (server) => {
|
|
|
27983
28755
|
const parsed = parseSkillContent(args.content);
|
|
27984
28756
|
if (args.scope === "swarm") {
|
|
27985
28757
|
const agent = getAgentById(requestInfo.agentId);
|
|
27986
|
-
|
|
28758
|
+
const decision = can({
|
|
28759
|
+
principal: {
|
|
28760
|
+
kind: "agent",
|
|
28761
|
+
agentId: requestInfo.agentId,
|
|
28762
|
+
isLead: agent?.isLead ?? false
|
|
28763
|
+
},
|
|
28764
|
+
verb: "skill.create.swarm",
|
|
28765
|
+
resource: { kind: "none" },
|
|
28766
|
+
source: "mcp"
|
|
28767
|
+
});
|
|
28768
|
+
if (!decision.allow) {
|
|
27987
28769
|
return {
|
|
27988
28770
|
content: [
|
|
27989
28771
|
{
|
|
@@ -28073,7 +28855,17 @@ var registerSkillDeleteTool = (server) => {
|
|
|
28073
28855
|
};
|
|
28074
28856
|
}
|
|
28075
28857
|
const agent = getAgentById(requestInfo.agentId);
|
|
28076
|
-
|
|
28858
|
+
const decision = can({
|
|
28859
|
+
principal: {
|
|
28860
|
+
kind: "agent",
|
|
28861
|
+
agentId: requestInfo.agentId,
|
|
28862
|
+
isLead: agent?.isLead ?? false
|
|
28863
|
+
},
|
|
28864
|
+
verb: "skill.delete.any",
|
|
28865
|
+
resource: { kind: "owned", ownerAgentId: existing.ownerAgentId },
|
|
28866
|
+
source: "mcp"
|
|
28867
|
+
});
|
|
28868
|
+
if (!decision.allow) {
|
|
28077
28869
|
return {
|
|
28078
28870
|
content: [{ type: "text", text: "Only the owning agent or lead can delete this skill." }],
|
|
28079
28871
|
structuredContent: {
|
|
@@ -28268,7 +29060,17 @@ var registerSkillInstallTool = (server) => {
|
|
|
28268
29060
|
const targetAgentId = args.agentId ?? requestInfo.agentId;
|
|
28269
29061
|
if (targetAgentId !== requestInfo.agentId) {
|
|
28270
29062
|
const agent = getAgentById(requestInfo.agentId);
|
|
28271
|
-
|
|
29063
|
+
const decision = can({
|
|
29064
|
+
principal: {
|
|
29065
|
+
kind: "agent",
|
|
29066
|
+
agentId: requestInfo.agentId,
|
|
29067
|
+
isLead: agent?.isLead ?? false
|
|
29068
|
+
},
|
|
29069
|
+
verb: "skill.install.any",
|
|
29070
|
+
resource: { kind: "agent", agentId: targetAgentId },
|
|
29071
|
+
source: "mcp"
|
|
29072
|
+
});
|
|
29073
|
+
if (!decision.allow) {
|
|
28272
29074
|
return {
|
|
28273
29075
|
content: [{ type: "text", text: "Only leads can install skills for other agents." }],
|
|
28274
29076
|
structuredContent: {
|
|
@@ -28354,7 +29156,17 @@ var registerSkillInstallRemoteTool = (server) => {
|
|
|
28354
29156
|
};
|
|
28355
29157
|
}
|
|
28356
29158
|
const agent = getAgentById(requestInfo.agentId);
|
|
28357
|
-
|
|
29159
|
+
const decision = can({
|
|
29160
|
+
principal: {
|
|
29161
|
+
kind: "agent",
|
|
29162
|
+
agentId: requestInfo.agentId,
|
|
29163
|
+
isLead: agent?.isLead ?? false
|
|
29164
|
+
},
|
|
29165
|
+
verb: "skill.install.global",
|
|
29166
|
+
resource: { kind: "none" },
|
|
29167
|
+
source: "mcp"
|
|
29168
|
+
});
|
|
29169
|
+
if (!decision.allow) {
|
|
28358
29170
|
return {
|
|
28359
29171
|
content: [{ type: "text", text: "Only lead agents can install remote skills." }],
|
|
28360
29172
|
structuredContent: {
|
|
@@ -28778,7 +29590,17 @@ var registerSkillUninstallTool = (server) => {
|
|
|
28778
29590
|
const targetAgentId = args.agentId ?? requestInfo.agentId;
|
|
28779
29591
|
if (targetAgentId !== requestInfo.agentId) {
|
|
28780
29592
|
const agent = getAgentById(requestInfo.agentId);
|
|
28781
|
-
|
|
29593
|
+
const decision = can({
|
|
29594
|
+
principal: {
|
|
29595
|
+
kind: "agent",
|
|
29596
|
+
agentId: requestInfo.agentId,
|
|
29597
|
+
isLead: agent?.isLead ?? false
|
|
29598
|
+
},
|
|
29599
|
+
verb: "skill.uninstall.any",
|
|
29600
|
+
resource: { kind: "agent", agentId: targetAgentId },
|
|
29601
|
+
source: "mcp"
|
|
29602
|
+
});
|
|
29603
|
+
if (!decision.allow) {
|
|
28782
29604
|
return {
|
|
28783
29605
|
content: [{ type: "text", text: "Only leads can uninstall skills for other agents." }],
|
|
28784
29606
|
structuredContent: {
|
|
@@ -28853,7 +29675,17 @@ var registerSkillUpdateTool = (server) => {
|
|
|
28853
29675
|
};
|
|
28854
29676
|
}
|
|
28855
29677
|
const agent = getAgentById(requestInfo.agentId);
|
|
28856
|
-
|
|
29678
|
+
const updateDecision = can({
|
|
29679
|
+
principal: {
|
|
29680
|
+
kind: "agent",
|
|
29681
|
+
agentId: requestInfo.agentId,
|
|
29682
|
+
isLead: agent?.isLead ?? false
|
|
29683
|
+
},
|
|
29684
|
+
verb: "skill.update.any",
|
|
29685
|
+
resource: { kind: "owned", ownerAgentId: existing.ownerAgentId },
|
|
29686
|
+
source: "mcp"
|
|
29687
|
+
});
|
|
29688
|
+
if (!updateDecision.allow) {
|
|
28857
29689
|
return {
|
|
28858
29690
|
content: [
|
|
28859
29691
|
{ type: "text", text: "Only the owning agent or lead can update this skill." }
|
|
@@ -28893,7 +29725,16 @@ var registerSkillUpdateTool = (server) => {
|
|
|
28893
29725
|
updates.isEnabled = args.isEnabled;
|
|
28894
29726
|
}
|
|
28895
29727
|
if (args.scope !== undefined && args.scope !== existing.scope) {
|
|
28896
|
-
if (args.scope === "swarm" && !
|
|
29728
|
+
if (args.scope === "swarm" && !can({
|
|
29729
|
+
principal: {
|
|
29730
|
+
kind: "agent",
|
|
29731
|
+
agentId: requestInfo.agentId,
|
|
29732
|
+
isLead: agent?.isLead ?? false
|
|
29733
|
+
},
|
|
29734
|
+
verb: "skill.promote.swarm",
|
|
29735
|
+
resource: { kind: "owned", ownerAgentId: existing.ownerAgentId },
|
|
29736
|
+
source: "mcp"
|
|
29737
|
+
}).allow) {
|
|
28897
29738
|
return {
|
|
28898
29739
|
content: [
|
|
28899
29740
|
{
|
|
@@ -28973,7 +29814,13 @@ var registerSlackDeleteTool = (server) => {
|
|
|
28973
29814
|
structuredContent: { success: false, message: "Agent not found." }
|
|
28974
29815
|
};
|
|
28975
29816
|
}
|
|
28976
|
-
|
|
29817
|
+
const decision = can({
|
|
29818
|
+
principal: { kind: "agent", agentId: agent.id, isLead: agent.isLead },
|
|
29819
|
+
verb: "integration.slack.delete",
|
|
29820
|
+
resource: { kind: "none" },
|
|
29821
|
+
source: "mcp"
|
|
29822
|
+
});
|
|
29823
|
+
if (!decision.allow) {
|
|
28977
29824
|
return {
|
|
28978
29825
|
content: [{ type: "text", text: "Deleting Slack messages requires lead privileges." }],
|
|
28979
29826
|
structuredContent: {
|
|
@@ -29497,7 +30344,13 @@ var registerSlackPostTool = (server) => {
|
|
|
29497
30344
|
structuredContent: { success: false, message: "Agent not found." }
|
|
29498
30345
|
};
|
|
29499
30346
|
}
|
|
29500
|
-
|
|
30347
|
+
const decision = can({
|
|
30348
|
+
principal: { kind: "agent", agentId: agent.id, isLead: agent.isLead },
|
|
30349
|
+
verb: "integration.slack.post",
|
|
30350
|
+
resource: { kind: "none" },
|
|
30351
|
+
source: "mcp"
|
|
30352
|
+
});
|
|
30353
|
+
if (!decision.allow) {
|
|
29501
30354
|
return {
|
|
29502
30355
|
content: [{ type: "text", text: "Posting to Slack channels requires lead privileges." }],
|
|
29503
30356
|
structuredContent: {
|
|
@@ -29657,7 +30510,13 @@ var registerSlackReadTool = (server) => {
|
|
|
29657
30510
|
slackChannelId = task.slackChannelId;
|
|
29658
30511
|
slackThreadTs = task.slackThreadTs;
|
|
29659
30512
|
} else if (channelId) {
|
|
29660
|
-
|
|
30513
|
+
const decision = can({
|
|
30514
|
+
principal: { kind: "agent", agentId: agent.id, isLead: agent.isLead },
|
|
30515
|
+
verb: "integration.slack.read",
|
|
30516
|
+
resource: { kind: "none" },
|
|
30517
|
+
source: "mcp"
|
|
30518
|
+
});
|
|
30519
|
+
if (!decision.allow) {
|
|
29661
30520
|
return {
|
|
29662
30521
|
content: [{ type: "text", text: "Direct channel access requires lead privileges." }],
|
|
29663
30522
|
structuredContent: {
|
|
@@ -29982,7 +30841,13 @@ var registerSlackStartThreadTool = (server) => {
|
|
|
29982
30841
|
structuredContent: { success: false, message: "Agent not found." }
|
|
29983
30842
|
};
|
|
29984
30843
|
}
|
|
29985
|
-
|
|
30844
|
+
const decision = can({
|
|
30845
|
+
principal: { kind: "agent", agentId: agent.id, isLead: agent.isLead },
|
|
30846
|
+
verb: "integration.slack.thread.start",
|
|
30847
|
+
resource: { kind: "none" },
|
|
30848
|
+
source: "mcp"
|
|
30849
|
+
});
|
|
30850
|
+
if (!decision.allow) {
|
|
29986
30851
|
return {
|
|
29987
30852
|
content: [{ type: "text", text: "Posting to Slack channels requires lead privileges." }],
|
|
29988
30853
|
structuredContent: {
|
|
@@ -30089,7 +30954,13 @@ var registerSlackUpdateTool = (server) => {
|
|
|
30089
30954
|
structuredContent: { success: false, message: "Agent not found." }
|
|
30090
30955
|
};
|
|
30091
30956
|
}
|
|
30092
|
-
|
|
30957
|
+
const decision = can({
|
|
30958
|
+
principal: { kind: "agent", agentId: agent.id, isLead: agent.isLead },
|
|
30959
|
+
verb: "integration.slack.update",
|
|
30960
|
+
resource: { kind: "none" },
|
|
30961
|
+
source: "mcp"
|
|
30962
|
+
});
|
|
30963
|
+
if (!decision.allow) {
|
|
30093
30964
|
return {
|
|
30094
30965
|
content: [{ type: "text", text: "Editing Slack messages requires lead privileges." }],
|
|
30095
30966
|
structuredContent: {
|
|
@@ -30282,7 +31153,13 @@ var registerSlackUploadFileTool = (server) => {
|
|
|
30282
31153
|
slackChannelId = task.slackChannelId;
|
|
30283
31154
|
slackThreadTs = resolveTaskUploadThreadTs(task);
|
|
30284
31155
|
} else if (channelId) {
|
|
30285
|
-
|
|
31156
|
+
const decision = can({
|
|
31157
|
+
principal: { kind: "agent", agentId: agent.id, isLead: agent.isLead },
|
|
31158
|
+
verb: "integration.slack.upload",
|
|
31159
|
+
resource: { kind: "none" },
|
|
31160
|
+
source: "mcp"
|
|
31161
|
+
});
|
|
31162
|
+
if (!decision.allow) {
|
|
30286
31163
|
return {
|
|
30287
31164
|
content: [{ type: "text", text: "Direct channel access requires lead privileges." }],
|
|
30288
31165
|
structuredContent: {
|
|
@@ -33430,7 +34307,7 @@ async function notifySlack(text) {
|
|
|
33430
34307
|
return;
|
|
33431
34308
|
}
|
|
33432
34309
|
try {
|
|
33433
|
-
const { getSlackApp: getSlackApp2 } = await import("./app-
|
|
34310
|
+
const { getSlackApp: getSlackApp2 } = await import("./app-es4nzc71.js");
|
|
33434
34311
|
const app = getSlackApp2();
|
|
33435
34312
|
if (!app) {
|
|
33436
34313
|
console.warn("[Jira webhook keepalive] Slack not available, cannot send notification");
|
|
@@ -33499,7 +34376,7 @@ async function deleteJiraWebhook(webhookId) {
|
|
|
33499
34376
|
console.log(`[Jira webhook keepalive] Deleted webhook id=${webhookId}`);
|
|
33500
34377
|
}
|
|
33501
34378
|
async function overwriteWebhookIds(next) {
|
|
33502
|
-
const { getDb: getDb2 } = await import("./db-
|
|
34379
|
+
const { getDb: getDb2 } = await import("./db-bbgahh4z.js");
|
|
33503
34380
|
const db = getDb2();
|
|
33504
34381
|
const txn = db.transaction(() => {
|
|
33505
34382
|
const row = db.query("SELECT metadata FROM oauth_apps WHERE provider = 'jira'").get();
|
|
@@ -107948,6 +108825,28 @@ var registerDeleteConfigTool = (server) => {
|
|
|
107948
108825
|
}
|
|
107949
108826
|
};
|
|
107950
108827
|
}
|
|
108828
|
+
const agent = getAgentById(requestInfo.agentId);
|
|
108829
|
+
const decision = can({
|
|
108830
|
+
principal: {
|
|
108831
|
+
kind: "agent",
|
|
108832
|
+
agentId: requestInfo.agentId,
|
|
108833
|
+
isLead: agent?.isLead ?? false
|
|
108834
|
+
},
|
|
108835
|
+
verb: "config.delete.any",
|
|
108836
|
+
resource: { kind: "none" },
|
|
108837
|
+
source: "mcp"
|
|
108838
|
+
});
|
|
108839
|
+
if (!decision.allow) {
|
|
108840
|
+
const message = "Deleting swarm config requires the lead agent.";
|
|
108841
|
+
return {
|
|
108842
|
+
content: [{ type: "text", text: message }],
|
|
108843
|
+
structuredContent: {
|
|
108844
|
+
yourAgentId: requestInfo.agentId,
|
|
108845
|
+
success: false,
|
|
108846
|
+
message
|
|
108847
|
+
}
|
|
108848
|
+
};
|
|
108849
|
+
}
|
|
107951
108850
|
try {
|
|
107952
108851
|
const existing = getSwarmConfigLookupById(id);
|
|
107953
108852
|
if (!existing) {
|
|
@@ -108040,8 +108939,27 @@ var registerGetConfigTool = (server) => {
|
|
|
108040
108939
|
if (key) {
|
|
108041
108940
|
configs = configs.filter((c) => c.key === key);
|
|
108042
108941
|
}
|
|
108043
|
-
|
|
108942
|
+
let effectiveIncludeSecrets = includeSecrets ?? false;
|
|
108943
|
+
let secretsNote = "";
|
|
108044
108944
|
if (includeSecrets) {
|
|
108945
|
+
const agent = getAgentById(requestInfo.agentId);
|
|
108946
|
+
const decision = can({
|
|
108947
|
+
principal: {
|
|
108948
|
+
kind: "agent",
|
|
108949
|
+
agentId: requestInfo.agentId,
|
|
108950
|
+
isLead: agent?.isLead ?? false
|
|
108951
|
+
},
|
|
108952
|
+
verb: "config.read.secrets",
|
|
108953
|
+
resource: { kind: "none" },
|
|
108954
|
+
source: "mcp"
|
|
108955
|
+
});
|
|
108956
|
+
if (!decision.allow) {
|
|
108957
|
+
effectiveIncludeSecrets = false;
|
|
108958
|
+
secretsNote = " (secret values masked: reading unmasked secrets requires the lead agent)";
|
|
108959
|
+
}
|
|
108960
|
+
}
|
|
108961
|
+
const result = effectiveIncludeSecrets ? configs : maskSecrets(configs);
|
|
108962
|
+
if (effectiveIncludeSecrets) {
|
|
108045
108963
|
for (const c of result) {
|
|
108046
108964
|
if (c.isSecret && c.value) {
|
|
108047
108965
|
registerVolatileSecret(c.value, `config:${c.key}`);
|
|
@@ -108049,7 +108967,7 @@ var registerGetConfigTool = (server) => {
|
|
|
108049
108967
|
}
|
|
108050
108968
|
}
|
|
108051
108969
|
const count = result.length;
|
|
108052
|
-
const configList = count === 0 ? "No configs found." : result.map((c) => `- ${c.key}=${c.isSecret && !
|
|
108970
|
+
const configList = count === 0 ? "No configs found." : result.map((c) => `- ${c.key}=${c.isSecret && !effectiveIncludeSecrets ? "********" : c.value} (scope: ${c.scope}${c.scopeId ? `, scopeId: ${c.scopeId}` : ""})`).join(`
|
|
108053
108971
|
`);
|
|
108054
108972
|
return {
|
|
108055
108973
|
content: [
|
|
@@ -108057,13 +108975,13 @@ var registerGetConfigTool = (server) => {
|
|
|
108057
108975
|
type: "text",
|
|
108058
108976
|
text: count === 0 ? "No configs found." : `Found ${count} config(s):
|
|
108059
108977
|
|
|
108060
|
-
${configList}`
|
|
108978
|
+
${configList}${secretsNote}`
|
|
108061
108979
|
}
|
|
108062
108980
|
],
|
|
108063
108981
|
structuredContent: {
|
|
108064
108982
|
yourAgentId: requestInfo.agentId,
|
|
108065
108983
|
success: true,
|
|
108066
|
-
message: count === 0 ? "No configs found." : `Found ${count} config(s)
|
|
108984
|
+
message: count === 0 ? "No configs found." : `Found ${count} config(s).${secretsNote}`,
|
|
108067
108985
|
configs: result,
|
|
108068
108986
|
count
|
|
108069
108987
|
}
|
|
@@ -108124,8 +109042,27 @@ var registerListConfigTool = (server) => {
|
|
|
108124
109042
|
scopeId,
|
|
108125
109043
|
key
|
|
108126
109044
|
});
|
|
108127
|
-
|
|
109045
|
+
let effectiveIncludeSecrets = includeSecrets ?? false;
|
|
109046
|
+
let secretsNote = "";
|
|
108128
109047
|
if (includeSecrets) {
|
|
109048
|
+
const agent = getAgentById(requestInfo.agentId);
|
|
109049
|
+
const decision = can({
|
|
109050
|
+
principal: {
|
|
109051
|
+
kind: "agent",
|
|
109052
|
+
agentId: requestInfo.agentId,
|
|
109053
|
+
isLead: agent?.isLead ?? false
|
|
109054
|
+
},
|
|
109055
|
+
verb: "config.read.secrets",
|
|
109056
|
+
resource: { kind: "none" },
|
|
109057
|
+
source: "mcp"
|
|
109058
|
+
});
|
|
109059
|
+
if (!decision.allow) {
|
|
109060
|
+
effectiveIncludeSecrets = false;
|
|
109061
|
+
secretsNote = " (secret values masked: reading unmasked secrets requires the lead agent)";
|
|
109062
|
+
}
|
|
109063
|
+
}
|
|
109064
|
+
const result = effectiveIncludeSecrets ? configs : maskSecrets(configs);
|
|
109065
|
+
if (effectiveIncludeSecrets) {
|
|
108129
109066
|
for (const c of result) {
|
|
108130
109067
|
if (c.isSecret && c.value) {
|
|
108131
109068
|
registerVolatileSecret(c.value, `config:${c.key}`);
|
|
@@ -108133,7 +109070,7 @@ var registerListConfigTool = (server) => {
|
|
|
108133
109070
|
}
|
|
108134
109071
|
}
|
|
108135
109072
|
const count = result.length;
|
|
108136
|
-
const configList = count === 0 ? "No configs found." : result.map((c) => `- [${c.scope}${c.scopeId ? `:${c.scopeId}` : ""}] ${c.key}=${c.isSecret && !
|
|
109073
|
+
const configList = count === 0 ? "No configs found." : result.map((c) => `- [${c.scope}${c.scopeId ? `:${c.scopeId}` : ""}] ${c.key}=${c.isSecret && !effectiveIncludeSecrets ? "********" : c.value}${c.description ? ` — ${c.description}` : ""}`).join(`
|
|
108137
109074
|
`);
|
|
108138
109075
|
return {
|
|
108139
109076
|
content: [
|
|
@@ -108141,13 +109078,13 @@ var registerListConfigTool = (server) => {
|
|
|
108141
109078
|
type: "text",
|
|
108142
109079
|
text: count === 0 ? "No configs found." : `Found ${count} config(s):
|
|
108143
109080
|
|
|
108144
|
-
${configList}`
|
|
109081
|
+
${configList}${secretsNote}`
|
|
108145
109082
|
}
|
|
108146
109083
|
],
|
|
108147
109084
|
structuredContent: {
|
|
108148
109085
|
yourAgentId: requestInfo.agentId,
|
|
108149
109086
|
success: true,
|
|
108150
|
-
message: count === 0 ? "No configs found." : `Found ${count} config(s)
|
|
109087
|
+
message: count === 0 ? "No configs found." : `Found ${count} config(s).${secretsNote}`,
|
|
108151
109088
|
configs: result,
|
|
108152
109089
|
count
|
|
108153
109090
|
}
|
|
@@ -108231,7 +109168,17 @@ var registerSetConfigTool = (server) => {
|
|
|
108231
109168
|
}
|
|
108232
109169
|
if (key.toUpperCase() === CREDENTIAL_BINDINGS_CONFIG_KEY) {
|
|
108233
109170
|
const agent = getAgentById(requestInfo.agentId);
|
|
108234
|
-
|
|
109171
|
+
const decision = can({
|
|
109172
|
+
principal: {
|
|
109173
|
+
kind: "agent",
|
|
109174
|
+
agentId: requestInfo.agentId,
|
|
109175
|
+
isLead: agent?.isLead ?? false
|
|
109176
|
+
},
|
|
109177
|
+
verb: "config.credential-bindings.write",
|
|
109178
|
+
resource: { kind: "none" },
|
|
109179
|
+
source: "mcp"
|
|
109180
|
+
});
|
|
109181
|
+
if (!decision.allow) {
|
|
108235
109182
|
const message = "Only the lead can manage SCRIPT_CREDENTIAL_BINDINGS. Use the credential-bindings tool.";
|
|
108236
109183
|
return {
|
|
108237
109184
|
content: [{ type: "text", text: message }],
|
|
@@ -108242,6 +109189,29 @@ var registerSetConfigTool = (server) => {
|
|
|
108242
109189
|
}
|
|
108243
109190
|
};
|
|
108244
109191
|
}
|
|
109192
|
+
} else {
|
|
109193
|
+
const agent = getAgentById(requestInfo.agentId);
|
|
109194
|
+
const decision = can({
|
|
109195
|
+
principal: {
|
|
109196
|
+
kind: "agent",
|
|
109197
|
+
agentId: requestInfo.agentId,
|
|
109198
|
+
isLead: agent?.isLead ?? false
|
|
109199
|
+
},
|
|
109200
|
+
verb: "config.write.any",
|
|
109201
|
+
resource: { kind: "none" },
|
|
109202
|
+
source: "mcp"
|
|
109203
|
+
});
|
|
109204
|
+
if (!decision.allow) {
|
|
109205
|
+
const message = "Writing swarm config requires the lead agent.";
|
|
109206
|
+
return {
|
|
109207
|
+
content: [{ type: "text", text: message }],
|
|
109208
|
+
structuredContent: {
|
|
109209
|
+
yourAgentId: requestInfo.agentId,
|
|
109210
|
+
success: false,
|
|
109211
|
+
message
|
|
109212
|
+
}
|
|
109213
|
+
};
|
|
109214
|
+
}
|
|
108245
109215
|
}
|
|
108246
109216
|
const validationError = validateConfigValue(key, value);
|
|
108247
109217
|
if (validationError) {
|
|
@@ -108595,7 +109565,7 @@ async function taskActionHandler(ctx, input) {
|
|
|
108595
109565
|
if (!existingTask) {
|
|
108596
109566
|
return { success: false, message: `Task "${taskId}" not found.` };
|
|
108597
109567
|
}
|
|
108598
|
-
const ownershipError = assertOwnsTask(ctx, existingTask);
|
|
109568
|
+
const ownershipError = assertOwnsTask(ctx, existingTask, "task.action.own");
|
|
108599
109569
|
if (ownershipError)
|
|
108600
109570
|
return ownershipError;
|
|
108601
109571
|
if (action === "to_backlog") {
|
|
@@ -109331,7 +110301,13 @@ var registerUpdateProfileTool = (server) => {
|
|
|
109331
110301
|
}
|
|
109332
110302
|
};
|
|
109333
110303
|
}
|
|
109334
|
-
|
|
110304
|
+
const decision = can({
|
|
110305
|
+
principal: { kind: "agent", agentId: callingAgent.id, isLead: callingAgent.isLead },
|
|
110306
|
+
verb: "agent.profile.update.any",
|
|
110307
|
+
resource: { kind: "agent", agentId: targetAgentId },
|
|
110308
|
+
source: "mcp"
|
|
110309
|
+
});
|
|
110310
|
+
if (!decision.allow) {
|
|
109335
110311
|
return {
|
|
109336
110312
|
content: [
|
|
109337
110313
|
{
|
|
@@ -110017,6 +110993,7 @@ var registerListWorkflowRunsTool = (server) => {
|
|
|
110017
110993
|
// src/tools/workflows/list-workflows.ts
|
|
110018
110994
|
init_zod();
|
|
110019
110995
|
init_db();
|
|
110996
|
+
init_types();
|
|
110020
110997
|
var registerListWorkflowsTool = (server) => {
|
|
110021
110998
|
createToolRegistrar(server)("list-workflows", {
|
|
110022
110999
|
title: "List Workflows",
|
|
@@ -110024,6 +111001,8 @@ var registerListWorkflowsTool = (server) => {
|
|
|
110024
111001
|
description: "List all automation workflows, optionally filtered by enabled status. Returns SLIM rows WITHOUT the full `definition` (DAG) — each row carries a `nodeCount` instead. To inspect or patch a workflow's nodes/triggers, call `get-workflow` by id, or pass `includeFull: true` here.",
|
|
110025
111002
|
inputSchema: exports_external.object({
|
|
110026
111003
|
enabled: exports_external.boolean().optional().describe("Filter by enabled status (omit to return all)"),
|
|
111004
|
+
consecutiveErrorsMin: exports_external.number().int().min(0).optional().describe("Only return workflows with at least this many latest consecutive failed runs."),
|
|
111005
|
+
lastRunStatus: WorkflowRunStatusSchema.optional().describe("Only return workflows whose latest run has this status."),
|
|
110027
111006
|
includeFull: exports_external.boolean().optional().describe("Return the full workflow `definition` + trigger config instead of slim rows. Default false — prefer `get-workflow` to fetch a single workflow in full.")
|
|
110028
111007
|
}),
|
|
110029
111008
|
outputSchema: exports_external.object({
|
|
@@ -110031,9 +111010,9 @@ var registerListWorkflowsTool = (server) => {
|
|
|
110031
111010
|
message: exports_external.string(),
|
|
110032
111011
|
workflows: exports_external.array(exports_external.unknown())
|
|
110033
111012
|
})
|
|
110034
|
-
}, async ({ enabled: enabled2, includeFull }) => {
|
|
111013
|
+
}, async ({ enabled: enabled2, consecutiveErrorsMin, lastRunStatus, includeFull }) => {
|
|
110035
111014
|
try {
|
|
110036
|
-
const filters =
|
|
111015
|
+
const filters = { enabled: enabled2, consecutiveErrorsMin, lastRunStatus };
|
|
110037
111016
|
const workflows = includeFull ? listWorkflows(filters) : listWorkflows(filters, { slim: true });
|
|
110038
111017
|
return {
|
|
110039
111018
|
content: [{ type: "text", text: `Found ${workflows.length} workflow(s).` }],
|
|
@@ -110583,6 +111562,7 @@ function createServer() {
|
|
|
110583
111562
|
registerListSchedulesTool(server);
|
|
110584
111563
|
registerCreateScheduleTool(server);
|
|
110585
111564
|
registerUpdateScheduleTool(server);
|
|
111565
|
+
registerPatchScheduleTool(server);
|
|
110586
111566
|
registerDeleteScheduleTool(server);
|
|
110587
111567
|
registerRunScheduleNowTool(server);
|
|
110588
111568
|
}
|
|
@@ -110788,4 +111768,4 @@ function writeSkillsToFilesystem(entries, harnessType = "all", home) {
|
|
|
110788
111768
|
return { synced, removed, errors };
|
|
110789
111769
|
}
|
|
110790
111770
|
|
|
110791
|
-
export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, userCtx, isPollTracingEnabled, initOtel, withSpan, startSpan, withSpanContext, withRemoteContext, injectTraceContext, recordSessionCost, createToolRegistrar, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, setCorsHeaders, parseQueryParams, getPathSegments, safeRequestUrlForLog, agentWithCapacity, parseBody, BODY_TOO_LARGE, enforceContentLengthCap, json, jsonError, triggerSchemaErrorResponse, deriveApiBaseUrl, httpServerSemconvAttributes, describeRequestRoute, route, assertSelectOnlyQuery, executeReadOnlyQuery, handleDbQuery, snapshotMetric, snapshotPage, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, storeLinks, refreshLinks, canReadMemory, getLinksForMemory, recordRetrievals, expandCandidatesWithGraph, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, resolveHttpAuditUserId, createEvent, createEventsBatch, getEventCountsFiltered, getEventsFiltered, mergeScheduleTiming, validateRecurringTiming, sendTaskOutputSchema, sendTaskHandler, parseSkillContent, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, isInboxAllowed, isSenderAllowed, handleMessageReceived, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, canClaim, emitBudgetRefusalSideEffects, taskActionInputSchema, taskActionOutputSchema, taskActionHandler, hasCapability, getEnabledCapabilities, createServer, writeSkillsToFilesystem };
|
|
111771
|
+
export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, setAuditSink, clearAuditSink, can, userCtx, isPollTracingEnabled, initOtel, withSpan, startSpan, withSpanContext, withRemoteContext, injectTraceContext, recordSessionCost, createToolRegistrar, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, setCorsHeaders, parseQueryParams, getPathSegments, safeRequestUrlForLog, agentWithCapacity, parseBody, BODY_TOO_LARGE, enforceContentLengthCap, json, jsonError, triggerSchemaErrorResponse, deriveApiBaseUrl, httpServerSemconvAttributes, describeRequestRoute, route, assertSelectOnlyQuery, executeReadOnlyQuery, handleDbQuery, snapshotMetric, snapshotPage, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, storeLinks, refreshLinks, canReadMemory, getLinksForMemory, recordRetrievals, expandCandidatesWithGraph, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, resolveHttpAuditUserId, createEvent, createEventsBatch, getEventCountsFiltered, getEventsFiltered, mergeScheduleTiming, validateRecurringTiming, sendTaskOutputSchema, sendTaskHandler, parseSkillContent, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, isInboxAllowed, isSenderAllowed, handleMessageReceived, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, canClaim, emitBudgetRefusalSideEffects, taskActionInputSchema, taskActionOutputSchema, taskActionHandler, hasCapability, getEnabledCapabilities, createServer, writeSkillsToFilesystem };
|