@ekanos/cli 0.15.0 → 0.17.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/README.md +103 -8
- package/dist/auth/ekanos-api.d.ts +23 -0
- package/dist/auth/ekanos-api.js +33 -6
- package/dist/auth/ekanos-api.js.map +1 -1
- package/dist/commands/add.d.ts +2 -0
- package/dist/commands/add.js +118 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/agents.js +3 -2
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/apps.d.ts +11 -3
- package/dist/commands/apps.js +86 -28
- package/dist/commands/apps.js.map +1 -1
- package/dist/commands/audiences.d.ts +31 -0
- package/dist/commands/audiences.js +239 -0
- package/dist/commands/audiences.js.map +1 -0
- package/dist/commands/build.d.ts +2 -0
- package/dist/commands/build.js +41 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/catalog.d.ts +4 -2
- package/dist/commands/catalog.js +166 -35
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/check.d.ts +2 -0
- package/dist/commands/check.js +43 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/codegen.d.ts +2 -0
- package/dist/commands/codegen.js +49 -0
- package/dist/commands/codegen.js.map +1 -0
- package/dist/commands/contract.d.ts +52 -0
- package/dist/commands/contract.js +300 -0
- package/dist/commands/contract.js.map +1 -0
- package/dist/commands/dev.d.ts +7 -0
- package/dist/commands/dev.js +186 -12
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/index-experience.d.ts +31 -0
- package/dist/commands/index-experience.js +21 -0
- package/dist/commands/index-experience.js.map +1 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.js +12 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +17 -0
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/new.d.ts +2 -0
- package/dist/commands/new.js +39 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/publish.d.ts +59 -0
- package/dist/commands/publish.js +118 -65
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/runs.d.ts +7 -3
- package/dist/commands/runs.js +21 -5
- package/dist/commands/runs.js.map +1 -1
- package/dist/commands/scope-notice.d.ts +13 -0
- package/dist/commands/scope-notice.js +12 -4
- package/dist/commands/scope-notice.js.map +1 -1
- package/dist/commands/sources-roles.d.ts +5 -0
- package/dist/commands/sources-roles.js +235 -0
- package/dist/commands/sources-roles.js.map +1 -0
- package/dist/commands/sources.d.ts +5 -0
- package/dist/commands/sources.js +8 -1
- package/dist/commands/sources.js.map +1 -1
- package/dist/commands/sync.d.ts +2 -0
- package/dist/commands/sync.js +150 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/team-agent-readiness.d.ts +18 -2
- package/dist/commands/team-agent-readiness.js +39 -39
- package/dist/commands/team-agent-readiness.js.map +1 -1
- package/dist/commands/team-agents-agents.d.ts +5 -2
- package/dist/commands/team-agents-agents.js +152 -15
- package/dist/commands/team-agents-agents.js.map +1 -1
- package/dist/commands/team-agents-define.d.ts +31 -0
- package/dist/commands/team-agents-define.js +176 -0
- package/dist/commands/team-agents-define.js.map +1 -0
- package/dist/commands/team-agents-mcp.js +112 -10
- package/dist/commands/team-agents-mcp.js.map +1 -1
- package/dist/commands/team-agents-triggers.d.ts +1 -1
- package/dist/commands/team-agents-triggers.js +137 -5
- package/dist/commands/team-agents-triggers.js.map +1 -1
- package/dist/commands/team-agents.d.ts +4 -1
- package/dist/commands/team-agents.js +17 -4
- package/dist/commands/team-agents.js.map +1 -1
- package/dist/commands/team-llm-key.d.ts +14 -0
- package/dist/commands/team-llm-key.js +122 -0
- package/dist/commands/team-llm-key.js.map +1 -0
- package/dist/commands/teams-audience.d.ts +12 -0
- package/dist/commands/teams-audience.js +144 -0
- package/dist/commands/teams-audience.js.map +1 -0
- package/dist/commands/teams-connect.js +123 -31
- package/dist/commands/teams-connect.js.map +1 -1
- package/dist/commands/teams-lifecycle.d.ts +90 -0
- package/dist/commands/teams-lifecycle.js +457 -0
- package/dist/commands/teams-lifecycle.js.map +1 -0
- package/dist/commands/teams-onboard.d.ts +14 -0
- package/dist/commands/teams-onboard.js +62 -13
- package/dist/commands/teams-onboard.js.map +1 -1
- package/dist/commands/teams-overview.js +6 -2
- package/dist/commands/teams-overview.js.map +1 -1
- package/dist/commands/teams-scope.js +4 -0
- package/dist/commands/teams-scope.js.map +1 -1
- package/dist/commands/teams.d.ts +25 -5
- package/dist/commands/teams.js +106 -39
- package/dist/commands/teams.js.map +1 -1
- package/dist/commands/workflows.d.ts +37 -0
- package/dist/commands/workflows.js +589 -0
- package/dist/commands/workflows.js.map +1 -0
- package/dist/compatibility.d.ts +10 -1
- package/dist/compatibility.js +10 -1
- package/dist/compatibility.js.map +1 -1
- package/dist/connect-fields.d.ts +22 -0
- package/dist/connect-fields.js +115 -0
- package/dist/connect-fields.js.map +1 -0
- package/dist/context.d.ts +12 -0
- package/dist/context.js +32 -9
- package/dist/context.js.map +1 -1
- package/dist/dev-experience.d.ts +125 -0
- package/dist/dev-experience.js +128 -0
- package/dist/dev-experience.js.map +1 -0
- package/dist/experience/boundary.d.ts +12 -0
- package/dist/experience/boundary.js +260 -0
- package/dist/experience/boundary.js.map +1 -0
- package/dist/experience/build.d.ts +16 -0
- package/dist/experience/build.js +90 -0
- package/dist/experience/build.js.map +1 -0
- package/dist/experience/checks.d.ts +29 -0
- package/dist/experience/checks.js +133 -0
- package/dist/experience/checks.js.map +1 -0
- package/dist/experience/contract-sources.d.ts +36 -0
- package/dist/experience/contract-sources.js +111 -0
- package/dist/experience/contract-sources.js.map +1 -0
- package/dist/experience/definition-checks.d.ts +26 -0
- package/dist/experience/definition-checks.js +201 -0
- package/dist/experience/definition-checks.js.map +1 -0
- package/dist/experience/definition-shape.d.ts +60 -0
- package/dist/experience/definition-shape.js +2 -0
- package/dist/experience/definition-shape.js.map +1 -0
- package/dist/experience/init.d.ts +10 -0
- package/dist/experience/init.js +64 -0
- package/dist/experience/init.js.map +1 -0
- package/dist/experience/integrations-codegen.d.ts +17 -0
- package/dist/experience/integrations-codegen.js +51 -0
- package/dist/experience/integrations-codegen.js.map +1 -0
- package/dist/experience/json-schema-to-ts.d.ts +1 -0
- package/dist/experience/json-schema-to-ts.js +90 -0
- package/dist/experience/json-schema-to-ts.js.map +1 -0
- package/dist/experience/load-experience.d.ts +23 -0
- package/dist/experience/load-experience.js +115 -0
- package/dist/experience/load-experience.js.map +1 -0
- package/dist/experience/overrides.d.ts +8 -0
- package/dist/experience/overrides.js +21 -0
- package/dist/experience/overrides.js.map +1 -0
- package/dist/experience/pin-integration.d.ts +8 -0
- package/dist/experience/pin-integration.js +17 -0
- package/dist/experience/pin-integration.js.map +1 -0
- package/dist/experience/pin-ops.d.ts +12 -0
- package/dist/experience/pin-ops.js +36 -0
- package/dist/experience/pin-ops.js.map +1 -0
- package/dist/experience/pins.d.ts +35 -0
- package/dist/experience/pins.js +91 -0
- package/dist/experience/pins.js.map +1 -0
- package/dist/experience/project.d.ts +52 -0
- package/dist/experience/project.js +149 -0
- package/dist/experience/project.js.map +1 -0
- package/dist/experience/publish.d.ts +51 -0
- package/dist/experience/publish.js +144 -0
- package/dist/experience/publish.js.map +1 -0
- package/dist/experience/regenerate.d.ts +10 -0
- package/dist/experience/regenerate.js +33 -0
- package/dist/experience/regenerate.js.map +1 -0
- package/dist/experience/report.d.ts +9 -0
- package/dist/experience/report.js +23 -0
- package/dist/experience/report.js.map +1 -0
- package/dist/harness-scaffold.d.ts +52 -18
- package/dist/harness-scaffold.js +189 -9
- package/dist/harness-scaffold.js.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.js +494 -127
- package/dist/index.js.map +1 -1
- package/dist/invocation.d.ts +31 -0
- package/dist/invocation.js +58 -0
- package/dist/invocation.js.map +1 -0
- package/dist/project-checks.d.ts +12 -0
- package/dist/project-checks.js +46 -0
- package/dist/project-checks.js.map +1 -1
- package/dist/project.d.ts +14 -0
- package/dist/project.js +10 -0
- package/dist/project.js.map +1 -1
- package/dist/repo/publish.d.ts +42 -0
- package/dist/repo/publish.js +225 -0
- package/dist/repo/publish.js.map +1 -0
- package/dist/repo/scaffold.d.ts +30 -0
- package/dist/repo/scaffold.js +165 -0
- package/dist/repo/scaffold.js.map +1 -0
- package/dist/runs-api.js +8 -3
- package/dist/runs-api.js.map +1 -1
- package/dist/safe-fs.d.ts +18 -0
- package/dist/safe-fs.js +57 -0
- package/dist/safe-fs.js.map +1 -1
- package/dist/secret-form.d.ts +48 -0
- package/dist/secret-form.js +212 -0
- package/dist/secret-form.js.map +1 -0
- package/dist/secret-input.d.ts +96 -0
- package/dist/secret-input.js +299 -0
- package/dist/secret-input.js.map +1 -0
- package/dist/team-connect-api.d.ts +78 -3
- package/dist/team-connect-api.js +17 -2
- package/dist/team-connect-api.js.map +1 -1
- package/dist/team-lifecycle-api.d.ts +435 -0
- package/dist/team-lifecycle-api.js +301 -0
- package/dist/team-lifecycle-api.js.map +1 -0
- package/dist/teams-api.d.ts +49 -1
- package/dist/teams-api.js +149 -27
- package/dist/teams-api.js.map +1 -1
- package/dist/unknown-command.d.ts +18 -0
- package/dist/unknown-command.js +50 -0
- package/dist/unknown-command.js.map +1 -0
- package/dist/validate-findings.js +2 -1
- package/dist/validate-findings.js.map +1 -1
- package/dist/workflows-api.d.ts +69 -0
- package/dist/workflows-api.js +182 -0
- package/dist/workflows-api.js.map +1 -0
- package/package.json +3 -3
- package/templates/AGENTS.md.tmpl +6 -4
- package/templates/claude-skill.md.tmpl +4 -1
- package/templates/ekanos.json.tmpl +1 -0
- package/templates/experience/AGENTS.md.tmpl +22 -0
- package/templates/experience/ekanos.json.tmpl +7 -0
- package/templates/experience/ekanos.lock.json.tmpl +4 -0
- package/templates/experience/eslint.config.mjs.tmpl +25 -0
- package/templates/experience/gitignore.tmpl +17 -0
- package/templates/experience/package.json.tmpl +41 -0
- package/templates/experience/src/.ekanos/integrations.d.ts.tmpl +3 -0
- package/templates/experience/src/experience.ts.tmpl +30 -0
- package/templates/experience/src/widgets/hello-widget.tsx.tmpl +40 -0
- package/templates/experience/tsconfig.json.tmpl +20 -0
- package/templates/harness/app/%5F%5Fekanos/api/[...path]/route.ts.tmpl +9 -0
- package/templates/harness/app/[slug]/activation/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/tile/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/triggers/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/widgets/[widgetId]/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/widgets/page.tsx.tmpl +1 -1
- package/templates/harness/app/experience/layout.tsx.tmpl +17 -0
- package/templates/harness/app/experience/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/pages/[id]/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/review-queue/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/runs/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/widgets/[id]/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/widgets/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/workflows/[id]/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/workflows/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/connect/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/events/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/health/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/operations/[kind]/[name]/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/operations/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/activation/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/layout.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/tile/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/triggers/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/widgets/[widgetId]/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/widgets/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/runs/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/layout.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/page.tsx.tmpl +1 -0
- package/templates/harness/app/page.experience.tsx.tmpl +5 -0
- package/templates/harness/repo/app/%5F%5Fekanos/api/[...path]/route.ts.tmpl +11 -0
- package/templates/harness/repo/app/(repo)/connections/page.tsx.tmpl +1 -0
- package/templates/harness/repo/app/(repo)/layout.tsx.tmpl +1 -0
- package/templates/harness/repo/app/(repo)/page.tsx.tmpl +1 -0
- package/templates/harness/repo/app/experiences/[name]/connect/page.tsx.tmpl +1 -0
- package/templates/harness/repo/app/experiences/[name]/layout.tsx.tmpl +9 -0
- package/templates/harness/repo/app/experiences/page.tsx.tmpl +5 -0
- package/templates/harness/repo/app/harness-shell.tsx.tmpl +9 -0
- package/templates/harness/repo/app/integrations/[slug]/layout.tsx.tmpl +1 -0
- package/templates/harness/repo/app/integrations/page.tsx.tmpl +5 -0
- package/templates/harness/repo/app/repo-experiences.ts.tmpl +5 -0
- package/templates/harness/styles/globals.css.tmpl +15 -1
- package/templates/package.json.tmpl +4 -4
- package/templates/skills/build-agent/SKILL.md +43 -10
- package/templates/skills/build-agent/references/agent-json.md +4 -1
- package/templates/skills/build-agent/references/app-setup.md +14 -7
- package/templates/skills/build-agent/references/rollout.md +26 -2
- package/templates/skills/build-agent/references/set-up-an-integration.md +46 -29
- package/templates/skills/build-integration/references/widget-design.md +1 -1
- package/templates/skills/ekanos-platform/SKILL.md +66 -14
- package/templates/skills/polish-widgets/references/patterns.md +3 -3
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import { TeamMcpListSchema, TeamMcpRemoveResultSchema, TeamMcpStatusSchema, } from '@ekanos/integration-schema';
|
|
2
2
|
import { invalidStateError, usageError } from '../errors.js';
|
|
3
|
+
import { cli } from '../invocation.js';
|
|
4
|
+
import { SINGLE_SECRET_FORMS, collectSecrets, readSecretFlags, secretInputGiven, } from '../secret-input.js';
|
|
3
5
|
import { call } from '../teams-api.js';
|
|
4
6
|
import { promptHidden } from './apps.js';
|
|
5
7
|
import { requireOperand, usageFor } from './team-agents.js';
|
|
8
|
+
import { teamsSecretIO } from './teams.js';
|
|
9
|
+
import { confirmChange } from './teams-lifecycle.js';
|
|
6
10
|
/**
|
|
7
|
-
* `ekanos teams mcp list|add|status|token|effect|remove` — a team's MCP servers,
|
|
11
|
+
* `ekanos teams mcp list|add|status|token|effect|refresh|attach|detach|remove` — a team's MCP servers,
|
|
8
12
|
* set up by its Source admin (`/api/partner/teams/<team>/mcp/*`).
|
|
9
13
|
*
|
|
10
|
-
* A bearer token is
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* member in their own browser: the CLI
|
|
14
|
+
* A bearer token is typed at the admin's terminal with hidden input or,
|
|
15
|
+
* without one, read from `--secret-env`, `--secret-file`, `--secret-stdin`
|
|
16
|
+
* or a `--browser` form (`secret-input.ts`) — never a value in argv. An
|
|
17
|
+
* OAuth server is signed in by a team member in their own browser: the CLI
|
|
18
|
+
* prints the link for them.
|
|
14
19
|
*/
|
|
15
20
|
const AUTH_FLAGS = { none: 'none', token: 'bearer', oauth: 'oauth' };
|
|
16
21
|
export async function runTeamMcp(ctx, run) {
|
|
@@ -27,6 +32,11 @@ export async function runTeamMcp(ctx, run) {
|
|
|
27
32
|
return effect(ctx, run);
|
|
28
33
|
case 'remove':
|
|
29
34
|
return remove(ctx, run);
|
|
35
|
+
case 'attach':
|
|
36
|
+
case 'detach':
|
|
37
|
+
return attachment(ctx, run, run.verb === 'attach');
|
|
38
|
+
case 'refresh':
|
|
39
|
+
return refresh(ctx, run);
|
|
30
40
|
default:
|
|
31
41
|
throw usageError(`Unknown teams mcp subcommand "${run.verb}".`, usageFor('mcp'));
|
|
32
42
|
}
|
|
@@ -63,7 +73,8 @@ async function add(ctx, run) {
|
|
|
63
73
|
url,
|
|
64
74
|
auth }, (stringFlag(run, 'name') ? { name: stringFlag(run, 'name') } : {})),
|
|
65
75
|
}));
|
|
66
|
-
if (auth === 'bearer' &&
|
|
76
|
+
if (auth === 'bearer' &&
|
|
77
|
+
(canPrompt(ctx, run) || secretInputGiven(readSecretFlags(run.args.flags)))) {
|
|
67
78
|
return enterToken(ctx, run, team, key);
|
|
68
79
|
}
|
|
69
80
|
return ctx.succeed(Object.assign({ host: run.host }, added), renderStatus(ctx, added, `Added ${key} to ${team}`));
|
|
@@ -95,6 +106,84 @@ async function remove(ctx, run) {
|
|
|
95
106
|
],
|
|
96
107
|
}));
|
|
97
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* `teams mcp attach|detach <team> <server-key> <agent-key>`: the app's
|
|
111
|
+
* Attach / Detach on the agent's Tools tab. A provided agent takes the
|
|
112
|
+
* team's servers only where its template allows; one its template attached
|
|
113
|
+
* stays. Detaching asks first at a terminal, `--yes` in a script.
|
|
114
|
+
*/
|
|
115
|
+
async function attachment(ctx, run, attach) {
|
|
116
|
+
const team = requireOperand(run.operands[0], 'team slug', 'mcp');
|
|
117
|
+
const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');
|
|
118
|
+
const agent = requireOperand(run.operands[2], 'agent key', 'mcp');
|
|
119
|
+
noExtra(run, 3);
|
|
120
|
+
if (!attach && !run.args.yes) {
|
|
121
|
+
await confirmChange(ctx, run.args, {
|
|
122
|
+
what: `Detaching ${key} from ${agent} on ${team} takes its tools away from that agent; the server stays on the team for its other agents.`,
|
|
123
|
+
command: `${cli()} teams mcp detach ${team} ${key} ${agent} --yes`,
|
|
124
|
+
question: `Detach ${key} from ${agent} on ${team}? [y/N]`,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
const data = await run.client.call((accessToken) => call(run.host, accessToken, TeamMcpStatusSchema, {
|
|
128
|
+
method: attach ? 'PUT' : 'DELETE',
|
|
129
|
+
path: `${mcpPath(team)}/${encodeURIComponent(key)}/agents/${encodeURIComponent(agent)}`,
|
|
130
|
+
source: run.source,
|
|
131
|
+
}));
|
|
132
|
+
return ctx.succeed(Object.assign({ host: run.host }, data), renderStatus(ctx, data, attach
|
|
133
|
+
? `Attached ${key} to ${agent} on ${team}`
|
|
134
|
+
: `Detached ${key} from ${agent} on ${team}`));
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* `teams mcp refresh <team> <server-key>` — the app's Refresh: the server's
|
|
138
|
+
* tools listed again. `--agent <key>` (no server key) refreshes every
|
|
139
|
+
* server attached to that agent.
|
|
140
|
+
*/
|
|
141
|
+
async function refresh(ctx, run) {
|
|
142
|
+
var _a;
|
|
143
|
+
const team = requireOperand(run.operands[0], 'team slug', 'mcp');
|
|
144
|
+
const agent = (_a = stringFlag(run, 'agent')) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
145
|
+
if (agent && run.operands[1] !== undefined) {
|
|
146
|
+
throw usageError('Name a server key or --agent, not both.', `e.g. ${cli()} teams mcp refresh ${team} --agent ${agent}`);
|
|
147
|
+
}
|
|
148
|
+
const keys = agent
|
|
149
|
+
? await serversOf(run, team, agent)
|
|
150
|
+
: [requireOperand(run.operands[1], 'MCP server key', 'mcp')];
|
|
151
|
+
noExtra(run, agent ? 1 : 2);
|
|
152
|
+
const refreshed = [];
|
|
153
|
+
for (const key of keys) {
|
|
154
|
+
refreshed.push(await run.client.call((accessToken) => call(run.host, accessToken, TeamMcpStatusSchema, {
|
|
155
|
+
method: 'POST',
|
|
156
|
+
path: `${mcpPath(team)}/${encodeURIComponent(key)}/refresh`,
|
|
157
|
+
source: run.source,
|
|
158
|
+
})));
|
|
159
|
+
}
|
|
160
|
+
if (!agent) {
|
|
161
|
+
const data = refreshed[0];
|
|
162
|
+
return ctx.succeed(Object.assign({ host: run.host }, data), renderStatus(ctx, data, `Refreshed ${data.server.key}'s tools on ${team}`));
|
|
163
|
+
}
|
|
164
|
+
return ctx.succeed({ host: run.host, team: { slug: team }, agent, servers: refreshed }, refreshed.length === 0
|
|
165
|
+
? ctx.ui.result({
|
|
166
|
+
title: `${agent} on ${team} has no MCP server attached`,
|
|
167
|
+
tone: 'warn',
|
|
168
|
+
notes: [
|
|
169
|
+
`Attach one: ${cli()} teams mcp attach ${team} <server-key> ${agent}`,
|
|
170
|
+
],
|
|
171
|
+
})
|
|
172
|
+
: refreshed
|
|
173
|
+
.map((data) => renderStatus(ctx, data, `Refreshed ${data.server.key}'s tools for ${agent} on ${team}`))
|
|
174
|
+
.join('\n\n'));
|
|
175
|
+
}
|
|
176
|
+
/** The team's servers the agent has attached (by the team or its template). */
|
|
177
|
+
async function serversOf(run, team, agent) {
|
|
178
|
+
const list = await run.client.call((accessToken) => call(run.host, accessToken, TeamMcpListSchema, {
|
|
179
|
+
method: 'GET',
|
|
180
|
+
path: mcpPath(team),
|
|
181
|
+
source: run.source,
|
|
182
|
+
}));
|
|
183
|
+
return list.servers
|
|
184
|
+
.filter((server) => server.agents.includes(agent))
|
|
185
|
+
.map((server) => server.key);
|
|
186
|
+
}
|
|
98
187
|
async function status(ctx, run) {
|
|
99
188
|
const team = requireOperand(run.operands[0], 'team slug', 'mcp');
|
|
100
189
|
const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');
|
|
@@ -110,14 +199,27 @@ async function token(ctx, run) {
|
|
|
110
199
|
const team = requireOperand(run.operands[0], 'team slug', 'mcp');
|
|
111
200
|
const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');
|
|
112
201
|
noExtra(run, 2);
|
|
113
|
-
|
|
114
|
-
|
|
202
|
+
const secret = readSecretFlags(run.args.flags);
|
|
203
|
+
if (!canPrompt(ctx, run) && !secretInputGiven(secret)) {
|
|
204
|
+
throw usageError("teams mcp token needs the server's token, and there is no terminal to ask at.", `Without a terminal, pass ${SINGLE_SECRET_FORMS}. Or run it yourself in your terminal: ${cli()} teams mcp token ${team} ${key} --source ${run.source}`);
|
|
115
205
|
}
|
|
116
206
|
return enterToken(ctx, run, team, key);
|
|
117
207
|
}
|
|
118
208
|
async function enterToken(ctx, run, team, key) {
|
|
119
209
|
var _a;
|
|
120
|
-
const
|
|
210
|
+
const collected = await collectSecrets(ctx, {
|
|
211
|
+
fields: [
|
|
212
|
+
{ name: 'token', label: `Bearer token for ${key}`, sensitive: true },
|
|
213
|
+
],
|
|
214
|
+
flags: readSecretFlags(run.args.flags),
|
|
215
|
+
io: teamsSecretIO(run.args),
|
|
216
|
+
interactive: canPrompt(ctx, run),
|
|
217
|
+
title: `the ${key} MCP server on ${team}`,
|
|
218
|
+
refusal: "teams mcp token needs the server's token, and there is no terminal to ask at.",
|
|
219
|
+
again: `teams mcp token ${team} ${key} --source ${run.source}`,
|
|
220
|
+
prompt: () => { var _a; return ((_a = run.args.askSecret) !== null && _a !== void 0 ? _a : promptHidden)(`Bearer token for ${key} on ${team} (hidden): `); },
|
|
221
|
+
});
|
|
222
|
+
const value = (_a = collected.token) !== null && _a !== void 0 ? _a : '';
|
|
121
223
|
if (!value) {
|
|
122
224
|
throw usageError('No token entered; nothing was saved.', `Run "ekanos teams mcp token ${team} ${key}" when you have it.`);
|
|
123
225
|
}
|
|
@@ -187,7 +289,7 @@ function renderStatus(ctx, data, title) {
|
|
|
187
289
|
notes.push('A team member who manages agents opens this link, signed in to the team, to connect it (you cannot sign in for them):', data.connectUrl);
|
|
188
290
|
}
|
|
189
291
|
else if (server.auth === 'bearer' && server.status !== 'connected') {
|
|
190
|
-
notes.push(`Enter its token in your terminal:
|
|
292
|
+
notes.push(`Enter its token in your terminal: ${cli()} teams mcp token ${data.team.slug} ${server.key}`);
|
|
191
293
|
}
|
|
192
294
|
if (data.effectsFromTemplate) {
|
|
193
295
|
notes.push("Its tools' effects come from the agent template (toolEffects in agent.json).");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team-agents-mcp.js","sourceRoot":"","sources":["../../src/commands/team-agents-mcp.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type TeamMcpList,\n TeamMcpListSchema,\n TeamMcpRemoveResultSchema,\n type TeamMcpServer,\n type TeamMcpStatus,\n TeamMcpStatusSchema,\n} from '@ekanos/integration-schema';\n\nimport type { CliContext } from '../context';\nimport { invalidStateError, usageError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { call } from '../teams-api';\nimport { promptHidden } from './apps';\nimport { type TeamAgentRun, requireOperand, usageFor } from './team-agents';\n\n/**\n * `ekanos teams mcp list|add|status|token|effect|remove` — a team's MCP servers,\n * set up by its Source admin (`/api/partner/teams/<team>/mcp/*`).\n *\n * A bearer token is only ever typed at the admin's terminal with hidden\n * input — never a flag, a file or a non-interactive run — so an agent\n * driving the CLI never handles it. An OAuth server is signed in by a team\n * member in their own browser: the CLI prints the link for them.\n */\n\nconst AUTH_FLAGS = { none: 'none', token: 'bearer', oauth: 'oauth' } as const;\n\nexport async function runTeamMcp(\n ctx: CliContext,\n run: TeamAgentRun,\n): Promise<ExitCode> {\n switch (run.verb) {\n case 'list':\n return list(ctx, run);\n case 'add':\n return add(ctx, run);\n case 'status':\n return status(ctx, run);\n case 'token':\n return token(ctx, run);\n case 'effect':\n return effect(ctx, run);\n case 'remove':\n return remove(ctx, run);\n default:\n throw usageError(\n `Unknown teams mcp subcommand \"${run.verb}\".`,\n usageFor('mcp'),\n );\n }\n}\n\nasync function list(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n noExtra(run, 1);\n const data = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpListSchema, {\n method: 'GET',\n path: mcpPath(team),\n source: run.source,\n }),\n );\n return ctx.succeed({ host: run.host, ...data }, renderList(ctx, data));\n}\n\nasync function add(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');\n noExtra(run, 2);\n\n const url = stringFlag(run, 'url');\n if (!url) {\n throw usageError(\n 'teams mcp add needs the server URL.',\n `Run \"ekanos teams mcp add ${team} ${key} --url https://… [--auth none|token|oauth]\".`,\n );\n }\n const authFlag = stringFlag(run, 'auth') ?? 'oauth';\n if (!(authFlag in AUTH_FLAGS)) {\n throw usageError(\n `--auth must be none, token or oauth (got \"${authFlag}\").`,\n usageFor('mcp'),\n );\n }\n const auth = AUTH_FLAGS[authFlag as keyof typeof AUTH_FLAGS];\n\n const added = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpStatusSchema, {\n method: 'POST',\n path: mcpPath(team),\n source: run.source,\n body: {\n key,\n url,\n auth,\n ...(stringFlag(run, 'name') ? { name: stringFlag(run, 'name') } : {}),\n },\n }),\n );\n\n if (auth === 'bearer' && canPrompt(ctx, run)) {\n return enterToken(ctx, run, team, key);\n }\n return ctx.succeed(\n { host: run.host, ...added },\n renderStatus(ctx, added, `Added ${key} to ${team}`),\n );\n}\n\n/**\n * `teams mcp remove <team> <server-key> --yes`: the app's Remove — every\n * agent of the team loses the server, and its credentials are deleted.\n */\nasync function remove(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');\n noExtra(run, 2);\n if (!run.args.yes) {\n throw invalidStateError(\n `Removing ${key} from ${team} takes it away from every agent of the team that uses it, and deletes its stored token or sign-in.`,\n `Re-run with --yes: ekanos teams mcp remove ${team} ${key} --yes`,\n );\n }\n const removed = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpRemoveResultSchema, {\n method: 'DELETE',\n path: `${mcpPath(team)}/${encodeURIComponent(key)}`,\n source: run.source,\n }),\n );\n return ctx.succeed(\n { host: run.host, ...removed },\n ctx.ui.result({\n title: `Removed ${removed.removed} from ${removed.team.slug}`,\n tone: 'warn',\n rows: [\n [\n 'Agents that lost it',\n removed.agents.length > 0 ? removed.agents.join(', ') : 'none',\n ],\n ],\n }),\n );\n}\n\nasync function status(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');\n noExtra(run, 2);\n const data = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpStatusSchema, {\n method: 'GET',\n path: `${mcpPath(team)}/${encodeURIComponent(key)}`,\n source: run.source,\n }),\n );\n return ctx.succeed(\n { host: run.host, ...data },\n renderStatus(ctx, data, `${key} on ${team}`),\n );\n}\n\nasync function token(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');\n noExtra(run, 2);\n if (!canPrompt(ctx, run)) {\n throw usageError(\n \"teams mcp token takes the server's token at a terminal, never in a script or an agent run.\",\n `Run it yourself in your terminal: npx @ekanos/cli teams mcp token ${team} ${key} --source ${run.source}`,\n );\n }\n return enterToken(ctx, run, team, key);\n}\n\nasync function enterToken(\n ctx: CliContext,\n run: TeamAgentRun,\n team: string,\n key: string,\n): Promise<ExitCode> {\n const value = (\n await (run.args.askSecret ?? promptHidden)(\n `Bearer token for ${key} on ${team} (hidden): `,\n )\n ).trim();\n if (!value) {\n throw usageError(\n 'No token entered; nothing was saved.',\n `Run \"ekanos teams mcp token ${team} ${key}\" when you have it.`,\n );\n }\n const saved = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpStatusSchema, {\n method: 'PUT',\n path: `${mcpPath(team)}/${encodeURIComponent(key)}/token`,\n source: run.source,\n body: { token: value },\n }),\n );\n return ctx.succeed(\n { host: run.host, ...saved },\n renderStatus(ctx, saved, `Saved ${key}'s token for ${team}`),\n );\n}\n\nasync function effect(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');\n const tool = run.operands[2]?.trim();\n const value = run.operands[3]?.trim().toLowerCase();\n noExtra(run, 4);\n if (!tool || (value !== 'read' && value !== 'write')) {\n throw usageError(\n 'teams mcp effect needs a tool and read or write.',\n `Run \"ekanos teams mcp effect ${team} ${key} <tool> read|write\"; \"ekanos teams mcp status ${team} ${key}\" lists the tools.`,\n );\n }\n const saved = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpStatusSchema, {\n method: 'PUT',\n path: `${mcpPath(team)}/${encodeURIComponent(key)}/effects`,\n source: run.source,\n body: { tool, effect: value },\n }),\n );\n return ctx.succeed(\n { host: run.host, ...saved },\n renderStatus(ctx, saved, `${tool} on ${key} is now a ${value}`),\n );\n}\n\nfunction renderList(ctx: CliContext, data: TeamMcpList): string {\n if (data.servers.length === 0 && data.missing.length === 0) {\n return ctx.ui.result({\n title: `No MCP servers on ${data.team.slug}`,\n tone: 'warn',\n notes: [\n `Add one: ekanos teams mcp add ${data.team.slug} <key> --url https://… --auth none|token|oauth`,\n ],\n });\n }\n return ctx.ui.result({\n title: `MCP servers on ${data.team.slug}`,\n tone:\n data.missing.some((entry) => entry.required) ||\n data.servers.some((server) => server.status !== 'connected')\n ? 'warn'\n : 'ok',\n rows: [\n ...data.servers.map((server): [string, string] => [\n server.key,\n describeServer(server),\n ]),\n ...data.missing.map((entry): [string, string] => [\n entry.key,\n `✗ missing — ${entry.agent} ${entry.required ? 'needs' : 'can use'} ${entry.url}`,\n ]),\n ],\n notes: [\n `\"ekanos teams mcp status ${data.team.slug} <key>\" shows a server's tools and how to connect it.`,\n ],\n });\n}\n\nfunction renderStatus(\n ctx: CliContext,\n data: TeamMcpStatus,\n title: string,\n): string {\n const { server } = data;\n const notes: string[] = [];\n if (data.syncError) notes.push(`Listing its tools failed: ${data.syncError}`);\n if (data.connectUrl) {\n notes.push(\n 'A team member who manages agents opens this link, signed in to the team, to connect it (you cannot sign in for them):',\n data.connectUrl,\n );\n } else if (server.auth === 'bearer' && server.status !== 'connected') {\n notes.push(\n `Enter its token in your terminal: npx @ekanos/cli teams mcp token ${data.team.slug} ${server.key}`,\n );\n }\n if (data.effectsFromTemplate) {\n notes.push(\n \"Its tools' effects come from the agent template (toolEffects in agent.json).\",\n );\n } else if (data.tools.some((tool) => !tool.confirmed)) {\n notes.push(\n `Unconfirmed tools count as writes. Mark a read: ekanos teams mcp effect ${data.team.slug} ${server.key} <tool> read`,\n );\n }\n return ctx.ui.result({\n title,\n tone: server.status === 'connected' && !data.syncError ? 'ok' : 'warn',\n rows: [\n ['Server', describeServer(server)],\n ['URL', server.url],\n ...(data.tools.length > 0\n ? [\n [\n 'Tools',\n data.tools.map(\n (tool) =>\n `${tool.name} · ${tool.effect}${tool.confirmed ? '' : ` (unconfirmed, server suggests ${tool.suggested})`}`,\n ),\n ] as [string, string[]],\n ]\n : []),\n ],\n notes,\n });\n}\n\nfunction describeServer(server: TeamMcpServer): string {\n const state =\n server.status === 'connected'\n ? `✓ connected · ${server.toolCount} tool${server.toolCount === 1 ? '' : 's'}`\n : server.status === 'error'\n ? `✗ error${server.lastError ? `: ${server.lastError}` : ''}`\n : `✗ needs ${server.auth === 'oauth' ? 'sign-in' : server.auth === 'bearer' ? 'a token' : 'a refresh'}`;\n const auth = server.auth === 'bearer' ? 'token' : server.auth;\n const used = [\n ...server.declaredBy.map(\n (use) =>\n `${use.agent} (${use.required ? 'required' : 'optional'}${use.urlMatches ? '' : ', different URL — not the one it needs'})`,\n ),\n ...server.agents.filter(\n (agent) => !server.declaredBy.some((use) => use.agent === agent),\n ),\n ];\n return `${state} · ${auth}${used.length > 0 ? ` · used by ${used.join(', ')}` : ''}`;\n}\n\nfunction mcpPath(team: string): string {\n return `/api/partner/teams/${encodeURIComponent(team)}/mcp`;\n}\n\nfunction stringFlag(run: TeamAgentRun, name: string): string | undefined {\n const value = run.args.flags?.[name];\n return typeof value === 'string' && value.trim() ? value.trim() : undefined;\n}\n\nfunction noExtra(run: TeamAgentRun, count: number): void {\n const extra = run.operands[count];\n if (extra !== undefined) {\n throw usageError(`Unexpected argument \"${extra}\".`, usageFor('mcp'));\n }\n}\n\nfunction canPrompt(ctx: CliContext, run: TeamAgentRun): boolean {\n return !ctx.jsonMode && (run.args.stdinIsTTY ?? process.stdin.isTTY === true);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"team-agents-mcp.js","sourceRoot":"","sources":["../../src/commands/team-agents-mcp.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type TeamMcpList,\n TeamMcpListSchema,\n TeamMcpRemoveResultSchema,\n type TeamMcpServer,\n type TeamMcpStatus,\n TeamMcpStatusSchema,\n} from '@ekanos/integration-schema';\n\nimport type { CliContext } from '../context';\nimport { invalidStateError, usageError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { cli } from '../invocation';\nimport {\n SINGLE_SECRET_FORMS,\n collectSecrets,\n readSecretFlags,\n secretInputGiven,\n} from '../secret-input';\nimport { call } from '../teams-api';\nimport { promptHidden } from './apps';\nimport { type TeamAgentRun, requireOperand, usageFor } from './team-agents';\nimport { teamsSecretIO } from './teams';\nimport { confirmChange } from './teams-lifecycle';\n\n/**\n * `ekanos teams mcp list|add|status|token|effect|refresh|attach|detach|remove` — a team's MCP servers,\n * set up by its Source admin (`/api/partner/teams/<team>/mcp/*`).\n *\n * A bearer token is typed at the admin's terminal with hidden input or,\n * without one, read from `--secret-env`, `--secret-file`, `--secret-stdin`\n * or a `--browser` form (`secret-input.ts`) — never a value in argv. An\n * OAuth server is signed in by a team member in their own browser: the CLI\n * prints the link for them.\n */\n\nconst AUTH_FLAGS = { none: 'none', token: 'bearer', oauth: 'oauth' } as const;\n\nexport async function runTeamMcp(\n ctx: CliContext,\n run: TeamAgentRun,\n): Promise<ExitCode> {\n switch (run.verb) {\n case 'list':\n return list(ctx, run);\n case 'add':\n return add(ctx, run);\n case 'status':\n return status(ctx, run);\n case 'token':\n return token(ctx, run);\n case 'effect':\n return effect(ctx, run);\n case 'remove':\n return remove(ctx, run);\n case 'attach':\n case 'detach':\n return attachment(ctx, run, run.verb === 'attach');\n case 'refresh':\n return refresh(ctx, run);\n default:\n throw usageError(\n `Unknown teams mcp subcommand \"${run.verb}\".`,\n usageFor('mcp'),\n );\n }\n}\n\nasync function list(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n noExtra(run, 1);\n const data = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpListSchema, {\n method: 'GET',\n path: mcpPath(team),\n source: run.source,\n }),\n );\n return ctx.succeed({ host: run.host, ...data }, renderList(ctx, data));\n}\n\nasync function add(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');\n noExtra(run, 2);\n\n const url = stringFlag(run, 'url');\n if (!url) {\n throw usageError(\n 'teams mcp add needs the server URL.',\n `Run \"ekanos teams mcp add ${team} ${key} --url https://… [--auth none|token|oauth]\".`,\n );\n }\n const authFlag = stringFlag(run, 'auth') ?? 'oauth';\n if (!(authFlag in AUTH_FLAGS)) {\n throw usageError(\n `--auth must be none, token or oauth (got \"${authFlag}\").`,\n usageFor('mcp'),\n );\n }\n const auth = AUTH_FLAGS[authFlag as keyof typeof AUTH_FLAGS];\n\n const added = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpStatusSchema, {\n method: 'POST',\n path: mcpPath(team),\n source: run.source,\n body: {\n key,\n url,\n auth,\n ...(stringFlag(run, 'name') ? { name: stringFlag(run, 'name') } : {}),\n },\n }),\n );\n\n if (\n auth === 'bearer' &&\n (canPrompt(ctx, run) || secretInputGiven(readSecretFlags(run.args.flags)))\n ) {\n return enterToken(ctx, run, team, key);\n }\n return ctx.succeed(\n { host: run.host, ...added },\n renderStatus(ctx, added, `Added ${key} to ${team}`),\n );\n}\n\n/**\n * `teams mcp remove <team> <server-key> --yes`: the app's Remove — every\n * agent of the team loses the server, and its credentials are deleted.\n */\nasync function remove(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');\n noExtra(run, 2);\n if (!run.args.yes) {\n throw invalidStateError(\n `Removing ${key} from ${team} takes it away from every agent of the team that uses it, and deletes its stored token or sign-in.`,\n `Re-run with --yes: ekanos teams mcp remove ${team} ${key} --yes`,\n );\n }\n const removed = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpRemoveResultSchema, {\n method: 'DELETE',\n path: `${mcpPath(team)}/${encodeURIComponent(key)}`,\n source: run.source,\n }),\n );\n return ctx.succeed(\n { host: run.host, ...removed },\n ctx.ui.result({\n title: `Removed ${removed.removed} from ${removed.team.slug}`,\n tone: 'warn',\n rows: [\n [\n 'Agents that lost it',\n removed.agents.length > 0 ? removed.agents.join(', ') : 'none',\n ],\n ],\n }),\n );\n}\n\n/**\n * `teams mcp attach|detach <team> <server-key> <agent-key>`: the app's\n * Attach / Detach on the agent's Tools tab. A provided agent takes the\n * team's servers only where its template allows; one its template attached\n * stays. Detaching asks first at a terminal, `--yes` in a script.\n */\nasync function attachment(\n ctx: CliContext,\n run: TeamAgentRun,\n attach: boolean,\n): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');\n const agent = requireOperand(run.operands[2], 'agent key', 'mcp');\n noExtra(run, 3);\n if (!attach && !run.args.yes) {\n await confirmChange(ctx, run.args, {\n what: `Detaching ${key} from ${agent} on ${team} takes its tools away from that agent; the server stays on the team for its other agents.`,\n command: `${cli()} teams mcp detach ${team} ${key} ${agent} --yes`,\n question: `Detach ${key} from ${agent} on ${team}? [y/N]`,\n });\n }\n const data = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpStatusSchema, {\n method: attach ? 'PUT' : 'DELETE',\n path: `${mcpPath(team)}/${encodeURIComponent(key)}/agents/${encodeURIComponent(agent)}`,\n source: run.source,\n }),\n );\n return ctx.succeed(\n { host: run.host, ...data },\n renderStatus(\n ctx,\n data,\n attach\n ? `Attached ${key} to ${agent} on ${team}`\n : `Detached ${key} from ${agent} on ${team}`,\n ),\n );\n}\n\n/**\n * `teams mcp refresh <team> <server-key>` — the app's Refresh: the server's\n * tools listed again. `--agent <key>` (no server key) refreshes every\n * server attached to that agent.\n */\nasync function refresh(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n const agent = stringFlag(run, 'agent')?.toLowerCase();\n if (agent && run.operands[1] !== undefined) {\n throw usageError(\n 'Name a server key or --agent, not both.',\n `e.g. ${cli()} teams mcp refresh ${team} --agent ${agent}`,\n );\n }\n const keys = agent\n ? await serversOf(run, team, agent)\n : [requireOperand(run.operands[1], 'MCP server key', 'mcp')];\n noExtra(run, agent ? 1 : 2);\n\n const refreshed: TeamMcpStatus[] = [];\n for (const key of keys) {\n refreshed.push(\n await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpStatusSchema, {\n method: 'POST',\n path: `${mcpPath(team)}/${encodeURIComponent(key)}/refresh`,\n source: run.source,\n }),\n ),\n );\n }\n if (!agent) {\n const data = refreshed[0]!;\n return ctx.succeed(\n { host: run.host, ...data },\n renderStatus(\n ctx,\n data,\n `Refreshed ${data.server.key}'s tools on ${team}`,\n ),\n );\n }\n return ctx.succeed(\n { host: run.host, team: { slug: team }, agent, servers: refreshed },\n refreshed.length === 0\n ? ctx.ui.result({\n title: `${agent} on ${team} has no MCP server attached`,\n tone: 'warn',\n notes: [\n `Attach one: ${cli()} teams mcp attach ${team} <server-key> ${agent}`,\n ],\n })\n : refreshed\n .map((data) =>\n renderStatus(\n ctx,\n data,\n `Refreshed ${data.server.key}'s tools for ${agent} on ${team}`,\n ),\n )\n .join('\\n\\n'),\n );\n}\n\n/** The team's servers the agent has attached (by the team or its template). */\nasync function serversOf(\n run: TeamAgentRun,\n team: string,\n agent: string,\n): Promise<string[]> {\n const list = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpListSchema, {\n method: 'GET',\n path: mcpPath(team),\n source: run.source,\n }),\n );\n return list.servers\n .filter((server) => server.agents.includes(agent))\n .map((server) => server.key);\n}\n\nasync function status(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');\n noExtra(run, 2);\n const data = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpStatusSchema, {\n method: 'GET',\n path: `${mcpPath(team)}/${encodeURIComponent(key)}`,\n source: run.source,\n }),\n );\n return ctx.succeed(\n { host: run.host, ...data },\n renderStatus(ctx, data, `${key} on ${team}`),\n );\n}\n\nasync function token(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');\n noExtra(run, 2);\n const secret = readSecretFlags(run.args.flags);\n if (!canPrompt(ctx, run) && !secretInputGiven(secret)) {\n throw usageError(\n \"teams mcp token needs the server's token, and there is no terminal to ask at.\",\n `Without a terminal, pass ${SINGLE_SECRET_FORMS}. Or run it yourself in your terminal: ${cli()} teams mcp token ${team} ${key} --source ${run.source}`,\n );\n }\n return enterToken(ctx, run, team, key);\n}\n\nasync function enterToken(\n ctx: CliContext,\n run: TeamAgentRun,\n team: string,\n key: string,\n): Promise<ExitCode> {\n const collected = await collectSecrets(ctx, {\n fields: [\n { name: 'token', label: `Bearer token for ${key}`, sensitive: true },\n ],\n flags: readSecretFlags(run.args.flags),\n io: teamsSecretIO(run.args),\n interactive: canPrompt(ctx, run),\n title: `the ${key} MCP server on ${team}`,\n refusal:\n \"teams mcp token needs the server's token, and there is no terminal to ask at.\",\n again: `teams mcp token ${team} ${key} --source ${run.source}`,\n prompt: () =>\n (run.args.askSecret ?? promptHidden)(\n `Bearer token for ${key} on ${team} (hidden): `,\n ),\n });\n const value = collected.token ?? '';\n if (!value) {\n throw usageError(\n 'No token entered; nothing was saved.',\n `Run \"ekanos teams mcp token ${team} ${key}\" when you have it.`,\n );\n }\n const saved = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpStatusSchema, {\n method: 'PUT',\n path: `${mcpPath(team)}/${encodeURIComponent(key)}/token`,\n source: run.source,\n body: { token: value },\n }),\n );\n return ctx.succeed(\n { host: run.host, ...saved },\n renderStatus(ctx, saved, `Saved ${key}'s token for ${team}`),\n );\n}\n\nasync function effect(ctx: CliContext, run: TeamAgentRun): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'mcp');\n const key = requireOperand(run.operands[1], 'MCP server key', 'mcp');\n const tool = run.operands[2]?.trim();\n const value = run.operands[3]?.trim().toLowerCase();\n noExtra(run, 4);\n if (!tool || (value !== 'read' && value !== 'write')) {\n throw usageError(\n 'teams mcp effect needs a tool and read or write.',\n `Run \"ekanos teams mcp effect ${team} ${key} <tool> read|write\"; \"ekanos teams mcp status ${team} ${key}\" lists the tools.`,\n );\n }\n const saved = await run.client.call((accessToken) =>\n call(run.host, accessToken, TeamMcpStatusSchema, {\n method: 'PUT',\n path: `${mcpPath(team)}/${encodeURIComponent(key)}/effects`,\n source: run.source,\n body: { tool, effect: value },\n }),\n );\n return ctx.succeed(\n { host: run.host, ...saved },\n renderStatus(ctx, saved, `${tool} on ${key} is now a ${value}`),\n );\n}\n\nfunction renderList(ctx: CliContext, data: TeamMcpList): string {\n if (data.servers.length === 0 && data.missing.length === 0) {\n return ctx.ui.result({\n title: `No MCP servers on ${data.team.slug}`,\n tone: 'warn',\n notes: [\n `Add one: ekanos teams mcp add ${data.team.slug} <key> --url https://… --auth none|token|oauth`,\n ],\n });\n }\n return ctx.ui.result({\n title: `MCP servers on ${data.team.slug}`,\n tone:\n data.missing.some((entry) => entry.required) ||\n data.servers.some((server) => server.status !== 'connected')\n ? 'warn'\n : 'ok',\n rows: [\n ...data.servers.map((server): [string, string] => [\n server.key,\n describeServer(server),\n ]),\n ...data.missing.map((entry): [string, string] => [\n entry.key,\n `✗ missing — ${entry.agent} ${entry.required ? 'needs' : 'can use'} ${entry.url}`,\n ]),\n ],\n notes: [\n `\"ekanos teams mcp status ${data.team.slug} <key>\" shows a server's tools and how to connect it.`,\n ],\n });\n}\n\nfunction renderStatus(\n ctx: CliContext,\n data: TeamMcpStatus,\n title: string,\n): string {\n const { server } = data;\n const notes: string[] = [];\n if (data.syncError) notes.push(`Listing its tools failed: ${data.syncError}`);\n if (data.connectUrl) {\n notes.push(\n 'A team member who manages agents opens this link, signed in to the team, to connect it (you cannot sign in for them):',\n data.connectUrl,\n );\n } else if (server.auth === 'bearer' && server.status !== 'connected') {\n notes.push(\n `Enter its token in your terminal: ${cli()} teams mcp token ${data.team.slug} ${server.key}`,\n );\n }\n if (data.effectsFromTemplate) {\n notes.push(\n \"Its tools' effects come from the agent template (toolEffects in agent.json).\",\n );\n } else if (data.tools.some((tool) => !tool.confirmed)) {\n notes.push(\n `Unconfirmed tools count as writes. Mark a read: ekanos teams mcp effect ${data.team.slug} ${server.key} <tool> read`,\n );\n }\n return ctx.ui.result({\n title,\n tone: server.status === 'connected' && !data.syncError ? 'ok' : 'warn',\n rows: [\n ['Server', describeServer(server)],\n ['URL', server.url],\n ...(data.tools.length > 0\n ? [\n [\n 'Tools',\n data.tools.map(\n (tool) =>\n `${tool.name} · ${tool.effect}${tool.confirmed ? '' : ` (unconfirmed, server suggests ${tool.suggested})`}`,\n ),\n ] as [string, string[]],\n ]\n : []),\n ],\n notes,\n });\n}\n\nfunction describeServer(server: TeamMcpServer): string {\n const state =\n server.status === 'connected'\n ? `✓ connected · ${server.toolCount} tool${server.toolCount === 1 ? '' : 's'}`\n : server.status === 'error'\n ? `✗ error${server.lastError ? `: ${server.lastError}` : ''}`\n : `✗ needs ${server.auth === 'oauth' ? 'sign-in' : server.auth === 'bearer' ? 'a token' : 'a refresh'}`;\n const auth = server.auth === 'bearer' ? 'token' : server.auth;\n const used = [\n ...server.declaredBy.map(\n (use) =>\n `${use.agent} (${use.required ? 'required' : 'optional'}${use.urlMatches ? '' : ', different URL — not the one it needs'})`,\n ),\n ...server.agents.filter(\n (agent) => !server.declaredBy.some((use) => use.agent === agent),\n ),\n ];\n return `${state} · ${auth}${used.length > 0 ? ` · used by ${used.join(', ')}` : ''}`;\n}\n\nfunction mcpPath(team: string): string {\n return `/api/partner/teams/${encodeURIComponent(team)}/mcp`;\n}\n\nfunction stringFlag(run: TeamAgentRun, name: string): string | undefined {\n const value = run.args.flags?.[name];\n return typeof value === 'string' && value.trim() ? value.trim() : undefined;\n}\n\nfunction noExtra(run: TeamAgentRun, count: number): void {\n const extra = run.operands[count];\n if (extra !== undefined) {\n throw usageError(`Unexpected argument \"${extra}\".`, usageFor('mcp'));\n }\n}\n\nfunction canPrompt(ctx: CliContext, run: TeamAgentRun): boolean {\n return !ctx.jsonMode && (run.args.stdinIsTTY ?? process.stdin.isTTY === true);\n}\n"]}
|
|
@@ -2,7 +2,7 @@ import type { CliContext } from '../context.js';
|
|
|
2
2
|
import type { ExitCode } from '../exit-codes.js';
|
|
3
3
|
import { type TeamAgentRun } from './team-agents.js';
|
|
4
4
|
/**
|
|
5
|
-
* `ekanos teams triggers list|add|remove` and `ekanos teams links
|
|
5
|
+
* `ekanos teams triggers list|add|remove|rotate|enable|disable|edit` and `ekanos teams links
|
|
6
6
|
* list|add|remove` — a team agent's triggers and outgoing links, set up by
|
|
7
7
|
* the Source admin. When the template keeps an area, the host shows the
|
|
8
8
|
* effective rows and refuses changes with the command that hands the area
|
|
@@ -9,14 +9,16 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
-
import { TeamAgentLinkAddResultSchema, TeamAgentLinkListSchema, TeamAgentRowRemoveResultSchema, TeamAgentTriggerAddResultSchema, TeamAgentTriggerListSchema, } from '@ekanos/integration-schema';
|
|
12
|
+
import { TeamAgentLinkAddResultSchema, TeamAgentLinkListSchema, TeamAgentRowRemoveResultSchema, TeamAgentTriggerAddResultSchema, TeamAgentTriggerListSchema, TeamAgentTriggerUpdateResultSchema, } from '@ekanos/integration-schema';
|
|
13
13
|
import { invalidStateError, usageError } from '../errors.js';
|
|
14
|
+
import { cli } from '../invocation.js';
|
|
14
15
|
import { ensureSecretsDir, writeSecretFile } from '../secret-file.js';
|
|
15
16
|
import { call } from '../teams-api.js';
|
|
16
17
|
import { parseFilters } from './agents-edit.js';
|
|
17
18
|
import { requireOperand, usageFor } from './team-agents.js';
|
|
19
|
+
import { confirmChange } from './teams-lifecycle.js';
|
|
18
20
|
/**
|
|
19
|
-
* `ekanos teams triggers list|add|remove` and `ekanos teams links
|
|
21
|
+
* `ekanos teams triggers list|add|remove|rotate|enable|disable|edit` and `ekanos teams links
|
|
20
22
|
* list|add|remove` — a team agent's triggers and outgoing links, set up by
|
|
21
23
|
* the Source admin. When the template keeps an area, the host shows the
|
|
22
24
|
* effective rows and refuses changes with the command that hands the area
|
|
@@ -78,11 +80,15 @@ export async function runTeamTriggers(ctx, run) {
|
|
|
78
80
|
: null;
|
|
79
81
|
if (saved)
|
|
80
82
|
rows.push(...saved.rows);
|
|
81
|
-
|
|
83
|
+
const personal = added.agent.ownership === 'personal';
|
|
84
|
+
return ctx.succeed(Object.assign(Object.assign(Object.assign({ host: run.host }, rest), { webhook: (_d = saved === null || saved === void 0 ? void 0 : saved.json) !== null && _d !== void 0 ? _d : null }), (personal ? { actsFor: 'creator' } : {})), ctx.ui.result({
|
|
82
85
|
title: `Added a ${added.trigger.type} trigger to ${added.agent.slug} on ${added.team.slug}`,
|
|
83
|
-
tone: saved ? 'warn' : 'ok',
|
|
86
|
+
tone: saved || personal ? 'warn' : 'ok',
|
|
84
87
|
rows,
|
|
85
|
-
notes:
|
|
88
|
+
notes: [
|
|
89
|
+
...(personal ? personalTriggerNotes(added.trigger.type) : []),
|
|
90
|
+
...(saved ? saved.notes : []),
|
|
91
|
+
],
|
|
86
92
|
}));
|
|
87
93
|
}
|
|
88
94
|
case 'remove': {
|
|
@@ -104,6 +110,10 @@ export async function runTeamTriggers(ctx, run) {
|
|
|
104
110
|
}
|
|
105
111
|
case 'rotate':
|
|
106
112
|
return rotateSecret(ctx, run, team, key);
|
|
113
|
+
case 'enable':
|
|
114
|
+
case 'disable':
|
|
115
|
+
case 'edit':
|
|
116
|
+
return updateTrigger(ctx, run, team, key, run.verb);
|
|
107
117
|
default:
|
|
108
118
|
throw usageError(`Unknown teams triggers subcommand "${run.verb}".`, usageFor('triggers'));
|
|
109
119
|
}
|
|
@@ -220,6 +230,9 @@ async function rotateSecret(ctx, run, team, key) {
|
|
|
220
230
|
tone: 'warn',
|
|
221
231
|
rows: (_g = saved === null || saved === void 0 ? void 0 : saved.rows) !== null && _g !== void 0 ? _g : [],
|
|
222
232
|
notes: [
|
|
233
|
+
...(rotated.agent.ownership === 'personal'
|
|
234
|
+
? personalTriggerNotes('webhook')
|
|
235
|
+
: []),
|
|
223
236
|
...((_h = saved === null || saved === void 0 ? void 0 : saved.notes) !== null && _h !== void 0 ? _h : []),
|
|
224
237
|
...(trigger.secretSet === false
|
|
225
238
|
? []
|
|
@@ -254,6 +267,125 @@ function saveTriggerToken(run, dir, input) {
|
|
|
254
267
|
],
|
|
255
268
|
};
|
|
256
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* A personal agent's trigger acts for its creator, with their own
|
|
272
|
+
* connections (plan 247 decision 3) — so its webhook token is as good as
|
|
273
|
+
* their say-so, within the agent's tools and policy.
|
|
274
|
+
*/
|
|
275
|
+
function personalTriggerNotes(type) {
|
|
276
|
+
return type === 'webhook'
|
|
277
|
+
? [
|
|
278
|
+
'This is a personal agent: each request to this webhook makes it act as its creator, with their own connections. Whoever holds the token can do that, within its tools and policy (a write set to approve still waits for them). Keep the token secret, and rotate it if it may have leaked.',
|
|
279
|
+
]
|
|
280
|
+
: [
|
|
281
|
+
'This is a personal agent: each run this trigger starts acts as its creator, with their own connections.',
|
|
282
|
+
];
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* `teams triggers enable|disable|edit <team> <key> <trigger-id|key>` — the
|
|
286
|
+
* app's trigger switch and Edit. The trigger stays what it is: same type,
|
|
287
|
+
* same install or event, and a webhook keeps its URL and token (only
|
|
288
|
+
* `teams triggers rotate` makes a new one). Turning one off, or changing who
|
|
289
|
+
* a Slack trigger answers, asks first at a terminal; `--yes` in a script.
|
|
290
|
+
*/
|
|
291
|
+
async function updateTrigger(ctx, run, team, key, verb) {
|
|
292
|
+
var _a;
|
|
293
|
+
var _b, _c;
|
|
294
|
+
const ref = (_a = run.operands[2]) === null || _a === void 0 ? void 0 : _a.trim();
|
|
295
|
+
if (!ref) {
|
|
296
|
+
throw usageError(`Name the trigger to ${verb}, by its id or key.`, `List them: ${cli()} teams triggers list ${team} ${key}`);
|
|
297
|
+
}
|
|
298
|
+
noExtra(run.operands, 3, 'triggers');
|
|
299
|
+
const body = verb === 'edit'
|
|
300
|
+
? editBody(run, team, key, ref)
|
|
301
|
+
: { enabled: verb === 'enable' };
|
|
302
|
+
const audience = body.channels !== undefined || body.directMessages !== undefined;
|
|
303
|
+
if (!run.args.yes && (verb === 'disable' || audience)) {
|
|
304
|
+
await confirmChange(ctx, run.args, verb === 'disable'
|
|
305
|
+
? {
|
|
306
|
+
what: `Turning trigger ${ref} of ${key} on ${team} off stops it starting runs until it is turned on again. A webhook keeps its URL and token.`,
|
|
307
|
+
command: `${cli()} teams triggers disable ${team} ${key} ${ref} --yes`,
|
|
308
|
+
question: `Turn trigger ${ref} of ${key} on ${team} off? [y/N]`,
|
|
309
|
+
}
|
|
310
|
+
: {
|
|
311
|
+
what: 'Anyone in those channels, and anyone who messages the bot, can then ask the agent to act with everything it is granted.',
|
|
312
|
+
command: `${cli()} teams triggers edit ${team} ${key} ${ref} … --yes`,
|
|
313
|
+
question: `Let that audience ask ${key} on ${team} to act? [y/N]`,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
const result = await run.client.call((token) => call(run.host, token, TeamAgentTriggerUpdateResultSchema, {
|
|
317
|
+
method: 'PATCH',
|
|
318
|
+
path: `${agentPath(team, key)}/triggers/${encodeURIComponent(ref)}`,
|
|
319
|
+
source: run.source,
|
|
320
|
+
body: audience ? Object.assign(Object.assign({}, body), { confirmAudience: true }) : body,
|
|
321
|
+
}));
|
|
322
|
+
const title = verb === 'edit'
|
|
323
|
+
? `Changed trigger ${(_b = result.trigger.key) !== null && _b !== void 0 ? _b : result.trigger.id} of ${result.agent.slug} on ${result.team.slug}`
|
|
324
|
+
: `Turned trigger ${(_c = result.trigger.key) !== null && _c !== void 0 ? _c : result.trigger.id} of ${result.agent.slug} on ${result.team.slug} ${verb === 'enable' ? 'on' : 'off'}`;
|
|
325
|
+
return ctx.succeed(Object.assign({ host: run.host }, result), ctx.ui.result({
|
|
326
|
+
title,
|
|
327
|
+
tone: 'ok',
|
|
328
|
+
rows: [
|
|
329
|
+
['Trigger', result.trigger.id],
|
|
330
|
+
['Fires on', describeTrigger(result.trigger)],
|
|
331
|
+
...(verb === 'edit'
|
|
332
|
+
? [
|
|
333
|
+
[
|
|
334
|
+
'Changed',
|
|
335
|
+
result.changed
|
|
336
|
+
.map((field) => { var _a; return (_a = CHANGED_WORDS[field]) !== null && _a !== void 0 ? _a : field; })
|
|
337
|
+
.join(', '),
|
|
338
|
+
],
|
|
339
|
+
]
|
|
340
|
+
: []),
|
|
341
|
+
],
|
|
342
|
+
notes: result.trigger.type === 'webhook'
|
|
343
|
+
? ['Its URL and token are unchanged.']
|
|
344
|
+
: [],
|
|
345
|
+
}));
|
|
346
|
+
}
|
|
347
|
+
/** A changed field as `teams triggers edit` names it. */
|
|
348
|
+
const CHANGED_WORDS = {
|
|
349
|
+
enabled: 'on/off',
|
|
350
|
+
promptTemplate: 'prompt',
|
|
351
|
+
scheduleCron: 'cron',
|
|
352
|
+
timezone: 'time zone',
|
|
353
|
+
filter: 'filter',
|
|
354
|
+
channels: 'channels',
|
|
355
|
+
directMessages: 'direct messages',
|
|
356
|
+
onMention: 'mentions',
|
|
357
|
+
labelNames: 'labels',
|
|
358
|
+
};
|
|
359
|
+
/** What `teams triggers edit` changes, from its flags; at least one. */
|
|
360
|
+
function editBody(run, team, key, ref) {
|
|
361
|
+
var _a;
|
|
362
|
+
const flags = (_a = run.args.flags) !== null && _a !== void 0 ? _a : {};
|
|
363
|
+
const body = {};
|
|
364
|
+
const prompt = flags.prompt;
|
|
365
|
+
if (typeof prompt === 'string')
|
|
366
|
+
body.promptTemplate = prompt.trim();
|
|
367
|
+
const cron = flag(run, 'cron');
|
|
368
|
+
if (cron)
|
|
369
|
+
body.scheduleCron = cron;
|
|
370
|
+
const timezone = flag(run, 'timezone');
|
|
371
|
+
if (timezone)
|
|
372
|
+
body.timezone = timezone;
|
|
373
|
+
const filters = filterFlag(run);
|
|
374
|
+
if (filters.length > 0)
|
|
375
|
+
body.filter = parseFilters(filters);
|
|
376
|
+
if (flags.channel !== undefined)
|
|
377
|
+
body.channels = listFlag(run, 'channel');
|
|
378
|
+
if (typeof flags.dms === 'boolean')
|
|
379
|
+
body.directMessages = flags.dms;
|
|
380
|
+
if (flags.label !== undefined)
|
|
381
|
+
body.labelNames = listFlag(run, 'label');
|
|
382
|
+
if (typeof flags.mention === 'boolean')
|
|
383
|
+
body.onMention = flags.mention;
|
|
384
|
+
if (Object.keys(body).length === 0) {
|
|
385
|
+
throw usageError('Say what to change.', `e.g. ${cli()} teams triggers edit ${team} ${key} ${ref} --prompt "…" (or --cron, --timezone, --filter, --channel, --dms, --label, --mention). To turn it on or off: ${cli()} teams triggers enable|disable ${team} ${key} ${ref}`);
|
|
386
|
+
}
|
|
387
|
+
return body;
|
|
388
|
+
}
|
|
257
389
|
function triggerBody(run, team, key) {
|
|
258
390
|
var _a, _b, _c, _d;
|
|
259
391
|
var _e, _f;
|