diff --git a/README.md b/README.md index 9b26c6cdf..fd11984b0 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,6 @@ $: npm run test - [`@microsoft/teams.api`](./packages/api/README.md) - [`@microsoft/teams.botbuilder`](./packages/botbuilder/README.md) - [`@microsoft/teams.cards`](./packages/cards/README.md) -- [`@microsoft/teams.cli`](./packages/cli/README.md) - [`@microsoft/teams.client`](./packages/client/README.md) - [`@microsoft/teams.common`](./packages/common/README.md) - [`@microsoft/teams.config`](./packages/config/README.md) @@ -94,8 +93,8 @@ $: npm run test > ℹ️ used to test the SDK or as a visual sample of how certain features can be implemented. > ⚠️ **WARNING** these apps are changed often and are not intended to be used outside the -> projects monorepo. To easily setup a new project please use the **templates** available via -> the `@microsoft/teams.cli` and follow the +> projects monorepo. To create and manage Teams apps for these samples, use the official +> Teams CLI (`@microsoft/teams.cli`) and follow the > [Getting Started](https://microsoft.github.io/teams-sdk/typescript/getting-started) documentation! - [`@examples/echo`](./examples/echo/README.md) @@ -112,4 +111,4 @@ $: npm run test ## Links - [Teams Developer Portal: Apps](https://dev.teams.microsoft.com/apps) -- [Teams Toolkit](https://www.npmjs.com/package/@microsoft/teamsapp-cli) +- [Teams CLI](https://www.npmjs.com/package/@microsoft/teams.cli) diff --git a/examples/a2a/README.md b/examples/a2a/README.md index d4f376135..4ec137806 100644 --- a/examples/a2a/README.md +++ b/examples/a2a/README.md @@ -89,6 +89,24 @@ Fill in: - `BOT_SELF_URL` — `http://localhost:` for local dev. - `PEER_NAME` / `PEER_URL` — the other bot. +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "a2a" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Run In two terminals: diff --git a/examples/ai-mcp/README.md b/examples/ai-mcp/README.md index 0232f16a4..60cfdf599 100644 --- a/examples/ai-mcp/README.md +++ b/examples/ai-mcp/README.md @@ -22,9 +22,27 @@ This is the TypeScript counterpart to the .NET [`ExtAIBot`](https://github.com/m - An **Azure OpenAI resource** with a deployed model (e.g. `gpt-4o`) and an API key. No Foundry project required. - A Teams bot registration (App ID + secret). +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "ai-mcp" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Setup -Create a `.env` in this directory: +Add the Azure OpenAI settings to the `.env` created by the CLI: ```env AZURE_OPENAI_ENDPOINT=https://.openai.azure.com diff --git a/examples/botbuilder/README.md b/examples/botbuilder/README.md index f22ccf8ea..e35514049 100644 --- a/examples/botbuilder/README.md +++ b/examples/botbuilder/README.md @@ -2,6 +2,24 @@ A bot that implements a Bot Builder Adapter. +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "botbuilder" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Run ```bash diff --git a/examples/cards/README.md b/examples/cards/README.md index 49866ed43..2ca1ddbd4 100644 --- a/examples/cards/README.md +++ b/examples/cards/README.md @@ -13,12 +13,20 @@ a demo of adaptive cards npm install ``` -To run on teams, run: +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: ```bash -npx @microsoft/teams.cli config add atk.basic +npm install -g @microsoft/teams.cli +teams --version +teams login ``` -This will add all the atk related configs. +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "cards" --endpoint "https:///api/messages" --env .env --json +``` -Then run the sample via atk. +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. diff --git a/examples/dialogs/README.md b/examples/dialogs/README.md index efd133a57..244c845b5 100644 --- a/examples/dialogs/README.md +++ b/examples/dialogs/README.md @@ -20,12 +20,20 @@ A demo of dialogs (task modules) in Teams. npm install ``` -To run on teams, run: +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: ```bash -npx @microsoft/teams.cli config add atk.basic +npm install -g @microsoft/teams.cli +teams --version +teams login ``` -This will add all the atk related configs. +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "dialogs" --endpoint "https:///api/messages" --env .env --json +``` -Then run the sample via atk. +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. diff --git a/examples/echo/README.md b/examples/echo/README.md index 825d6bff6..34eb99737 100644 --- a/examples/echo/README.md +++ b/examples/echo/README.md @@ -2,6 +2,24 @@ A bot that echos back what the user said to it. +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "echo" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Run ```bash diff --git a/examples/graph/README.md b/examples/graph/README.md index 5372d3589..fe66dceea 100644 --- a/examples/graph/README.md +++ b/examples/graph/README.md @@ -1,70 +1,104 @@ -# Auth test +# Graph auth sample -Run this first to get all the config files: +This sample demonstrates signing a user in and calling Microsoft Graph with the `userGraph` client. +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login ``` -teams config add atk.oauth + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "graph" --endpoint "https:///api/messages" --env .env --json ``` -Then run via ATK. +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. Save the `teamsAppId` and `botId` from the JSON output for the auth setup below. + +## Configure Graph auth + +This sample expects an OAuth connection named `graph`, matching `defaultConnectionName: 'graph'` in `src/index.ts`. + +Follow the Teams SDK [SSO setup guide](https://github.com/microsoft/teams-sdk/blob/main/plugins/teams-sdk/skills/teams-dev/references/guide-setup-sso.md) flow: + +1. Make sure Azure CLI is installed and signed in with the same account used for `teams login`: + + ```bash + az account show + ``` -## Teams Toolkit Configuration: Oauth +2. Check where the bot is hosted: -Use this if you want to enable user authentication in your Teams application. + ```bash + teams app bot get + ``` -## How to update scopes + If the bot is Teams-managed, migrate it to Azure first: -1. In the `aad.manifest.json` file, update the `requiredResourceAccess` list to add the required scopes. + ```bash + az group create --name --location + teams app bot migrate --resource-group + ``` -2. In the `infra/botRegistration/azurebot.bicep` file, under the `botServicesMicrosoftGraphConnection` resource, update the `properties.scopes` string to be a comma-delimited list of the required scopes. +3. Create or reuse the bot client secret from `.env`, then configure the AAD app identifier URI, `access_as_user` scope, Teams pre-authorization, and Bot Framework redirect URI as described in the SSO setup guide. -### Example +4. Create the Azure Bot OAuth connection named `graph`: + + ```bash + az bot authsetting create \ + --name \ + --resource-group \ + --setting-name "graph" \ + --service Aadv2 \ + --client-id \ + --client-secret \ + --provider-scope-string "User.Read" \ + --parameters tenantId= tokenExchangeUrl=api://botid- \ + --subscription + ``` + +5. Set the Teams app SSO identity fields: + + ```bash + teams app update \ + --web-app-info-id "" \ + --web-app-info-resource "api://botid-" + ``` + +6. Verify the setup: + + ```bash + teams app doctor + ``` + +## Updating Graph scopes + +The default OAuth connection uses `User.Read`. To request more Microsoft Graph delegated permissions, update the OAuth connection scopes in Azure Bot Service. For example: + +```bash +az bot authsetting create \ + --name \ + --resource-group \ + --setting-name "graph" \ + --service Aadv2 \ + --client-id \ + --client-secret \ + --provider-scope-string "User.Read People.Read User.ReadBasic.All" \ + --parameters tenantId= tokenExchangeUrl=api://botid- \ + --subscription +``` -If you want to add the `People.Read.All` and `User.ReadBasic.All` scopes. +> Admin consent may be required depending on the scopes you add. -1. Your `requiredResourceAccess` property should look like: +## Run -```json -"requiredResourceAccess": [ - { - "resourceAppId": "Microsoft Graph", - "resourceAccess": [ - { - "id": "People.Read.All", - "type": "Scope" - } - ] - }, - { - "resourceAppId": "Microsoft Graph", - "resourceAccess": [ - { - "id": "User.ReadBasic.All", - "type": "Scope" - } - ] - }, -] +```bash +npm run dev ``` -2. Update the `properties.scopes` to be `People.Read.All,User.ReadBasic.All`. - -## Configuring a Regional Bot -NOTE: This example uses west europe, but follow the equivalent for other locations. - -1. In `azurebot.bicep`, replace all `global` occurrences to `westeurope` -2. In `manifest.json`, in `validDomains`, `*.botframework.com` should be replaced by `europe.token.botframework.com` -2. In `aad.manifest.json`, replace `https://token.botframework.com/.auth/web/redirect` with `https://europe.token.botframework.com/.auth/web/redirect` -3. In `index.ts`, update `AppOptions` to include `apiClientSettings` - -```typescript -const app = new App({ -oauth: { -defaultConnectionName: 'graph', -}, -logger: new ConsoleLogger('@examples/auth', { level: 'debug' }), -apiClientSettings: { - oauthUrl: "https://europe.token.botframework.com", -} -}); -``` \ No newline at end of file +In Teams, send any message to start sign-in. After sign-in succeeds, the bot calls `GET /me` through Microsoft Graph and replies with the signed-in user's display name. diff --git a/examples/http-adapters/README.md b/examples/http-adapters/README.md index d15f5c330..e063ec084 100644 --- a/examples/http-adapters/README.md +++ b/examples/http-adapters/README.md @@ -12,6 +12,24 @@ An adapter bridges your HTTP framework with teams.ts. You create your server, pa - **[hono/](./hono/)** - Build a custom adapter and manage the lifecycle yourself - **[fastify/](./fastify/)** - Build a custom adapter and let App manage its lifecycle +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "http-adapters" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Running ```bash diff --git a/examples/mcp-server/README.md b/examples/mcp-server/README.md index 77db2e0f8..0f4a5cdd6 100644 --- a/examples/mcp-server/README.md +++ b/examples/mcp-server/README.md @@ -43,6 +43,24 @@ Teams AAD user id of someone in the same tenant. For the simplest setup, message the bot once with a real user, then read the user id off the first `message` activity in the server log and use that. +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "mcp-server" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Run ```bash diff --git a/examples/meetings/README.md b/examples/meetings/README.md index 66bdbabcd..78b30c333 100644 --- a/examples/meetings/README.md +++ b/examples/meetings/README.md @@ -2,6 +2,24 @@ This sample demonstrates how to handle real-time updates for meeting events and meeting participant events. +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "meetings" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Run ```bash diff --git a/examples/message-extensions/README.md b/examples/message-extensions/README.md index 91159f94f..e4e48936d 100644 --- a/examples/message-extensions/README.md +++ b/examples/message-extensions/README.md @@ -24,6 +24,24 @@ Handle events - 'message.ext.card-button-clicked'; --> +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "message-extensions" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Run ```bash diff --git a/examples/message-extensions/src/index.ts b/examples/message-extensions/src/index.ts index 7515f4c12..a22ee9cc3 100644 --- a/examples/message-extensions/src/index.ts +++ b/examples/message-extensions/src/index.ts @@ -148,7 +148,7 @@ app.on('message.ext.query-settings-url', async ({ activity }) => { type: 'openUrl', title: 'Settings', // ensure the bot endpoint is set in the environment variables - // process.env.BOT_ENDPOINT is not populated by default in the Teams Toolkit setup. + // process.env.BOT_ENDPOINT is not populated by default by the Teams CLI setup. value: `${process.env.BOT_ENDPOINT}/tabs/settings?selectedOption=${escapedSelectedOption}` } ] diff --git a/examples/proactive-messaging/README.md b/examples/proactive-messaging/README.md index 54a07fb34..3f6d0a461 100644 --- a/examples/proactive-messaging/README.md +++ b/examples/proactive-messaging/README.md @@ -2,6 +2,24 @@ Send proactive messages to Teams users without running a server. +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "proactive-messaging" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Key Concepts **Without a server:** @@ -25,8 +43,9 @@ await app.send(conversationId, 'Hello!'); 1. Set up `.env`: ``` - BOT_ID= - BOT_PASSWORD= + CLIENT_ID= + CLIENT_SECRET= + TENANT_ID= ``` 2. Run: diff --git a/examples/quoting/README.md b/examples/quoting/README.md index d45dd3f46..03a94e4fe 100644 --- a/examples/quoting/README.md +++ b/examples/quoting/README.md @@ -14,6 +14,24 @@ A bot that demonstrates various ways to quote previous messages in Microsoft Tea | `help` | Shows available commands | | *(quote a message)* | Bot reads and displays the quoted reply metadata | +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "quoting" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Run ```bash @@ -27,4 +45,5 @@ Create a `.env` file: ``` CLIENT_ID= CLIENT_SECRET= +TENANT_ID= ``` diff --git a/examples/reactions/README.md b/examples/reactions/README.md index 757414003..9c8ad6927 100644 --- a/examples/reactions/README.md +++ b/examples/reactions/README.md @@ -14,6 +14,24 @@ A bot that demonstrates how to use the ReactionClient to add and remove reaction 2. The bot will reply and add a reaction to your message 3. Add or remove reactions on bot messages to see reaction events logged +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "reactions" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Run ```bash diff --git a/examples/suggested-action/README.md b/examples/suggested-action/README.md index 671b863f2..906dfe3ce 100644 --- a/examples/suggested-action/README.md +++ b/examples/suggested-action/README.md @@ -18,6 +18,24 @@ A bot that demonstrates the `Action.Submit` suggested action and the `suggestedA `'Action.Submit'` card action type, `ISuggestedActionSubmitInvokeActivity`, and the `suggested-action.submit` route are marked `@experimental` because the underlying platform feature is still rolling out. +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "suggested-action" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Run ```bash diff --git a/examples/tab/README.md b/examples/tab/README.md index 9f3c7e782..0a0f4e852 100644 --- a/examples/tab/README.md +++ b/examples/tab/README.md @@ -2,6 +2,24 @@ A bot that hosts custom tab content. +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "tab" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Run ```bash diff --git a/examples/targeted-messages/README.md b/examples/targeted-messages/README.md index af30dd15b..99217a666 100644 --- a/examples/targeted-messages/README.md +++ b/examples/targeted-messages/README.md @@ -54,6 +54,24 @@ To make a command behave like `send private` or `send public`: That combo makes the bot treat the slash-command message as private and lets you choose whether the response should be private or public. +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "targeted-messages" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Run ```bash @@ -67,4 +85,5 @@ Create a `.env` file: ``` CLIENT_ID= CLIENT_SECRET= +TENANT_ID= ``` diff --git a/examples/threading/README.md b/examples/threading/README.md index 86154d838..44c9468e2 100644 --- a/examples/threading/README.md +++ b/examples/threading/README.md @@ -19,6 +19,24 @@ A bot that demonstrates reactive and proactive threading in Microsoft Teams chan - `test manual` does the same using `toThreadedConversationId()` + `app.send()` directly - `test proactive` and `test manual` may return a service error in conversation types that do not currently support threading (e.g. meetings) +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: + +```bash +npm install -g @microsoft/teams.cli +teams --version +teams login +``` + +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "threading" --endpoint "https:///api/messages" --env .env --json +``` + +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams. + ## Run ```bash @@ -32,4 +50,5 @@ Create a `.env` file: ``` CLIENT_ID= CLIENT_SECRET= +TENANT_ID= ``` diff --git a/package-lock.json b/package-lock.json index b1ea326c3..52817f12b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -474,6 +474,22 @@ "typescript": "^5.4.5" } }, + "examples/core": { + "name": "@examples/core", + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@microsoft/teams.apps": "*", + "@microsoft/teams.common": "*" + }, + "devDependencies": { + "@types/node": "^22.5.4", + "dotenv": "^16.4.5", + "rimraf": "^6.0.1", + "tsx": "^4.20.6", + "typescript": "^5.4.5" + } + }, "examples/dialogs": { "name": "@examples/dialogs", "version": "0.0.6", @@ -2992,6 +3008,10 @@ "resolved": "examples/cards", "link": true }, + "node_modules/@examples/core": { + "resolved": "examples/core", + "link": true + }, "node_modules/@examples/dialogs": { "resolved": "examples/dialogs", "link": true @@ -5420,10 +5440,6 @@ "resolved": "packages/cards", "link": true }, - "node_modules/@microsoft/teams.cli": { - "resolved": "packages/cli", - "link": true - }, "node_modules/@microsoft/teams.client": { "resolved": "packages/client", "link": true @@ -8538,6 +8554,7 @@ }, "node_modules/ansi-regex": { "version": "5.0.1", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -8545,6 +8562,7 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -9772,6 +9790,7 @@ }, "node_modules/cliui": { "version": "8.0.1", + "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -9784,6 +9803,7 @@ }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "7.0.0", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -9854,6 +9874,7 @@ }, "node_modules/color-convert": { "version": "2.0.1", + "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -9864,6 +9885,7 @@ }, "node_modules/color-name": { "version": "1.1.4", + "dev": true, "license": "MIT" }, "node_modules/colorette": { @@ -10726,6 +10748,7 @@ }, "node_modules/emoji-regex": { "version": "8.0.0", + "dev": true, "license": "MIT" }, "node_modules/encodeurl": { @@ -11385,6 +11408,7 @@ }, "node_modules/escalade": { "version": "3.2.0", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -12334,6 +12358,7 @@ }, "node_modules/get-caller-file": { "version": "2.0.5", + "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -13168,6 +13193,7 @@ }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -17173,6 +17199,7 @@ }, "node_modules/require-directory": { "version": "2.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -18364,6 +18391,7 @@ }, "node_modules/string-width": { "version": "4.2.3", + "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -18441,6 +18469,7 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -20053,6 +20082,7 @@ }, "node_modules/y18n": { "version": "5.0.8", + "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -20084,6 +20114,7 @@ }, "node_modules/yargs": { "version": "17.7.2", + "dev": true, "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -20564,40 +20595,6 @@ "node": ">=20" } }, - "packages/cli": { - "name": "@microsoft/teams.cli", - "version": "0.0.0", - "license": "MIT", - "dependencies": { - "@microsoft/teams.common": "*", - "change-case": "^5.4.4", - "handlebars": "^4.7.9", - "yaml": "^2.8.3", - "yargs": "^17.7.2", - "zod": "^3.24.2" - }, - "bin": { - "teams": "dist/index.js" - }, - "devDependencies": { - "@microsoft/teams.config": "*", - "@types/jest": "^29.5.12", - "@types/node": "^22.10.7", - "@types/yargs": "^17.0.33", - "jest": "^29.7.0", - "rimraf": "^6.0.1", - "ts-jest": "^29.2.5", - "tsup": "^8.4.0", - "typescript": "^5.4.5" - }, - "engines": { - "node": ">=20" - } - }, - "packages/cli/node_modules/change-case": { - "version": "5.4.4", - "license": "MIT" - }, "packages/client": { "name": "@microsoft/teams.client", "version": "0.0.0", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md deleted file mode 100644 index 687337f9d..000000000 --- a/packages/cli/CHANGELOG.md +++ /dev/null @@ -1,420 +0,0 @@ -# @microsoft/teams.cli - -## 2.0.5 - -### Patch Changes - -- Bug fixes and minor improvements -- Updated dependencies - - @microsoft/teams.common@2.0.5 - -## 2.0.4 - -### Patch Changes - -- Fix backward compat issue with TokenCredentials -- Updated dependencies - - @microsoft/teams.common@2.0.4 - -## 2.0.3 - -### Patch Changes - -- Regional oauth support, additional auth mechanisms support, resync graph endpoints -- Updated dependencies - - @microsoft/teams.common@2.0.3 - -## 2.0.2 - -### Patch Changes - -- Number of bug fixes and CLI improvements -- Updated dependencies - - @microsoft/teams.common@2.0.2 - -## 2.0.1 - -### Patch Changes - -- Update templates to use latest instad of preview -- Updated dependencies - - @microsoft/teams.common@2.0.1 - -## 2.0.0 - -- First Stable V2 Release - -### Major Changes - -- 1d5f350: v2 preview release - -### Patch Changes - -- a231813: Variety of security fixes. - Now every incoming request to the server is validated to ensure that it is coming from a trusted source. - Other minor fixes and improvements. -- 05085e8: streaming bug fix -- 7a0e5f6: fix cli template versions -- 9bc2cee: - Add streamable http support to MCPClient - - Adds a way to "send" messages from a tab-app to the associated conversation -- 9b08518: add csharp support to CLI officially, add a2a support via new package, devtools updates -- 00d3edb: Python additions to CLI, A2A package bump to 0.3.0 -- ee61ca0: - Update graph packages to be tree-shakeable and use different calling strategy - - Minor bug fixes -- 70cb729: Disable automatic function calling, and show structured output -- 2337a4f: Add MCP client template -- e6f9b56: - Added user-token in activity context - - For app-graph, use tenant-specific tokens to make graph calls - - Fixed ATK issues related to multi-tenant deprecation - - Fixed bot-builder adapter which broke in the last release -- 9e2414b: cli template updates; botbuilder plugin custom server options; system route overrides; -- 753af04: Integrate Adaptive Cards designer with DevTools, some bug fixes, naming updates -- Updated dependencies [a231813] -- Updated dependencies [05085e8] -- Updated dependencies [7a0e5f6] -- Updated dependencies [1d5f350] -- Updated dependencies [9bc2cee] -- Updated dependencies [9b08518] -- Updated dependencies [00d3edb] -- Updated dependencies [ee61ca0] -- Updated dependencies [70cb729] -- Updated dependencies [2337a4f] -- Updated dependencies [e6f9b56] -- Updated dependencies [9e2414b] -- Updated dependencies [753af04] - - @microsoft/teams.common@2.0.0 - -## 2.0.0-preview.12 - -### Patch Changes - -- Python additions to CLI, A2A package bump to 0.3.0 -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.12 - -## 2.0.0-preview.11 - -### Patch Changes - -- cli template updates; botbuilder plugin custom server options; system route overrides; -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.11 - -## 2.0.0-preview.10 - -### Patch Changes - -- - Update graph packages to be tree-shakeable and use different calling strategy - - Minor bug fixes -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.10 - -## 2.0.0-preview.9 - -### Patch Changes - -- A number of auth related fixes, ATK fixes due to multi-tenant deprecation, and a streaming fix -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.9 - -## 2.0.0-preview.8 - -### Patch Changes - -- Variety of security fixes. - Now every incoming request to the server is validated to ensure that it is coming from a trusted source. - Other minor fixes and improvements. -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.8 - -## 2.0.0-preview.7 - -### Patch Changes - -- - Add streamable http support to MCPClient - - Adds a way to "send" messages from a tab-app to the associated conversation -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.7 - -## 2.0.0-preview.6 - -### Patch Changes - -- Disable automatic function calling, and show structured output -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.6 - -## 2.0.0-preview.5 - -### Patch Changes - -- streaming bug fix -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.5 - -## 2.0.0-preview.4 - -### Patch Changes - -- Integrate Adaptive Cards designer with DevTools, some bug fixes, naming updates -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.4 - -## 2.0.0-preview.3 - -### Patch Changes - -- add csharp support to CLI officially, add a2a support via new package, devtools updates -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.3 - -## 2.0.0-preview.2 - -### Patch Changes - -- Add MCP client template -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.2 - -## 2.0.0-preview.1 - -### Patch Changes - -- fix cli template versions -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.1 - -## 2.0.0-preview.0 - -### Major Changes - -- v2 preview release - -### Patch Changes - -- Updated dependencies - - @microsoft/teams.common@2.0.0-preview.0 - -## 0.2.14 - -### Patch Changes - -- fix cli bug and add mcp client customizations like headers and logging -- Updated dependencies - - @microsoft/teams.common@0.2.14 - -## 0.2.13 - -### Patch Changes - -- bugfixes, devtools updates, mcp client updates -- Updated dependencies - - @microsoft/teams.common@0.2.13 - -## 0.2.12 - -### Patch Changes - -- app startup fetch token bugfix -- Updated dependencies - - @microsoft/teams.common@0.2.12 - -## 0.2.11 - -### Patch Changes - -- dev plugin bug fix -- Updated dependencies - - @microsoft/teams.common@0.2.11 - -## 0.2.10 - -### Patch Changes - -- fix docs links and fix a couple minor issues -- Updated dependencies - - @microsoft/teams.common@0.2.10 - -## 0.2.9 - -### Patch Changes - -- config fetch response fix -- Updated dependencies - - @microsoft/teams.common@0.2.9 - -## 0.2.8 - -### Patch Changes - -- fix docs links -- Updated dependencies - - @microsoft/teams.common@0.2.8 - -## 0.2.7 - -### Patch Changes - -- package rename -- Updated dependencies - - @microsoft/teams.common@0.2.7 - -## 0.2.6 - -### Patch Changes - -- fix cli for lower node versions -- Updated dependencies - - @microsoft/teams.common@0.2.6 - -## 0.2.5 - -### Patch Changes - -- add mcp client, ai plugins, devtools improvements -- Updated dependencies - - @microsoft/teams.common@0.2.5 - -## 0.2.4 - -### Patch Changes - -- fix reflect-metadata dependency -- Updated dependencies - - @microsoft/teams.common@0.2.4 - -## 0.2.3 - -### Patch Changes - -- devtools fixes, plugins refactor, ai package fixes, new cli ttk configuration -- Updated dependencies - - @microsoft/teams.common@0.2.3 - -## 0.2.2 - -### Patch Changes - -- add mcp package and update ai package with use method -- Updated dependencies - - @microsoft/teams.common@0.2.2 - -## 0.2.1 - -### Patch Changes - -- change @azure/openai from peer dependency to regular -- Updated dependencies - - @microsoft/teams.common@0.2.1 - -## 0.2.0 - -### Minor Changes - -- refactor ai package interface, devtools updates - -### Patch Changes - -- Updated dependencies - - @microsoft/teams.common@0.2.0 - -## 0.1.3 - -### Patch Changes - -- add template logic to cli for more accurate templates/configs -- Updated dependencies - - @microsoft/teams.common@0.1.3 - -## 0.1.2 - -### Patch Changes - -- fix bug in `next` routing method -- Updated dependencies - - @microsoft/teams.ai@0.1.2 - - @microsoft/teams.common@0.1.2 - - @microsoft/teams.openai@0.1.2 - -## 0.1.1 - -### Patch Changes - -- adaptive cards action invoke response fix, tests for cards -- Updated dependencies - - @microsoft/teams.ai@0.1.1 - - @microsoft/teams.common@0.1.1 - - @microsoft/teams.openai@0.1.1 - -## 0.1.0 - -### Minor Changes - -- devtools fixes, breaking type changes due to rename/refactor - -### Patch Changes - -- Updated dependencies - - @microsoft/teams.ai@0.1.0 - - @microsoft/teams.common@0.1.0 - - @microsoft/teams.openai@0.1.0 - -## 0.0.6 - -### Patch Changes - -- fix middleware bug in removeMentionsText -- Updated dependencies - - @microsoft/teams.ai@0.0.6 - - @microsoft/teams.common@0.0.6 - - @microsoft/teams.openai@0.0.6 - -## 0.0.5 - -### Patch Changes - -- add removeMentionsText util and middleware, update docs -- Updated dependencies - - @microsoft/teams.ai@0.0.5 - - @microsoft/teams.common@0.0.5 - - @microsoft/teams.openai@0.0.5 - -## 0.0.4 - -### Patch Changes - -- fix auth credential error -- Updated dependencies - - @microsoft/teams.ai@0.0.4 - - @microsoft/teams.common@0.0.4 - - @microsoft/teams.openai@0.0.4 - -## 0.0.3 - -### Patch Changes - -- add support for more types of bot authentication, devtools fixes -- Updated dependencies - - @microsoft/teams.ai@0.0.3 - - @microsoft/teams.common@0.0.3 - - @microsoft/teams.openai@0.0.3 - -## 0.0.2 - -### Patch Changes - -- fix cli binary name -- Updated dependencies - - @microsoft/teams.ai@0.0.2 - - @microsoft/teams.common@0.0.2 - - @microsoft/teams.openai@0.0.2 - -## 0.0.1 - -### Patch Changes - -- port to new repository -- Updated dependencies - - @microsoft/teams.ai@0.0.1 - - @microsoft/teams.common@0.0.1 - - @microsoft/teams.openai@0.0.1 diff --git a/packages/cli/README.md b/packages/cli/README.md deleted file mode 100644 index 3ecf7bcde..000000000 --- a/packages/cli/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Teams: CLI - -

- - - - - - - - - - - - - - - -

- -A cli for building apps using `@microsoft/teams.ts`. - - - - - -## Install - -```bash -$: npm install @microsoft/teams.cli -``` - -## Dependencies - -N/A diff --git a/packages/cli/configs/atk/basic/csharp/TeamsApp/README.md b/packages/cli/configs/atk/basic/csharp/TeamsApp/README.md deleted file mode 100644 index b037c7d93..000000000 --- a/packages/cli/configs/atk/basic/csharp/TeamsApp/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# Welcome to M365 Agents Toolkit! - -## Pre-requisites - -- [Visual Studio v17.14.0 or above](https://visualstudio.microsoft.com/vs/) -- [M365 Agents Toolkit Extension for Visual Studio](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/toolkit-v4/install-teams-toolkit-vs) - -## Quick Start - -1. In the debug dropdown menu, select Dev Tunnels > Create A Tunnel (set authentication type to Public) or select an existing public dev tunnel -
![image](https://raw.githubusercontent.com/OfficeDev/TeamsFx/dev/docs/images/visualstudio/debug/create-devtunnel-button.png) -2. Right-click the 'TeamsApp' project in Solution Explorer and select **M365 Agents Toolkit > Select Microsoft 365 Account** -3. Sign in to M365 Agents Toolkit with a **Microsoft 365 work or school account** -4. Configure the Launch profile to be `Microsoft Teams (Browser)`. -5. Press F5, or select Debug > Start Debugging menu in Visual Studio to start your app. -
![image](https://raw.githubusercontent.com/OfficeDev/TeamsFx/dev/docs/images/visualstudio/debug/debug-button.png) -5. In the opened web browser, select Add button to install the app in Teams. - - -## Get more info - -New to Teams app development or M365 Agents Toolkit? Explore Teams app manifests, cloud deployment, and much more in the https://aka.ms/teams-toolkit-vs-docs. - -## Report an issue - -Select Visual Studio > Help > Send Feedback > Report a Problem. -Or, create an issue directly in our GitHub repository: -https://github.com/OfficeDev/TeamsFx/issues diff --git a/packages/cli/configs/atk/basic/csharp/TeamsApp/TeamsApp.ttkproj b/packages/cli/configs/atk/basic/csharp/TeamsApp/TeamsApp.ttkproj deleted file mode 100644 index 8a2ed2ae5..000000000 --- a/packages/cli/configs/atk/basic/csharp/TeamsApp/TeamsApp.ttkproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - 3df7dbbf-6757-c96e-d6ec-3928332da9e0 - - - - - \ No newline at end of file diff --git a/packages/cli/configs/atk/basic/csharp/TeamsApp/appPackage/color.png b/packages/cli/configs/atk/basic/csharp/TeamsApp/appPackage/color.png deleted file mode 100644 index 01aa37e34..000000000 Binary files a/packages/cli/configs/atk/basic/csharp/TeamsApp/appPackage/color.png and /dev/null differ diff --git a/packages/cli/configs/atk/basic/csharp/TeamsApp/appPackage/manifest.json.hbs b/packages/cli/configs/atk/basic/csharp/TeamsApp/appPackage/manifest.json.hbs deleted file mode 100644 index ca10dbe80..000000000 --- a/packages/cli/configs/atk/basic/csharp/TeamsApp/appPackage/manifest.json.hbs +++ /dev/null @@ -1,55 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.25/MicrosoftTeams.schema.json", - "version": "1.0.0", - "manifestVersion": "1.25", - "id": "$\{{TEAMS_APP_ID}}", - "name": { - "short": "{{ toKebabCase name }}-$\{{APP_NAME_SUFFIX}}", - "full": "{{ capitalize name }}" - }, - "developer": { - "name": "Microsoft", - "mpnId": "", - "websiteUrl": "https://microsoft.com", - "privacyUrl": "https://privacy.microsoft.com/privacystatement", - "termsOfUseUrl": "https://www.microsoft.com/legal/terms-of-use" - }, - "description": { - "short": "Sample bot that repeats back what you say", - "full": "Sample bot that repeats back what you say" - }, - "icons": { - "outline": "outline.png", - "color": "color.png" - }, - "accentColor": "#FFFFFF", - "staticTabs": [ - { - "entityId": "conversations", - "scopes": ["personal"] - }, - { - "entityId": "about", - "scopes": ["personal"] - } - ], - "bots": [ - { - "botId": "$\{{BOT_ID}}", - "scopes": ["personal", "team", "groupChat"], - "isNotificationOnly": false, - "supportsCalling": false, - "supportsVideo": false, - "supportsFiles": false - } - ], - "validDomains": [ - "$\{{BOT_DOMAIN}}", - "*.botframework.com" - ], - "webApplicationInfo": { - "id": "$\{{BOT_ID}}", - "resource": "api://botid-$\{{BOT_ID}}" - }, - "supportsChannelFeatures": "tier1" -} diff --git a/packages/cli/configs/atk/basic/csharp/TeamsApp/appPackage/outline.png b/packages/cli/configs/atk/basic/csharp/TeamsApp/appPackage/outline.png deleted file mode 100644 index f7a4c8644..000000000 Binary files a/packages/cli/configs/atk/basic/csharp/TeamsApp/appPackage/outline.png and /dev/null differ diff --git a/packages/cli/configs/atk/basic/csharp/TeamsApp/env/.env.dev b/packages/cli/configs/atk/basic/csharp/TeamsApp/env/.env.dev deleted file mode 100644 index 4b07861c0..000000000 --- a/packages/cli/configs/atk/basic/csharp/TeamsApp/env/.env.dev +++ /dev/null @@ -1,16 +0,0 @@ -# This file includes environment variables that will be committed to git by default. - -# Built-in environment variables -TEAMSFX_ENV=dev -APP_NAME_SUFFIX=dev - -# Updating AZURE_SUBSCRIPTION_ID or AZURE_RESOURCE_GROUP_NAME after provision may also require an update to RESOURCE_SUFFIX, because some services require a globally unique name across subscriptions/resource groups. -AZURE_SUBSCRIPTION_ID= -AZURE_RESOURCE_GROUP_NAME= -RESOURCE_SUFFIX= - -# Generated during provision, you can also add your own variables. -BOT_ID= -TEAMS_APP_ID= -BOT_AZURE_APP_SERVICE_RESOURCE_ID= -BOT_DOMAIN= \ No newline at end of file diff --git a/packages/cli/configs/atk/basic/csharp/TeamsApp/infra/azure.bicep b/packages/cli/configs/atk/basic/csharp/TeamsApp/infra/azure.bicep deleted file mode 100644 index 705d5881e..000000000 --- a/packages/cli/configs/atk/basic/csharp/TeamsApp/infra/azure.bicep +++ /dev/null @@ -1,95 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -param webAppSKU string - -@maxLength(42) -param botDisplayName string - -param serverfarmsName string = resourceBaseName -param webAppName string = resourceBaseName -param identityName string = resourceBaseName -param location string = resourceGroup().location - -resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - location: location - name: identityName -} - -// Compute resources for your Web App -resource serverfarm 'Microsoft.Web/serverfarms@2021-02-01' = { - kind: 'app' - location: location - name: serverfarmsName - sku: { - name: webAppSKU - } -} - -// Web App that hosts your agent -resource webApp 'Microsoft.Web/sites@2021-02-01' = { - kind: 'app' - location: location - name: webAppName - properties: { - serverFarmId: serverfarm.id - httpsOnly: true - siteConfig: { - alwaysOn: true - appSettings: [ - { - name: 'WEBSITE_RUN_FROM_PACKAGE' - value: '1' // Run Azure APP Service from a package file - } - { - name: 'WEBSITE_NODE_DEFAULT_VERSION' - value: '~20' // Set NodeJS version to 20.x for your site - } - { - name: 'RUNNING_ON_AZURE' - value: '1' - } - { - name: 'CLIENT_ID' - value: identity.properties.clientId - } - { - name: 'TENANT_ID' - value: identity.properties.tenantId - } - { - name: 'BOT_TYPE' - value: 'UserAssignedMsi' - } - ] - ftpsState: 'FtpsOnly' - } - } - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${identity.id}': {} - } - } -} - -// Register your web service as a bot with the Bot Framework -module azureBotRegistration './botRegistration/azurebot.bicep' = { - name: 'Azure-Bot-registration' - params: { - resourceBaseName: resourceBaseName - identityClientId: identity.properties.clientId - identityResourceId: identity.id - identityTenantId: identity.properties.tenantId - botAppDomain: webApp.properties.defaultHostName - botDisplayName: botDisplayName - } -} - -// The output will be persisted in .env.{envName}. Visit https://aka.ms/teamsfx-actions/arm-deploy for more details. -output BOT_AZURE_APP_SERVICE_RESOURCE_ID string = webApp.id -output BOT_DOMAIN string = webApp.properties.defaultHostName -output BOT_ID string = identity.properties.clientId -output BOT_TENANT_ID string = identity.properties.tenantId diff --git a/packages/cli/configs/atk/basic/csharp/TeamsApp/infra/azure.parameters.json.hbs b/packages/cli/configs/atk/basic/csharp/TeamsApp/infra/azure.parameters.json.hbs deleted file mode 100644 index 7b5ba26e9..000000000 --- a/packages/cli/configs/atk/basic/csharp/TeamsApp/infra/azure.parameters.json.hbs +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "resourceBaseName": { - "value": "bot$\{{RESOURCE_SUFFIX}}" - }, - "webAppSKU": { - "value": "B1" - }, - "botDisplayName": { - "value": "{{ toPascalCase name }}Infra" - } - } -} diff --git a/packages/cli/configs/atk/basic/csharp/TeamsApp/infra/botRegistration/azurebot.bicep b/packages/cli/configs/atk/basic/csharp/TeamsApp/infra/botRegistration/azurebot.bicep deleted file mode 100644 index f0343e34d..000000000 --- a/packages/cli/configs/atk/basic/csharp/TeamsApp/infra/botRegistration/azurebot.bicep +++ /dev/null @@ -1,42 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -@maxLength(42) -param botDisplayName string - -param botServiceName string = resourceBaseName -param botServiceSku string = 'F0' -param identityResourceId string -param identityClientId string -param identityTenantId string -param botAppDomain string - -// Register your web service as a bot with the Bot Framework -resource botService 'Microsoft.BotService/botServices@2021-03-01' = { - kind: 'azurebot' - location: 'global' - name: botServiceName - properties: { - displayName: botDisplayName - endpoint: 'https://${botAppDomain}/api/messages' - msaAppId: identityClientId - msaAppMSIResourceId: identityResourceId - msaAppTenantId: identityTenantId - msaAppType: 'UserAssignedMSI' - } - sku: { - name: botServiceSku - } -} - -// Connect the bot service to Microsoft Teams -resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = { - parent: botService - location: 'global' - name: 'MsTeamsChannel' - properties: { - channelName: 'MsTeamsChannel' - } -} diff --git a/packages/cli/configs/atk/basic/csharp/TeamsApp/teamsapp.local.yml.hbs b/packages/cli/configs/atk/basic/csharp/TeamsApp/teamsapp.local.yml.hbs deleted file mode 100644 index c63c7ef08..000000000 --- a/packages/cli/configs/atk/basic/csharp/TeamsApp/teamsapp.local.yml.hbs +++ /dev/null @@ -1,76 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/v1.7/yaml.schema.json -# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file -# Visit https://aka.ms/teamsfx-actions for details on actions -version: v1.7 - -provision: - # Creates a Teams app - - uses: teamsApp/create - with: - # Teams app name - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - # Write the information of created resources into environment file for - # the specified environment variable(s). - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID - - # Create or reuse an existing Microsoft Entra application for bot. - - uses: aadApp/create - with: - # The Microsoft Entra application's display name - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - generateClientSecret: true - signInAudience: AzureADMultipleOrgs - writeToEnvironmentFile: - # The Microsoft Entra application's client id created for bot. - clientId: BOT_ID - # The Microsoft Entra application's client secret created for bot. - clientSecret: SECRET_BOT_PASSWORD - # The Microsoft Entra application's object id created for bot. - objectId: BOT_OBJECT_ID - - # Generate runtime appsettings to JSON file - - uses: file/createOrUpdateJsonFile - with: - target: ../{{name}}/appsettings.Development.json - content: - Teams: - ClientId: $\{{BOT_ID}} - ClientSecret: $\{{SECRET_BOT_PASSWORD}} - - # Create or update the bot registration on dev.botframework.com - - uses: botFramework/create - with: - botId: $\{{BOT_ID}} - name: {{ toPascalCase name }} - messagingEndpoint: $\{{BOT_ENDPOINT}}/api/messages - description: "" - channels: - - name: msteams - - # Validate using manifest schema - - uses: teamsApp/validateManifest - with: - # Path to manifest template - manifestPath: ./appPackage/manifest.json - # Build Teams app package with latest env value - - uses: teamsApp/zipAppPackage - with: - # Path to manifest template - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputFolder: ./appPackage/build - # Validate app package using validation rules - - uses: teamsApp/validateAppPackage - with: - # Relative path to this file. This is the path for built zip file. - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - - # Apply the Teams app manifest to an existing Teams app in - # Teams Developer Portal. - # Will use the app id in manifest file to determine which Teams app to update. - - uses: teamsApp/update - with: - # Relative path to this file. This is the path for built zip file. - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - diff --git a/packages/cli/configs/atk/basic/csharp/TeamsApp/teamsapp.yml.hbs b/packages/cli/configs/atk/basic/csharp/TeamsApp/teamsapp.yml.hbs deleted file mode 100644 index ad74ba5df..000000000 --- a/packages/cli/configs/atk/basic/csharp/TeamsApp/teamsapp.yml.hbs +++ /dev/null @@ -1,88 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/v1.7/yaml.schema.json -# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file -# Visit https://aka.ms/teamsfx-actions for details on actions -version: v1.7 - -environmentFolderPath: ./env - -# Triggered when 'teamsapp provision' is executed -provision: - # Creates a Teams app - - uses: teamsApp/create - with: - # Teams app name - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - # Write the information of created resources into environment file for - # the specified environment variable(s). - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID - - - uses: arm/deploy # Deploy given ARM templates parallelly. - with: - # AZURE_SUBSCRIPTION_ID is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select a subscription. - # Referencing other environment variables with empty values - # will skip the subscription selection prompt. - subscriptionId: $\{{AZURE_SUBSCRIPTION_ID}} - # AZURE_RESOURCE_GROUP_NAME is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select or create one - # resource group. - # Referencing other environment variables with empty values - # will skip the resource group selection prompt. - resourceGroupName: $\{{AZURE_RESOURCE_GROUP_NAME}} - templates: - - path: ./infra/azure.bicep # Relative path to this file - # Relative path to this yaml file. - # Placeholders will be replaced with corresponding environment - # variable before ARM deployment. - parameters: ./infra/azure.parameters.json - # Required when deploying ARM template - deploymentName: Create-resources-for-bot - # M365 Agents Toolkit will download this bicep CLI version from github for you, - # will use bicep CLI in PATH if you remove this config. - bicepCliVersion: v0.9.1 - - # Validate using manifest schema - - uses: teamsApp/validateManifest - with: - # Path to manifest template - manifestPath: ./appPackage/manifest.json - # Build Teams app package with latest env value - - uses: teamsApp/zipAppPackage - with: - # Path to manifest template - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputFolder: ./appPackage/build - # Validate app package using validation rules - - uses: teamsApp/validateAppPackage - with: - # Relative path to this file. This is the path for built zip file. - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - # Apply the Teams app manifest to an existing Teams app in - # Teams Developer Portal. - # Will use the app id in manifest file to determine which Teams app to update. - - uses: teamsApp/update - with: - # Relative path to this file. This is the path for built zip file. - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - -# Triggered when 'teamsapp deploy' is executed -deploy: - - uses: cli/runDotnetCommand - with: - args: publish --configuration Release {{name}}/{{name}}.csproj - workingDirectory: ../ - # Deploy your application to Azure App Service using the zip deploy feature. - # For additional details, refer to https://aka.ms/zip-deploy-to-app-services. - - uses: azureAppService/zipDeploy - with: - # Deploy base folder - artifactFolder: {{name}}/bin/Release/net10.0/publish - # The resource id of the cloud resource to be deployed to. - # This key will be generated by arm/deploy action automatically. - # You can replace it with your existing Azure Resource id - # or add it to your environment variable file. - resourceId: $\{{BOT_AZURE_APP_SERVICE_RESOURCE_ID}} - workingDirectory: ../ -projectId: 2f69f4d5-d528-4510-b231-91456094b6a8 diff --git a/packages/cli/configs/atk/basic/python/.vscode/launch.json b/packages/cli/configs/atk/basic/python/.vscode/launch.json deleted file mode 100644 index ae4591536..000000000 --- a/packages/cli/configs/atk/basic/python/.vscode/launch.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Launch Remote (Edge)", - "type": "msedge", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "remote", - "order": 1 - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch Remote (Chrome)", - "type": "chrome", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "remote", - "order": 2 - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch App (Edge)", - "type": "msedge", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch App (Chrome)", - "type": "chrome", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Start", - "type": "debugpy", - "request": "launch", - "python": "${workspaceFolder}/.venv/bin/python", - "program": "${workspaceFolder}/src/main.py", - "console": "integratedTerminal" - }, - { - "name": "Start Test Tool", - "type": "node", - "request": "launch", - "runtimeExecutable": "${workspaceFolder}/devTools/teamsapptester/node_modules/.bin/teamsapptester", - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "skipFiles": ["/**"] - } - ], - "compounds": [ - { - "name": "Debug (Edge)", - "configurations": ["Launch App (Edge)", "Start"], - "preLaunchTask": "Start Teams App Locally", - "presentation": { - "group": "all", - "order": 1 - }, - "stopAll": true - }, - { - "name": "Debug (Chrome)", - "configurations": ["Launch App (Chrome)" , "Start"], - "preLaunchTask": "Start Teams App Locally", - "presentation": { - "group": "all", - "order": 2 - }, - "stopAll": true - }, - { - "name": "Debug in Test Tool", - "configurations": ["Start", "Start Test Tool"], - "preLaunchTask": "Start Teams App (Test Tool)", - "presentation": { - "group": "local", - "order": 1 - }, - "stopAll": true - } - ] -} diff --git a/packages/cli/configs/atk/basic/python/.vscode/tasks.json b/packages/cli/configs/atk/basic/python/.vscode/tasks.json deleted file mode 100644 index aa3fc1c17..000000000 --- a/packages/cli/configs/atk/basic/python/.vscode/tasks.json +++ /dev/null @@ -1,114 +0,0 @@ -// This file is automatically generated by M365 Agents Toolkit. -// The teamsfx tasks defined in this file require M365 Agents Toolkit version >= 5.0.0. -// See https://aka.ms/teamsfx-tasks for details on how to customize each task. -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Start Teams App Locally", - "dependsOn": [ - "Validate prerequisites", - "Start local tunnel", - "Provision", - "Deploy", - "setup-env" - ], - "dependsOrder": "sequence" - }, - { - "label": "Validate prerequisites", - "type": "teamsfx", - "command": "debug-check-prerequisites", - "args": { - "prerequisites": [ - "python", - "m365Account", - "portOccupancy" - ], - "portOccupancy": [ - 3978 - ] - } - }, - { - "label": "Start local tunnel", - "type": "teamsfx", - "command": "debug-start-local-tunnel", - "args": { - "type": "dev-tunnel", - "ports": [ - { - "portNumber": 3978, - "protocol": "http", - "access": "public", - "writeToEnvironmentFile": { - "endpoint": "BOT_ENDPOINT", - "domain": "BOT_DOMAIN" - } - } - ], - "env": "local" - }, - "isBackground": true, - "problemMatcher": "$teamsfx-local-tunnel-watch" - }, - { - "label": "Provision", - "type": "teamsfx", - "command": "provision", - "args": { - "env": "local" - } - }, - { - "label": "Deploy", - "type": "teamsfx", - "command": "deploy", - "args": { - "env": "local" - } - }, - { - "label": "setup-env", - "type": "shell", - "command": "pip install -e .", - "problemMatcher": [], - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "label": "Start Teams App (Test Tool)", - "dependsOn": [ - "Validate prerequisites (Test Tool)", - "Deploy (Test Tool)", - "setup-env" - ], - "dependsOrder": "sequence" - }, - { - "label": "Validate prerequisites (Test Tool)", - "type": "teamsfx", - "command": "debug-check-prerequisites", - "args": { - "prerequisites": [ - "python", - "portOccupancy" - ], - "portOccupancy": [ - 3978, - 56150 - ] - } - }, - { - "label": "Deploy (Test Tool)", - "type": "teamsfx", - "command": "deploy", - "args": { - "env": "testtool" - } - } - ] -} diff --git a/packages/cli/configs/atk/basic/python/env/.env.dev b/packages/cli/configs/atk/basic/python/env/.env.dev deleted file mode 100644 index 7bc662ca9..000000000 --- a/packages/cli/configs/atk/basic/python/env/.env.dev +++ /dev/null @@ -1,16 +0,0 @@ -# Built-in environment variables -TEAMSFX_ENV=dev -APP_NAME_SUFFIX=dev - -# Updating AZURE_SUBSCRIPTION_ID or AZURE_RESOURCE_GROUP_NAME after provision may also require an update to RESOURCE_SUFFIX, because some services require a globally unique name across subscriptions/resource groups. -AZURE_SUBSCRIPTION_ID= -AZURE_RESOURCE_GROUP_NAME= -RESOURCE_SUFFIX= - -TEAMS_APP_ID= -TEAMS_APP_TENANT_ID= -BOT_ID= -AAD_APP_OBJECT_ID= -AAD_APP_TENANT_ID= -BOT_AZURE_APP_SERVICE_RESOURCE_ID= -BOT_DOMAIN= diff --git a/packages/cli/configs/atk/basic/python/env/.env.testtool b/packages/cli/configs/atk/basic/python/env/.env.testtool deleted file mode 100644 index c82bc5257..000000000 --- a/packages/cli/configs/atk/basic/python/env/.env.testtool +++ /dev/null @@ -1,5 +0,0 @@ -TEAMSFX_ENV=testtool - -# Environment variables used by test tool -TEAMSAPPTESTER_PORT=56150 -TEAMSFX_NOTIFICATION_STORE_FILENAME=.notification.testtoolstore.json diff --git a/packages/cli/configs/atk/basic/python/infra/azure.bicep b/packages/cli/configs/atk/basic/python/infra/azure.bicep deleted file mode 100644 index 781290da7..000000000 --- a/packages/cli/configs/atk/basic/python/infra/azure.bicep +++ /dev/null @@ -1,86 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -@description('Required when create Azure Bot service') -param botAadAppClientId string - -@secure() -@description('Required by Bot Framework package in your bot project') -param botAadAppClientSecret string - -@maxLength(42) -param botDisplayName string - -param webAppSKU string -param linuxFxVersion string -param tenantId string - -param serverfarmsName string = resourceBaseName -param webAppName string = resourceBaseName -param location string = resourceGroup().location -param pythonVersion string = linuxFxVersion - -// Compute resources for your Web App -resource serverfarm 'Microsoft.Web/serverfarms@2021-02-01' = { - kind: 'app,linux' - location: location - name: serverfarmsName - sku: { - name: webAppSKU - } - properties:{ - reserved: true - } -} - -// Web App that hosts your agent -// Web App that hosts your bot -resource webApp 'Microsoft.Web/sites@2021-02-01' = { - kind: 'app,linux' - location: location - name: webAppName - properties: { - serverFarmId: serverfarm.id - siteConfig: { - alwaysOn: true - appCommandLine: 'python main.py' - linuxFxVersion: pythonVersion - appSettings: [ - { - name: 'SCM_DO_BUILD_DURING_DEPLOYMENT' - value: 'true' - } - { - name: 'CLIENT_ID' - value: botAadAppClientId - } - { - name: 'CLIENT_SECRET' - value: botAadAppClientSecret - } - { - name: 'TENANT_ID' - value: tenantId - } - ] - ftpsState: 'FtpsOnly' - } - } -} - -// Register your web service as a bot with the Bot Framework -module azureBotRegistration './botRegistration/azurebot.bicep' = { - name: 'Azure-Bot-registration' - params: { - resourceBaseName: resourceBaseName - botAadAppClientId: botAadAppClientId - botAppDomain: webApp.properties.defaultHostName - botDisplayName: botDisplayName - tenantId: tenantId - } -} - -output BOT_AZURE_APP_SERVICE_RESOURCE_ID string = webApp.id -output BOT_DOMAIN string = webApp.properties.defaultHostName diff --git a/packages/cli/configs/atk/basic/python/infra/azure.parameters.json.hbs b/packages/cli/configs/atk/basic/python/infra/azure.parameters.json.hbs deleted file mode 100644 index dc6d49a4f..000000000 --- a/packages/cli/configs/atk/basic/python/infra/azure.parameters.json.hbs +++ /dev/null @@ -1,27 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "resourceBaseName": { - "value": "bot$\{{RESOURCE_SUFFIX}}" - }, - "webAppSKU": { - "value": "B1" - }, - "botAadAppClientId": { - "value": "$\{{BOT_ID}}" - }, - "botAadAppClientSecret": { - "value": "$\{{SECRET_BOT_PASSWORD}}" - }, - "tenantId": { - "value": "$\{{AAD_APP_TENANT_ID}}" - }, - "linuxFxVersion": { - "value": "PYTHON|3.12" - }, - "botDisplayName": { - "value": "{{ toPascalCase name }}Infra" - } - } -} diff --git a/packages/cli/configs/atk/basic/python/infra/botRegistration/azurebot.bicep b/packages/cli/configs/atk/basic/python/infra/botRegistration/azurebot.bicep deleted file mode 100644 index 1627e0dfa..000000000 --- a/packages/cli/configs/atk/basic/python/infra/botRegistration/azurebot.bicep +++ /dev/null @@ -1,40 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -@maxLength(42) -param botDisplayName string - -param botServiceName string = resourceBaseName -param botServiceSku string = 'F0' -param botAadAppClientId string -param botAppDomain string -param tenantId string - -// Register your web service as a bot with the Bot Framework -resource botService 'Microsoft.BotService/botServices@2021-03-01' = { - kind: 'azurebot' - location: 'global' - name: botServiceName - properties: { - displayName: botDisplayName - endpoint: 'https://${botAppDomain}/api/messages' - msaAppId: botAadAppClientId - msaAppType: 'SingleTenant' - msaAppTenantId: tenantId - } - sku: { - name: botServiceSku - } -} - -// Connect the bot service to Microsoft Teams -resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = { - parent: botService - location: 'global' - name: 'MsTeamsChannel' - properties: { - channelName: 'MsTeamsChannel' - } -} diff --git a/packages/cli/configs/atk/basic/python/teamsapp.local.yml.hbs b/packages/cli/configs/atk/basic/python/teamsapp.local.yml.hbs deleted file mode 100644 index 69bf43d53..000000000 --- a/packages/cli/configs/atk/basic/python/teamsapp.local.yml.hbs +++ /dev/null @@ -1,69 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/1.0.0/yaml.schema.json -# -# The teamsapp.local.yml composes automation tasks for M365 Agents Toolkit when running locally. -# This file is used when running Start Debugging (F5) from Visual Studio Code or with the TeamsFx CLI commands. -# i.e. `teamsfx provision --env local` or `teamsfx deploy --env local`. -# -# You can customize this file. Visit https://aka.ms/teamsfx-v5.0-guide for more info about M365 Agents Toolkit project files. -version: 1.0.0 - -environmentFolderPath: ./env - -# Defines what the `provision` lifecycle step does with M365 Agents Toolkit. -# Runs first during Start Debugging (F5) or run manually using `teamsfx provision --env local`. -provision: - # Automates the creation of a Teams app registration and saves the App ID to an environment file. - - uses: teamsApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID - - # Automates the creation an Azure AD app registration which is required for a bot. - # The Bot ID (AAD app client ID) and Bot Password (AAD app client secret) are saved to an environment file. - - uses: botAadApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - writeToEnvironmentFile: - botId: BOT_ID - botPassword: SECRET_BOT_PASSWORD - - # Automates the creation and configuration of a Bot Framework registration which is required for a bot. - # This configures the bot to use the Azure AD app registration created in the previous step. - # M365 Agents Toolkit automatically creates a local Dev Tunnel URL and updates BOT_ENDPOINT when debugging (F5). - - uses: botFramework/create - with: - botId: $\{{BOT_ID}} - name: {{ toPascalCase name }} - messagingEndpoint: $\{{BOT_ENDPOINT}}/api/messages - description: '' - channels: - - name: msteams - - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates the creation of a Teams app package (.zip). - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - # Relative path to this file. This is the path for built zip file. - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - -deploy: - - uses: file/createOrUpdateEnvironmentFile - with: - target: ./.env - envs: - PORT: 3978 - CLIENT_ID: $\{{BOT_ID}} - CLIENT_SECRET: $\{{SECRET_BOT_PASSWORD}} diff --git a/packages/cli/configs/atk/basic/python/teamsapp.testtool.yml b/packages/cli/configs/atk/basic/python/teamsapp.testtool.yml deleted file mode 100644 index d25ef0c11..000000000 --- a/packages/cli/configs/atk/basic/python/teamsapp.testtool.yml +++ /dev/null @@ -1,21 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/v1.5/yaml.schema.json -# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file -# Visit https://aka.ms/teamsfx-actions for details on actions -version: v1.5 - -deploy: - # Install development tool(s) - - uses: devTool/install - with: - testTool: - version: ~0.2.1 - symlinkDir: ./devTools/teamsapptester - - # Generate runtime environment variables - - uses: file/createOrUpdateEnvironmentFile - with: - target: ./.env - envs: - PYTHON_ENV: local - PORT: 3978 - TEAMSFX_NOTIFICATION_STORE_FILENAME: ${{TEAMSFX_NOTIFICATION_STORE_FILENAME}} diff --git a/packages/cli/configs/atk/basic/python/teamsapp.yml.hbs b/packages/cli/configs/atk/basic/python/teamsapp.yml.hbs deleted file mode 100644 index fba0c4ff9..000000000 --- a/packages/cli/configs/atk/basic/python/teamsapp.yml.hbs +++ /dev/null @@ -1,134 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/1.0.0/yaml.schema.json -# -# The teamsapp.yml composes automation tasks for M365 Agents Toolkit when running other environment configurations. -# This file is used when selecting the Provision, Deploy, or Publish menu items in the M365 Agents Toolkit for Visual Studio Code window -# or with the TeamsFx CLI commands. -# i.e. `teamsfx provision --env {environment name}` or `teamsfx deploy --env {environment name}`. -# -# You can customize this file. Visit https://aka.ms/teamsfx-v5.0-guide for more info about M365 Agents Toolkit project files. -version: 1.0.0 - -environmentFolderPath: ./env - -# Defines what the `provision` lifecycle step does with M365 Agents Toolkit. -# Runs with the Provision menu or CLI using `teamsfx provision --env {environment name}`. -provision: - # Automates the creation of a Teams app registration and saves the App ID to an environment file. - - uses: teamsApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID - - # Creates a new Microsoft Entra app to authenticate users if - # the environment variable that stores clientId is empty - - uses: aadApp/create - with: - # Note: when you run aadApp/update, the Microsoft Entra app name will be updated - # based on the definition in manifest. If you don't want to change the - # name, make sure the name in Microsoft Entra manifest is the same with the name - # defined here. - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - # If the value is false, the driver will not generate client secret for you - generateClientSecret: true - # organization's Microsoft Entra tenant (for example, single tenant). - signInAudience: AzureADMultipleOrgs - # Write the information of created resources into environment file for the - # specified environment variable(s). - writeToEnvironmentFile: - clientId: BOT_ID - # Environment variable that starts with `SECRET_` will be stored to the - # .env.{envName}.user environment file - clientSecret: SECRET_BOT_PASSWORD - objectId: AAD_APP_OBJECT_ID - tenantId: AAD_APP_TENANT_ID - - - uses: arm/deploy # Deploy given ARM templates parallelly. - with: - # AZURE_SUBSCRIPTION_ID is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select a subscription. - # Referencing other environment variables with empty values - # will skip the subscription selection prompt. - subscriptionId: $\{{AZURE_SUBSCRIPTION_ID}} - # AZURE_RESOURCE_GROUP_NAME is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select or create one - # resource group. - # Referencing other environment variables with empty values - # will skip the resource group selection prompt. - resourceGroupName: $\{{AZURE_RESOURCE_GROUP_NAME}} - templates: - - path: ./infra/azure.bicep # Relative path to this file - # Relative path to this yaml file. - # Placeholders will be replaced with corresponding environment - # variable before ARM deployment. - parameters: ./infra/azure.parameters.json - # Required when deploying ARM template - deploymentName: Create-resources-for-bot - # M365 Agents Toolkit will download this bicep CLI version from github for you, - # will use bicep CLI in PATH if you remove this config. - bicepCliVersion: v0.9.1 - - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates creating a final app package (.zip) by replacing any variables in the manifest.json file for the current environment. - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Optional: Automates an app package check for errors that would prevent the app from being published and reports any problems. - - uses: teamsApp/validateAppPackage - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - -deploy: - - uses: script - with: - run: | - uv sync - uv export --no-hashes -o src/requirements.txt - # Deploy to an Azure App Service using the zip file created in the provision step. - - uses: azureAppService/zipDeploy - with: - artifactFolder: src - ignoreFile: .webappignore - # This example uses the env var thats generated by the arm/deploy action. - # You can replace it with an existing Azure Resource ID or other - # custom environment variable. - resourceId: $\{{BOT_AZURE_APP_SERVICE_RESOURCE_ID}} - -# Defines what the `publish` lifecycle step does with M365 Agents Toolkit. -# Runs with the Deploy menu or CLI using `teamsfx publish --env {environment name}`. -publish: - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates creating a final app package (.zip) by replacing any variables in the manifest.json file for the current environment. - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Optional: Automates an app package check for errors that would prevent the app from being published and reports any problems. - - uses: teamsApp/validateAppPackage - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip diff --git a/packages/cli/configs/atk/basic/typescript/.vscode/launch.json b/packages/cli/configs/atk/basic/typescript/.vscode/launch.json deleted file mode 100644 index 4f6e6a549..000000000 --- a/packages/cli/configs/atk/basic/typescript/.vscode/launch.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Launch Remote (Edge)", - "type": "msedge", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "remote", - "order": 1 - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch Remote (Chrome)", - "type": "chrome", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "remote", - "order": 2 - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch App (Edge)", - "type": "msedge", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "cascadeTerminateToConfigurations": ["Attach to Local Service"], - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch App (Chrome)", - "type": "chrome", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "cascadeTerminateToConfigurations": ["Attach to Local Service"], - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Attach to Local Service", - "type": "node", - "request": "attach", - "port": 9239, - "restart": true, - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - } - ], - "compounds": [ - { - "name": "Debug (Edge)", - "configurations": ["Launch App (Edge)", "Attach to Local Service"], - "preLaunchTask": "Start Teams App Locally", - "presentation": { - "group": "all", - "order": 1 - }, - "stopAll": true - }, - { - "name": "Debug (Chrome)", - "configurations": ["Launch App (Chrome)", "Attach to Local Service"], - "preLaunchTask": "Start Teams App Locally", - "presentation": { - "group": "all", - "order": 2 - }, - "stopAll": true - }, - { - "name": "Debug in Test Tool", - "configurations": ["Attach to Local Service"], - "preLaunchTask": "Start Teams App (Test Tool)", - "presentation": { - "group": "local", - "order": 1 - }, - "stopAll": true - } - ] -} diff --git a/packages/cli/configs/atk/basic/typescript/.vscode/tasks.json b/packages/cli/configs/atk/basic/typescript/.vscode/tasks.json deleted file mode 100644 index 1bce0df16..000000000 --- a/packages/cli/configs/atk/basic/typescript/.vscode/tasks.json +++ /dev/null @@ -1,204 +0,0 @@ -// This file is automatically generated by M365 Agents Toolkit. -// The teamsfx tasks defined in this file require M365 Agents Toolkit version >= 5.0.0. -// See https://aka.ms/teamsfx-tasks for details on how to customize each task. -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Start Teams App Locally", - "dependsOn": [ - "Validate prerequisites", - "Start local tunnel", - "Provision", - "Deploy", - "Start application" - ], - "dependsOrder": "sequence" - }, - { - // Check all required prerequisites. - // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. - "label": "Validate prerequisites", - "type": "teamsfx", - "command": "debug-check-prerequisites", - "args": { - "prerequisites": [ - "nodejs", // Validate if Node.js is installed. - "m365Account", // Sign-in prompt for Microsoft 365 account, then validate if the account enables the sideloading permission. - "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. - ], - "portOccupancy": [ - 3978, // app service port - 9239 // app inspector port for Node.js debugger - ] - } - }, - { - // Start the local tunnel service to forward public URL to local port and inspect traffic. - // See https://aka.ms/teamsfx-tasks/local-tunnel for the detailed args definitions. - "label": "Start local tunnel", - "type": "teamsfx", - "command": "debug-start-local-tunnel", - "args": { - "type": "dev-tunnel", - "ports": [ - { - "portNumber": 3978, - "protocol": "http", - "access": "public", - "writeToEnvironmentFile": { - "endpoint": "BOT_ENDPOINT", // output tunnel endpoint as BOT_ENDPOINT - "domain": "BOT_DOMAIN" // output tunnel domain as BOT_DOMAIN - } - } - ], - "env": "local" - }, - "isBackground": true, - "problemMatcher": "$teamsfx-local-tunnel-watch" - }, - { - // Create the debug resources. - // See https://aka.ms/teamsfx-tasks/provision to know the details and how to customize the args. - "label": "Provision", - "type": "teamsfx", - "command": "provision", - "args": { - "env": "local" - } - }, - { - // Build project. - // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. - "label": "Deploy", - "type": "teamsfx", - "command": "deploy", - "args": { - "env": "local" - } - }, - { - "label": "Start application", - "type": "shell", - "command": "npm run dev:teamsfx", - "isBackground": true, - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": { - "pattern": [ - { - "regexp": "^.*$", - "file": 0, - "location": 1, - "message": 2 - } - ], - "background": { - "activeOnStart": true, - "beginsPattern": "[nodemon] starting", - "endsPattern": "listening|[nodemon] app crashed" - } - } - }, - { - "label": "Start Teams App (Test Tool)", - "dependsOn": [ - "Validate prerequisites (Test Tool)", - "Deploy (Test Tool)", - "Start application (Test Tool)", - "Start Test Tool" - ], - "dependsOrder": "sequence" - }, - { - // Check all required prerequisites. - // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. - "label": "Validate prerequisites (Test Tool)", - "type": "teamsfx", - "command": "debug-check-prerequisites", - "args": { - "prerequisites": [ - "nodejs", // Validate if Node.js is installed. - "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. - ], - "portOccupancy": [ - 3978, // app service port - 9239, // app inspector port for Node.js debugger - 56150 // test tool port - ] - } - }, - { - // Build project. - // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. - "label": "Deploy (Test Tool)", - "type": "teamsfx", - "command": "deploy", - "args": { - "env": "testtool" - } - }, - { - "label": "Start application (Test Tool)", - "type": "shell", - "command": "npm run dev:teamsfx:testtool", - "isBackground": true, - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": { - "pattern": [ - { - "regexp": "^.*$", - "file": 0, - "location": 1, - "message": 2 - } - ], - "background": { - "activeOnStart": true, - "beginsPattern": "[nodemon] starting", - "endsPattern": "listening|[nodemon] app crashed" - } - } - }, - { - "label": "Start Test Tool", - "type": "shell", - "command": "npm run dev:teamsfx:launch-testtool", - "isBackground": true, - "options": { - "env": { - "PATH": "${workspaceFolder}/devTools/teamsapptester/node_modules/.bin:${env:PATH}" - } - }, - "windows": { - "options": { - "env": { - "PATH": "${workspaceFolder}/devTools/teamsapptester/node_modules/.bin;${env:PATH}" - } - } - }, - "problemMatcher": { - "pattern": [ - { - "regexp": "^.*$", - "file": 0, - "location": 1, - "message": 2 - } - ], - "background": { - "activeOnStart": true, - "beginsPattern": ".*", - "endsPattern": "listening on" - } - }, - "presentation": { - "panel": "dedicated", - "reveal": "silent" - } - } - ] -} diff --git a/packages/cli/configs/atk/basic/typescript/env/.env.dev b/packages/cli/configs/atk/basic/typescript/env/.env.dev deleted file mode 100644 index 5e12c5c06..000000000 --- a/packages/cli/configs/atk/basic/typescript/env/.env.dev +++ /dev/null @@ -1,19 +0,0 @@ -# This file includes environment variables that will be committed to git by default. - -# Built-in environment variables -TEAMSFX_ENV=dev -APP_NAME_SUFFIX=dev - -# Updating AZURE_SUBSCRIPTION_ID or AZURE_RESOURCE_GROUP_NAME after provision may also require an update to RESOURCE_SUFFIX, because some services require a globally unique name across subscriptions/resource groups. -AZURE_SUBSCRIPTION_ID= -AZURE_RESOURCE_GROUP_NAME= -RESOURCE_SUFFIX= - -# Generated during provision, you can also add your own variables. -TEAMS_APP_ID= -TEAMS_APP_TENANT_ID= -BOT_ID= -AAD_APP_OBJECT_ID= -AAD_APP_TENANT_ID= -BOT_AZURE_APP_SERVICE_RESOURCE_ID= -BOT_DOMAIN= diff --git a/packages/cli/configs/atk/basic/typescript/env/.env.testtool b/packages/cli/configs/atk/basic/typescript/env/.env.testtool deleted file mode 100644 index c82bc5257..000000000 --- a/packages/cli/configs/atk/basic/typescript/env/.env.testtool +++ /dev/null @@ -1,5 +0,0 @@ -TEAMSFX_ENV=testtool - -# Environment variables used by test tool -TEAMSAPPTESTER_PORT=56150 -TEAMSFX_NOTIFICATION_STORE_FILENAME=.notification.testtoolstore.json diff --git a/packages/cli/configs/atk/basic/typescript/infra/azure.bicep b/packages/cli/configs/atk/basic/typescript/infra/azure.bicep deleted file mode 100644 index 469d5d70a..000000000 --- a/packages/cli/configs/atk/basic/typescript/infra/azure.bicep +++ /dev/null @@ -1,88 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -@description('Required when create Azure Bot service') -param botAadAppClientId string - -@secure() -@description('Required by Bot Framework package in your bot project') -param botAadAppClientSecret string - -param webAppSKU string -param tenantId string - -@maxLength(42) -param botDisplayName string - -param serverfarmsName string = resourceBaseName -param webAppName string = resourceBaseName -param location string = resourceGroup().location - -// Compute resources for your Web App -resource serverfarm 'Microsoft.Web/serverfarms@2021-02-01' = { - kind: 'app' - location: location - name: serverfarmsName - sku: { - name: webAppSKU - } -} - -// Web App that hosts your agent -resource webApp 'Microsoft.Web/sites@2021-02-01' = { - kind: 'app' - location: location - name: webAppName - properties: { - serverFarmId: serverfarm.id - httpsOnly: true - siteConfig: { - alwaysOn: true - appSettings: [ - { - name: 'WEBSITE_RUN_FROM_PACKAGE' - value: '1' // Run Azure APP Service from a package file - } - { - name: 'WEBSITE_NODE_DEFAULT_VERSION' - value: '~20' // Set NodeJS version to 20.x for your site - } - { - name: 'RUNNING_ON_AZURE' - value: '1' - } - { - name: 'CLIENT_ID' - value: botAadAppClientId - } - { - name: 'CLIENT_SECRET' - value: botAadAppClientSecret - } - { - name: 'TENANT_ID' - value: tenantId - } - ] - ftpsState: 'FtpsOnly' - } - } -} - -// Register your web service as a bot with the Bot Framework -module azureBotRegistration './botRegistration/azurebot.bicep' = { - name: 'Azure-Bot-registration' - params: { - resourceBaseName: resourceBaseName - botAadAppClientId: botAadAppClientId - botAppDomain: webApp.properties.defaultHostName - botDisplayName: botDisplayName - tenantId: tenantId - } -} - -// The output will be persisted in .env.{envName}. Visit https://aka.ms/teamsfx-actions/arm-deploy for more details. -output BOT_AZURE_APP_SERVICE_RESOURCE_ID string = webApp.id -output BOT_DOMAIN string = webApp.properties.defaultHostName diff --git a/packages/cli/configs/atk/basic/typescript/infra/azure.parameters.json.hbs b/packages/cli/configs/atk/basic/typescript/infra/azure.parameters.json.hbs deleted file mode 100644 index 0428469d4..000000000 --- a/packages/cli/configs/atk/basic/typescript/infra/azure.parameters.json.hbs +++ /dev/null @@ -1,24 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "resourceBaseName": { - "value": "bot$\{{RESOURCE_SUFFIX}}" - }, - "webAppSKU": { - "value": "B1" - }, - "botAadAppClientId": { - "value": "$\{{BOT_ID}}" - }, - "botAadAppClientSecret": { - "value": "$\{{SECRET_BOT_PASSWORD}}" - }, - "tenantId": { - "value": "$\{{AAD_APP_TENANT_ID}}" - }, - "botDisplayName": { - "value": "{{ toPascalCase name }}Infra" - } - } -} diff --git a/packages/cli/configs/atk/basic/typescript/infra/botRegistration/azurebot.bicep b/packages/cli/configs/atk/basic/typescript/infra/botRegistration/azurebot.bicep deleted file mode 100644 index 1627e0dfa..000000000 --- a/packages/cli/configs/atk/basic/typescript/infra/botRegistration/azurebot.bicep +++ /dev/null @@ -1,40 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -@maxLength(42) -param botDisplayName string - -param botServiceName string = resourceBaseName -param botServiceSku string = 'F0' -param botAadAppClientId string -param botAppDomain string -param tenantId string - -// Register your web service as a bot with the Bot Framework -resource botService 'Microsoft.BotService/botServices@2021-03-01' = { - kind: 'azurebot' - location: 'global' - name: botServiceName - properties: { - displayName: botDisplayName - endpoint: 'https://${botAppDomain}/api/messages' - msaAppId: botAadAppClientId - msaAppType: 'SingleTenant' - msaAppTenantId: tenantId - } - sku: { - name: botServiceSku - } -} - -// Connect the bot service to Microsoft Teams -resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = { - parent: botService - location: 'global' - name: 'MsTeamsChannel' - properties: { - channelName: 'MsTeamsChannel' - } -} diff --git a/packages/cli/configs/atk/basic/typescript/teamsapp.local.yml.hbs b/packages/cli/configs/atk/basic/typescript/teamsapp.local.yml.hbs deleted file mode 100644 index 205323629..000000000 --- a/packages/cli/configs/atk/basic/typescript/teamsapp.local.yml.hbs +++ /dev/null @@ -1,77 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/1.0.0/yaml.schema.json -# -# The teamsapp.local.yml composes automation tasks for M365 Agents Toolkit when running locally. -# This file is used when running Start Debugging (F5) from Visual Studio Code or with the TeamsFx CLI commands. -# i.e. `teamsfx provision --env local` or `teamsfx deploy --env local`. -# -# You can customize this file. Visit https://aka.ms/teamsfx-v5.0-guide for more info about M365 Agents Toolkit project files. -version: 1.0.0 - -environmentFolderPath: ./env - -# Defines what the `provision` lifecycle step does with M365 Agents Toolkit. -# Runs first during Start Debugging (F5) or run manually using `teamsfx provision --env local`. -provision: - # Automates the creation of a Teams app registration and saves the App ID to an environment file. - - uses: teamsApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID - - # Automates the creation an Azure AD app registration which is required for a bot. - # The Bot ID (AAD app client ID) and Bot Password (AAD app client secret) are saved to an environment file. - - uses: botAadApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - writeToEnvironmentFile: - botId: BOT_ID - botPassword: SECRET_BOT_PASSWORD - - # Automates the creation and configuration of a Bot Framework registration which is required for a bot. - # This configures the bot to use the Azure AD app registration created in the previous step. - # M365 Agents Toolkit automatically creates a local Dev Tunnel URL and updates BOT_ENDPOINT when debugging (F5). - - uses: botFramework/create - with: - botId: $\{{BOT_ID}} - name: {{ toPascalCase name }} - messagingEndpoint: $\{{BOT_ENDPOINT}}/api/messages - description: '' - channels: - - name: msteams - - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates the creation of a Teams app package (.zip). - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - # Relative path to this file. This is the path for built zip file. - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - -# Defines what the `deploy` lifecycle step does with M365 Agents Toolkit. -# Runs after `provision` during Start Debugging (F5) or run manually using `teamsfx deploy --env local`. -deploy: - # Install any dependencies and build the web app using NPM - - uses: cli/runNpmCommand - name: install dependencies - with: - args: install --no-audit --workspaces=false - # Provides the M365 Agents Toolkit .env file values to the apps runtime so they can be accessed with `process.env`. - - uses: file/createOrUpdateEnvironmentFile - with: - target: ./.env - envs: - PORT: 3978 - CLIENT_ID: $\{{BOT_ID}} - CLIENT_SECRET: $\{{SECRET_BOT_PASSWORD}} diff --git a/packages/cli/configs/atk/basic/typescript/teamsapp.testtool.yml b/packages/cli/configs/atk/basic/typescript/teamsapp.testtool.yml deleted file mode 100644 index e9dab22c2..000000000 --- a/packages/cli/configs/atk/basic/typescript/teamsapp.testtool.yml +++ /dev/null @@ -1,26 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/v1.5/yaml.schema.json -# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file -# Visit https://aka.ms/teamsfx-actions for details on actions -version: v1.5 - -deploy: - # Install development tool(s) - - uses: devTool/install - with: - testTool: - version: ~0.2.1 - symlinkDir: ./devTools/teamsapptester - - # Run npm command - - uses: cli/runNpmCommand - with: - args: install --no-audit --workspaces=false - - # Generate runtime environment variables - - uses: file/createOrUpdateEnvironmentFile - with: - target: ./.env - envs: - NODE_ENV: local - PORT: 3978 - TEAMSFX_NOTIFICATION_STORE_FILENAME: ${{TEAMSFX_NOTIFICATION_STORE_FILENAME}} diff --git a/packages/cli/configs/atk/basic/typescript/teamsapp.yml.hbs b/packages/cli/configs/atk/basic/typescript/teamsapp.yml.hbs deleted file mode 100644 index 32c5e4556..000000000 --- a/packages/cli/configs/atk/basic/typescript/teamsapp.yml.hbs +++ /dev/null @@ -1,142 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/1.0.0/yaml.schema.json -# -# The teamsapp.yml composes automation tasks for M365 Agents Toolkit when running other environment configurations. -# This file is used when selecting the Provision, Deploy, or Publish menu items in the M365 Agents Toolkit for Visual Studio Code window -# or with the TeamsFx CLI commands. -# i.e. `teamsfx provision --env {environment name}` or `teamsfx deploy --env {environment name}`. -# -# You can customize this file. Visit https://aka.ms/teamsfx-v5.0-guide for more info about M365 Agents Toolkit project files. -version: 1.0.0 - -environmentFolderPath: ./env - -# Defines what the `provision` lifecycle step does with M365 Agents Toolkit. -# Runs with the Provision menu or CLI using `teamsfx provision --env {environment name}`. -provision: - # Automates the creation of a Teams app registration and saves the App ID to an environment file. - - uses: teamsApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID - - # Creates a new Microsoft Entra app to authenticate users if - # the environment variable that stores clientId is empty - - uses: aadApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - # Note: when you run aadApp/update, the Microsoft Entra app name will be updated - # based on the definition in manifest. If you don't want to change the - # name, make sure the name in Microsoft Entra manifest is the same with the name - # defined here. - # If the value is false, the driver will not generate client secret for you - generateClientSecret: true - # organization's Microsoft Entra tenant (for example, single tenant). - signInAudience: AzureADMultipleOrgs - # Write the information of created resources into environment file for the - # specified environment variable(s). - writeToEnvironmentFile: - clientId: BOT_ID - # Environment variable that starts with `SECRET_` will be stored to the - # .env.{envName}.user environment file - clientSecret: SECRET_BOT_PASSWORD - objectId: AAD_APP_OBJECT_ID - tenantId: AAD_APP_TENANT_ID - - - uses: arm/deploy # Deploy given ARM templates parallelly. - with: - # AZURE_SUBSCRIPTION_ID is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select a subscription. - # Referencing other environment variables with empty values - # will skip the subscription selection prompt. - subscriptionId: $\{{AZURE_SUBSCRIPTION_ID}} - # AZURE_RESOURCE_GROUP_NAME is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select or create one - # resource group. - # Referencing other environment variables with empty values - # will skip the resource group selection prompt. - resourceGroupName: $\{{AZURE_RESOURCE_GROUP_NAME}} - templates: - - path: ./infra/azure.bicep # Relative path to this file - # Relative path to this yaml file. - # Placeholders will be replaced with corresponding environment - # variable before ARM deployment. - parameters: ./infra/azure.parameters.json - # Required when deploying ARM template - deploymentName: Create-resources-for-bot - # M365 Agents Toolkit will download this bicep CLI version from github for you, - # will use bicep CLI in PATH if you remove this config. - bicepCliVersion: v0.9.1 - - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates creating a final app package (.zip) by replacing any variables in the manifest.json file for the current environment. - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Optional: Automates an app package check for errors that would prevent the app from being published and reports any problems. - - uses: teamsApp/validateAppPackage - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - -# Defines what the `deploy` lifecycle step does with M365 Agents Toolkit. -# Runs with the Deploy menu or CLI using `teamsfx deploy --env {environment name}`. -deploy: - # Install any dependencies and build the web app using NPM - - uses: cli/runNpmCommand - name: install dependencies - with: - args: install - - - uses: cli/runNpmCommand - name: build app - with: - args: run build --if-present - - # Deploy to an Azure App Service using the zip file created in the provision step. - - uses: azureAppService/zipDeploy - with: - artifactFolder: . - ignoreFile: .webappignore - # This example uses the env var thats generated by the arm/deploy action. - # You can replace it with an existing Azure Resource ID or other - # custom environment variable. - resourceId: $\{{BOT_AZURE_APP_SERVICE_RESOURCE_ID}} - -# Defines what the `publish` lifecycle step does with M365 Agents Toolkit. -# Runs with the Deploy menu or CLI using `teamsfx publish --env {environment name}`. -publish: - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates creating a final app package (.zip) by replacing any variables in the manifest.json file for the current environment. - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Optional: Automates an app package check for errors that would prevent the app from being published and reports any problems. - - uses: teamsApp/validateAppPackage - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip diff --git a/packages/cli/configs/atk/basic/typescript/web.config b/packages/cli/configs/atk/basic/typescript/web.config deleted file mode 100644 index 95763e55f..000000000 --- a/packages/cli/configs/atk/basic/typescript/web.config +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/cli/configs/atk/embed/typescript/.vscode/launch.json b/packages/cli/configs/atk/embed/typescript/.vscode/launch.json deleted file mode 100644 index 4f6e6a549..000000000 --- a/packages/cli/configs/atk/embed/typescript/.vscode/launch.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Launch Remote (Edge)", - "type": "msedge", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "remote", - "order": 1 - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch Remote (Chrome)", - "type": "chrome", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "remote", - "order": 2 - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch App (Edge)", - "type": "msedge", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "cascadeTerminateToConfigurations": ["Attach to Local Service"], - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch App (Chrome)", - "type": "chrome", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "cascadeTerminateToConfigurations": ["Attach to Local Service"], - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Attach to Local Service", - "type": "node", - "request": "attach", - "port": 9239, - "restart": true, - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - } - ], - "compounds": [ - { - "name": "Debug (Edge)", - "configurations": ["Launch App (Edge)", "Attach to Local Service"], - "preLaunchTask": "Start Teams App Locally", - "presentation": { - "group": "all", - "order": 1 - }, - "stopAll": true - }, - { - "name": "Debug (Chrome)", - "configurations": ["Launch App (Chrome)", "Attach to Local Service"], - "preLaunchTask": "Start Teams App Locally", - "presentation": { - "group": "all", - "order": 2 - }, - "stopAll": true - }, - { - "name": "Debug in Test Tool", - "configurations": ["Attach to Local Service"], - "preLaunchTask": "Start Teams App (Test Tool)", - "presentation": { - "group": "local", - "order": 1 - }, - "stopAll": true - } - ] -} diff --git a/packages/cli/configs/atk/embed/typescript/.vscode/tasks.json b/packages/cli/configs/atk/embed/typescript/.vscode/tasks.json deleted file mode 100644 index 1bce0df16..000000000 --- a/packages/cli/configs/atk/embed/typescript/.vscode/tasks.json +++ /dev/null @@ -1,204 +0,0 @@ -// This file is automatically generated by M365 Agents Toolkit. -// The teamsfx tasks defined in this file require M365 Agents Toolkit version >= 5.0.0. -// See https://aka.ms/teamsfx-tasks for details on how to customize each task. -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Start Teams App Locally", - "dependsOn": [ - "Validate prerequisites", - "Start local tunnel", - "Provision", - "Deploy", - "Start application" - ], - "dependsOrder": "sequence" - }, - { - // Check all required prerequisites. - // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. - "label": "Validate prerequisites", - "type": "teamsfx", - "command": "debug-check-prerequisites", - "args": { - "prerequisites": [ - "nodejs", // Validate if Node.js is installed. - "m365Account", // Sign-in prompt for Microsoft 365 account, then validate if the account enables the sideloading permission. - "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. - ], - "portOccupancy": [ - 3978, // app service port - 9239 // app inspector port for Node.js debugger - ] - } - }, - { - // Start the local tunnel service to forward public URL to local port and inspect traffic. - // See https://aka.ms/teamsfx-tasks/local-tunnel for the detailed args definitions. - "label": "Start local tunnel", - "type": "teamsfx", - "command": "debug-start-local-tunnel", - "args": { - "type": "dev-tunnel", - "ports": [ - { - "portNumber": 3978, - "protocol": "http", - "access": "public", - "writeToEnvironmentFile": { - "endpoint": "BOT_ENDPOINT", // output tunnel endpoint as BOT_ENDPOINT - "domain": "BOT_DOMAIN" // output tunnel domain as BOT_DOMAIN - } - } - ], - "env": "local" - }, - "isBackground": true, - "problemMatcher": "$teamsfx-local-tunnel-watch" - }, - { - // Create the debug resources. - // See https://aka.ms/teamsfx-tasks/provision to know the details and how to customize the args. - "label": "Provision", - "type": "teamsfx", - "command": "provision", - "args": { - "env": "local" - } - }, - { - // Build project. - // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. - "label": "Deploy", - "type": "teamsfx", - "command": "deploy", - "args": { - "env": "local" - } - }, - { - "label": "Start application", - "type": "shell", - "command": "npm run dev:teamsfx", - "isBackground": true, - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": { - "pattern": [ - { - "regexp": "^.*$", - "file": 0, - "location": 1, - "message": 2 - } - ], - "background": { - "activeOnStart": true, - "beginsPattern": "[nodemon] starting", - "endsPattern": "listening|[nodemon] app crashed" - } - } - }, - { - "label": "Start Teams App (Test Tool)", - "dependsOn": [ - "Validate prerequisites (Test Tool)", - "Deploy (Test Tool)", - "Start application (Test Tool)", - "Start Test Tool" - ], - "dependsOrder": "sequence" - }, - { - // Check all required prerequisites. - // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. - "label": "Validate prerequisites (Test Tool)", - "type": "teamsfx", - "command": "debug-check-prerequisites", - "args": { - "prerequisites": [ - "nodejs", // Validate if Node.js is installed. - "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. - ], - "portOccupancy": [ - 3978, // app service port - 9239, // app inspector port for Node.js debugger - 56150 // test tool port - ] - } - }, - { - // Build project. - // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. - "label": "Deploy (Test Tool)", - "type": "teamsfx", - "command": "deploy", - "args": { - "env": "testtool" - } - }, - { - "label": "Start application (Test Tool)", - "type": "shell", - "command": "npm run dev:teamsfx:testtool", - "isBackground": true, - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": { - "pattern": [ - { - "regexp": "^.*$", - "file": 0, - "location": 1, - "message": 2 - } - ], - "background": { - "activeOnStart": true, - "beginsPattern": "[nodemon] starting", - "endsPattern": "listening|[nodemon] app crashed" - } - } - }, - { - "label": "Start Test Tool", - "type": "shell", - "command": "npm run dev:teamsfx:launch-testtool", - "isBackground": true, - "options": { - "env": { - "PATH": "${workspaceFolder}/devTools/teamsapptester/node_modules/.bin:${env:PATH}" - } - }, - "windows": { - "options": { - "env": { - "PATH": "${workspaceFolder}/devTools/teamsapptester/node_modules/.bin;${env:PATH}" - } - } - }, - "problemMatcher": { - "pattern": [ - { - "regexp": "^.*$", - "file": 0, - "location": 1, - "message": 2 - } - ], - "background": { - "activeOnStart": true, - "beginsPattern": ".*", - "endsPattern": "listening on" - } - }, - "presentation": { - "panel": "dedicated", - "reveal": "silent" - } - } - ] -} diff --git a/packages/cli/configs/atk/embed/typescript/aad.manifest.json.hbs b/packages/cli/configs/atk/embed/typescript/aad.manifest.json.hbs deleted file mode 100644 index f2e70b531..000000000 --- a/packages/cli/configs/atk/embed/typescript/aad.manifest.json.hbs +++ /dev/null @@ -1,113 +0,0 @@ -{ - "id": "$\{{AAD_APP_OBJECT_ID}}", - "appId": "$\{{BOT_ID}}", - "displayName": "{{ toPascalCase name }}$\{{APP_NAME_SUFFIX}}", - "identifierUris": [ - "api://$\{{BOT_ID}}" - ], - - "signInAudience": "AzureADMultipleOrgs", - "api": { - "requestedAccessTokenVersion": 2, - "oauth2PermissionScopes": [ - { - "adminConsentDescription": "Allows Teams to call the app's web APIs as the current user.", - "adminConsentDisplayName": "Teams can access app's web APIs", - "id": "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}", - "isEnabled": true, - "type": "User", - "userConsentDescription": "Enable Teams to call this app's web APIs with the same rights that you have", - "userConsentDisplayName": "Teams can access app's web APIs and make requests on your behalf", - "value": "access_as_user" - } - ], - "preAuthorizedApplications": [ - { - "appId": "1fec8e78-bce4-4aaf-ab1b-5451cc387264", - "delegatedPermissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "5e3ce6c0-2b1f-4285-8d4b-75ee78787346", - "delegatedPermissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "d3590ed6-52b3-4102-aeff-aad2292ab01c", - "delegatedPermissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "00000002-0000-0ff1-ce00-000000000000", - "delegatedPermissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "bc59ab01-8403-45c6-8796-ac3ef710b3e3", - "delegatedPermissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "0ec893e0-5785-4de6-99da-4ed124e5296c", - "delegatedPermissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "4765445b-32c6-49b0-83e6-1d93765276ca", - "delegatedPermissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "4345a7b9-9a63-4910-a426-35363201d503", - "delegatedPermissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "27922004-5251-4030-b22d-91ecd9a37ea4", - "delegatedPermissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - } - ] - }, - "info": {}, - "optionalClaims": { - "idToken": [], - "accessToken": [ - { - "name": "idtyp", - "source": null, - "essential": false, - "additionalProperties": [] - } - ], - "saml2Token": [] - }, - "publicClient": { - "redirectUris": [] - }, - "requiredResourceAccess": [ - { - "resourceAppId": "Microsoft Graph", - "resourceAccess": [ - { - "id": "User.Read", - "type": "Scope" - } - ] - } - ], - "spa": { - "redirectUris": [ - "brk-multihub://$\{{BOT_DOMAIN}}" - ] - } -} \ No newline at end of file diff --git a/packages/cli/configs/atk/embed/typescript/env/.env.testtool b/packages/cli/configs/atk/embed/typescript/env/.env.testtool deleted file mode 100644 index c82bc5257..000000000 --- a/packages/cli/configs/atk/embed/typescript/env/.env.testtool +++ /dev/null @@ -1,5 +0,0 @@ -TEAMSFX_ENV=testtool - -# Environment variables used by test tool -TEAMSAPPTESTER_PORT=56150 -TEAMSFX_NOTIFICATION_STORE_FILENAME=.notification.testtoolstore.json diff --git a/packages/cli/configs/atk/embed/typescript/infra/azure.bicep b/packages/cli/configs/atk/embed/typescript/infra/azure.bicep deleted file mode 100644 index 1c353146b..000000000 --- a/packages/cli/configs/atk/embed/typescript/infra/azure.bicep +++ /dev/null @@ -1,95 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -param webAppSKU string - -@maxLength(42) -param botDisplayName string - -param serverfarmsName string = resourceBaseName -param webAppName string = resourceBaseName -param identityName string = resourceBaseName -param location string = resourceGroup().location - -resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - location: location - name: identityName -} - -// Compute resources for your Web App -resource serverfarm 'Microsoft.Web/serverfarms@2021-02-01' = { - kind: 'app' - location: location - name: serverfarmsName - sku: { - name: webAppSKU - } -} - -// Web App that hosts your agent -resource webApp 'Microsoft.Web/sites@2021-02-01' = { - kind: 'app' - location: location - name: webAppName - properties: { - serverFarmId: serverfarm.id - httpsOnly: true - siteConfig: { - alwaysOn: true - appSettings: [ - { - name: 'WEBSITE_RUN_FROM_PACKAGE' - value: '1' // Run Azure APP Service from a package file - } - { - name: 'WEBSITE_NODE_DEFAULT_VERSION' - value: '~20' // Set NodeJS version to 20.x for your site - } - { - name: 'RUNNING_ON_AZURE' - value: '1' - } - { - name: 'BOT_ID' - value: identity.properties.clientId - } - { - name: 'BOT_TENANT_ID' - value: identity.properties.tenantId - } - { - name: 'BOT_TYPE' - value: 'UserAssignedMsi' - } - ] - ftpsState: 'FtpsOnly' - } - } - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${identity.id}': {} - } - } -} - -// Register your web service as a bot with the Bot Framework -module azureBotRegistration './botRegistration/azurebot.bicep' = { - name: 'Azure-Bot-registration' - params: { - resourceBaseName: resourceBaseName - identityClientId: identity.properties.clientId - identityResourceId: identity.id - identityTenantId: identity.properties.tenantId - botAppDomain: webApp.properties.defaultHostName - botDisplayName: botDisplayName - } -} - -// The output will be persisted in .env.{envName}. Visit https://aka.ms/teamsfx-actions/arm-deploy for more details. -output BOT_AZURE_APP_SERVICE_RESOURCE_ID string = webApp.id -output BOT_DOMAIN string = webApp.properties.defaultHostName -output BOT_ID string = identity.properties.clientId -output BOT_TENANT_ID string = identity.properties.tenantId diff --git a/packages/cli/configs/atk/embed/typescript/infra/azure.parameters.json.hbs b/packages/cli/configs/atk/embed/typescript/infra/azure.parameters.json.hbs deleted file mode 100644 index 7b5ba26e9..000000000 --- a/packages/cli/configs/atk/embed/typescript/infra/azure.parameters.json.hbs +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "resourceBaseName": { - "value": "bot$\{{RESOURCE_SUFFIX}}" - }, - "webAppSKU": { - "value": "B1" - }, - "botDisplayName": { - "value": "{{ toPascalCase name }}Infra" - } - } -} diff --git a/packages/cli/configs/atk/embed/typescript/infra/botRegistration/azurebot.bicep b/packages/cli/configs/atk/embed/typescript/infra/botRegistration/azurebot.bicep deleted file mode 100644 index f0343e34d..000000000 --- a/packages/cli/configs/atk/embed/typescript/infra/botRegistration/azurebot.bicep +++ /dev/null @@ -1,42 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -@maxLength(42) -param botDisplayName string - -param botServiceName string = resourceBaseName -param botServiceSku string = 'F0' -param identityResourceId string -param identityClientId string -param identityTenantId string -param botAppDomain string - -// Register your web service as a bot with the Bot Framework -resource botService 'Microsoft.BotService/botServices@2021-03-01' = { - kind: 'azurebot' - location: 'global' - name: botServiceName - properties: { - displayName: botDisplayName - endpoint: 'https://${botAppDomain}/api/messages' - msaAppId: identityClientId - msaAppMSIResourceId: identityResourceId - msaAppTenantId: identityTenantId - msaAppType: 'UserAssignedMSI' - } - sku: { - name: botServiceSku - } -} - -// Connect the bot service to Microsoft Teams -resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = { - parent: botService - location: 'global' - name: 'MsTeamsChannel' - properties: { - channelName: 'MsTeamsChannel' - } -} diff --git a/packages/cli/configs/atk/embed/typescript/teamsapp.local.yml.hbs b/packages/cli/configs/atk/embed/typescript/teamsapp.local.yml.hbs deleted file mode 100644 index 9349df507..000000000 --- a/packages/cli/configs/atk/embed/typescript/teamsapp.local.yml.hbs +++ /dev/null @@ -1,101 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/1.0.0/yaml.schema.json -# -# The teamsapp.local.yml composes automation tasks for M365 Agents Toolkit when running locally. -# This file is used when running Start Debugging (F5) from Visual Studio Code or with the TeamsFx CLI commands. -# i.e. `teamsfx provision --env local` or `teamsfx deploy --env local`. -# -# You can customize this file. Visit https://aka.ms/teamsfx-v5.0-guide for more info about M365 Agents Toolkit project files. -version: 1.0.0 - -environmentFolderPath: ./env - -# Defines what the `provision` lifecycle step does with M365 Agents Toolkit. -# Runs first during Start Debugging (F5) or run manually using `teamsfx provision --env local`. -provision: - - uses: aadApp/create - with: - # Note: when you run aadApp/update, the Microsoft Entra app name will be updated - # based on the definition in manifest. If you don't want to change the - # name, make sure the name in Microsoft Entra manifest is the same with the name - # defined here. - name: {{ toPascalCase name }} - # If the value is false, the action will not generate client secret for you - generateClientSecret: true - # Authenticate users with a Microsoft work or school account in your - # organization's Microsoft Entra tenant (for example, single tenant). - signInAudience: AzureADMultipleOrgs - # Write the information of created resources into environment file for the - # specified environment variable(s). - writeToEnvironmentFile: - clientId: BOT_ID - # Environment variable that starts with `SECRET_` will be stored to the - # .env.{envName}.user environment file - clientSecret: SECRET_BOT_PASSWORD - objectId: AAD_APP_OBJECT_ID - tenantId: AAD_APP_TENANT_ID - authority: AAD_APP_OAUTH_AUTHORITY - authorityHost: AAD_APP_OAUTH_AUTHORITY_HOST - - # Automates the creation of a Teams app registration and saves the App ID to an environment file. - - uses: teamsApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID - - # Automates the creation and configuration of a Bot Framework registration which is required for a bot. - # This configures the bot to use the Azure AD app registration created in the previous step. - # M365 Agents Toolkit automatically creates a local Dev Tunnel URL and updates BOT_ENDPOINT when debugging (F5). - - uses: botFramework/create - with: - botId: $\{{BOT_ID}} - name: {{ toPascalCase name }} - messagingEndpoint: $\{{BOT_ENDPOINT}}/api/messages - description: '' - channels: - - name: msteams - - - uses: aadApp/update - with: - # This task sets the SPA redirect URI order to enable Nested App Authentication (NAA) for the embed app. - # Relative path to this file. Environment variables in manifest will - # be replaced before apply to Microsoft Entra app. - manifestPath: ./aad.manifest.json - outputFilePath: ./build/aad.manifest.$\{{TEAMSFX_ENV}}.json - - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates the creation of a Teams app package (.zip). - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - # Relative path to this file. This is the path for built zip file. - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - -# Defines what the `deploy` lifecycle step does with M365 Agents Toolkit. -# Runs after `provision` during Start Debugging (F5) or run manually using `teamsfx deploy --env local`. -deploy: - # Install any dependencies and build the web app using NPM - - uses: cli/runNpmCommand - name: install dependencies - with: - args: install --no-audit --workspaces=false - # Provides the M365 Agents Toolkit .env file values to the apps runtime so they can be accessed with `process.env`. - - uses: file/createOrUpdateEnvironmentFile - with: - target: ./.env - envs: - PORT: 3978 - CLIENT_ID: $\{{BOT_ID}} - CLIENT_SECRET: $\{{SECRET_BOT_PASSWORD}} - TENANT_ID: $\{{AAD_APP_TENANT_ID}} diff --git a/packages/cli/configs/atk/embed/typescript/teamsapp.testtool.yml b/packages/cli/configs/atk/embed/typescript/teamsapp.testtool.yml deleted file mode 100644 index e9dab22c2..000000000 --- a/packages/cli/configs/atk/embed/typescript/teamsapp.testtool.yml +++ /dev/null @@ -1,26 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/v1.5/yaml.schema.json -# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file -# Visit https://aka.ms/teamsfx-actions for details on actions -version: v1.5 - -deploy: - # Install development tool(s) - - uses: devTool/install - with: - testTool: - version: ~0.2.1 - symlinkDir: ./devTools/teamsapptester - - # Run npm command - - uses: cli/runNpmCommand - with: - args: install --no-audit --workspaces=false - - # Generate runtime environment variables - - uses: file/createOrUpdateEnvironmentFile - with: - target: ./.env - envs: - NODE_ENV: local - PORT: 3978 - TEAMSFX_NOTIFICATION_STORE_FILENAME: ${{TEAMSFX_NOTIFICATION_STORE_FILENAME}} diff --git a/packages/cli/configs/atk/embed/typescript/teamsapp.yml.hbs b/packages/cli/configs/atk/embed/typescript/teamsapp.yml.hbs deleted file mode 100644 index 897aa6629..000000000 --- a/packages/cli/configs/atk/embed/typescript/teamsapp.yml.hbs +++ /dev/null @@ -1,138 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/1.0.0/yaml.schema.json -# -# The teamsapp.yml composes automation tasks for M365 Agents Toolkit when running other environment configurations. -# This file is used when selecting the Provision, Deploy, or Publish menu items in the M365 Agents Toolkit for Visual Studio Code window -# or with the TeamsFx CLI commands. -# i.e. `teamsfx provision --env {environment name}` or `teamsfx deploy --env {environment name}`. -# -# You can customize this file. Visit https://aka.ms/teamsfx-v5.0-guide for more info about M365 Agents Toolkit project files. -version: 1.0.0 - -environmentFolderPath: ./env - -# Defines what the `provision` lifecycle step does with M365 Agents Toolkit. -# Runs with the Provision menu or CLI using `teamsfx provision --env {environment name}`. -provision: - - uses: aadApp/create - with: - # Note: when you run aadApp/update, the Microsoft Entra app name will be updated - # based on the definition in manifest. If you don't want to change the - # name, make sure the name in Microsoft Entra manifest is the same with the name - # defined here. - name: {{ toPascalCase name }} - # If the value is false, the action will not generate client secret for you - generateClientSecret: true - # Authenticate users with a Microsoft work or school account in your - # organization's Microsoft Entra tenant (for example, single tenant). - signInAudience: AzureADMultipleOrgs - # Write the information of created resources into environment file for the - # specified environment variable(s). - writeToEnvironmentFile: - clientId: BOT_ID - # Environment variable that starts with `SECRET_` will be stored to the - # .env.{envName}.user environment file - clientSecret: SECRET_BOT_PASSWORD - objectId: AAD_APP_OBJECT_ID - tenantId: AAD_APP_TENANT_ID - authority: AAD_APP_OAUTH_AUTHORITY - authorityHost: AAD_APP_OAUTH_AUTHORITY_HOST - - # Automates the creation of a Teams app registration and saves the App ID to an environment file. - - uses: teamsApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID - - # Automates the creation of infrastructure defined in ARM templates to host the bot. - # The created resource IDs are saved to an environment file. - - uses: arm/deploy - with: - subscriptionId: $\{{AZURE_SUBSCRIPTION_ID}} - resourceGroupName: $\{{AZURE_RESOURCE_GROUP_NAME}} - templates: - - path: ./infra/azure.bicep - parameters: ./infra/azure.parameters.json - deploymentName: Create-resources-for-{{ toKebabCase name }}-$\{{TEAMSFX_ENV}} - bicepCliVersion: v0.9.1 - - - uses: aadApp/update - with: - # This task sets the SPA redirect URI order to enable Nested App Authentication (NAA) for the embed app. - # Relative path to this file. Environment variables in manifest will - # be replaced before apply to Microsoft Entra app. - manifestPath: ./aad.manifest.json - outputFilePath: ./build/aad.manifest.$\{{TEAMSFX_ENV}}.json - - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates creating a final app package (.zip) by replacing any variables in the manifest.json file for the current environment. - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Optional: Automates an app package check for errors that would prevent the app from being published and reports any problems. - - uses: teamsApp/validateAppPackage - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - -# Defines what the `deploy` lifecycle step does with M365 Agents Toolkit. -# Runs with the Deploy menu or CLI using `teamsfx deploy --env {environment name}`. -deploy: - # Install any dependencies and build the web app using NPM - - uses: cli/runNpmCommand - name: install dependencies - with: - args: install - - - uses: cli/runNpmCommand - name: build app - with: - args: run build --if-present - - # Deploy to an Azure App Service using the zip file created in the provision step. - - uses: azureAppService/zipDeploy - with: - artifactFolder: . - ignoreFile: .webappignore - # This example uses the env var thats generated by the arm/deploy action. - # You can replace it with an existing Azure Resource ID or other - # custom environment variable. - resourceId: $\{{BOT_AZURE_APP_SERVICE_RESOURCE_ID}} - -# Defines what the `publish` lifecycle step does with M365 Agents Toolkit. -# Runs with the Deploy menu or CLI using `teamsfx publish --env {environment name}`. -publish: - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates creating a final app package (.zip) by replacing any variables in the manifest.json file for the current environment. - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Optional: Automates an app package check for errors that would prevent the app from being published and reports any problems. - - uses: teamsApp/validateAppPackage - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip diff --git a/packages/cli/configs/atk/oauth/python/.vscode/launch.json b/packages/cli/configs/atk/oauth/python/.vscode/launch.json deleted file mode 100644 index c318776b2..000000000 --- a/packages/cli/configs/atk/oauth/python/.vscode/launch.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Launch Remote (Edge)", - "type": "msedge", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "remote", - "order": 1 - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch Remote (Chrome)", - "type": "chrome", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "remote", - "order": 2 - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch App (Edge)", - "type": "msedge", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch App (Chrome)", - "type": "chrome", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Start", - "type": "debugpy", - "request": "launch", - "python": "${workspaceFolder}/.venv/bin/python", - "program": "${workspaceFolder}/src/main.py", - "console": "integratedTerminal" - } - ], - "compounds": [ - { - "name": "Debug (Edge)", - "configurations": ["Launch App (Edge)", "Start"], - "preLaunchTask": "Start Teams App Locally", - "presentation": { - "group": "all", - "order": 1 - }, - "stopAll": true - }, - { - "name": "Debug (Chrome)", - "configurations": ["Launch App (Chrome)" , "Start"], - "preLaunchTask": "Start Teams App Locally", - "presentation": { - "group": "all", - "order": 2 - }, - "stopAll": true - } - ] -} diff --git a/packages/cli/configs/atk/oauth/python/.vscode/tasks.json b/packages/cli/configs/atk/oauth/python/.vscode/tasks.json deleted file mode 100644 index 6c65be5c2..000000000 --- a/packages/cli/configs/atk/oauth/python/.vscode/tasks.json +++ /dev/null @@ -1,82 +0,0 @@ -// This file is automatically generated by M365 Agents Toolkit. -// The teamsfx tasks defined in this file require M365 Agents Toolkit version >= 5.0.0. -// See https://aka.ms/teamsfx-tasks for details on how to customize each task. -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Start Teams App Locally", - "dependsOn": [ - "Validate prerequisites", - "Start local tunnel", - "Provision", - "Deploy", - "setup-env" - ], - "dependsOrder": "sequence" - }, - { - "label": "Validate prerequisites", - "type": "teamsfx", - "command": "debug-check-prerequisites", - "args": { - "prerequisites": [ - "python", - "m365Account", - "portOccupancy" - ], - "portOccupancy": [ - 3978 - ] - } - }, - { - "label": "Start local tunnel", - "type": "teamsfx", - "command": "debug-start-local-tunnel", - "args": { - "type": "dev-tunnel", - "ports": [ - { - "portNumber": 3978, - "protocol": "http", - "access": "public", - "writeToEnvironmentFile": { - "endpoint": "BOT_ENDPOINT", - "domain": "BOT_DOMAIN" - } - } - ], - "env": "local" - }, - "isBackground": true, - "problemMatcher": "$teamsfx-local-tunnel-watch" - }, - { - "label": "Provision", - "type": "teamsfx", - "command": "provision", - "args": { - "env": "local" - } - }, - { - "label": "Deploy", - "type": "teamsfx", - "command": "deploy", - "args": { - "env": "local" - } - }, - { - "label": "setup-env", - "type": "shell", - "command": "pip install -e .", - "problemMatcher": [], - "group": { - "kind": "build", - "isDefault": true - } - } - ] -} diff --git a/packages/cli/configs/atk/oauth/python/README.md b/packages/cli/configs/atk/oauth/python/README.md deleted file mode 100644 index 461d743ae..000000000 --- a/packages/cli/configs/atk/oauth/python/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# M365 Agents Toolkit Configuration: Oauth - -Use this if you want to enable user authentication in your Teams application. - -## How to update scopes - -1. In the `aad.manifest.json` file, update the `requiredResourceAccess` list to add the required scopes. - -2. In the `infra/botRegistration/azurebot.bicep` file, under the `botServicesMicrosoftGraphConnection` resource, update the `properties.scopes` string to be a comma-delimited list of the required scopes. - -### Example - -If you want to add the `People.Read.All` and `User.ReadBasic.All` scopes. - -1. Your `requiredResourceAccess` property should look like: - -```json -"requiredResourceAccess": [ - { - "resourceAppId": "Microsoft Graph", - "resourceAccess": [ - { - "id": "People.Read.All", - "type": "Scope" - } - ] - }, - { - "resourceAppId": "Microsoft Graph", - "resourceAccess": [ - { - "id": "User.ReadBasic.All", - "type": "Scope" - } - ] - }, -] -``` - -2. Update the `properties.scopes` to be `People.Read.All,User.ReadBasic.All`. - -Refer [here](https://learn.microsoft.com/en-us/graph/permissions-reference) for in-depth Microsoft Graph permissions reference. diff --git a/packages/cli/configs/atk/oauth/python/aad.manifest.json.hbs b/packages/cli/configs/atk/oauth/python/aad.manifest.json.hbs deleted file mode 100644 index 63cae9b80..000000000 --- a/packages/cli/configs/atk/oauth/python/aad.manifest.json.hbs +++ /dev/null @@ -1,65 +0,0 @@ -{ - "id": "$\{{AAD_APP_OBJECT_ID}}", - "appId": "$\{{BOT_ID}}", - "name": "{{ toPascalCase name }}$\{{APP_NAME_SUFFIX}}", - "accessTokenAcceptedVersion": 2, - "signInAudience": "AzureADMultipleOrgs", - "optionalClaims": { - "idToken": [], - "accessToken": [ - { - "name": "idtyp", - "source": null, - "essential": false, - "additionalProperties": [] - } - ], - "saml2Token": [] - }, - "requiredResourceAccess": [ - { - "resourceAppId": "Microsoft Graph", - "resourceAccess": [ - { - "id": "User.Read", - "type": "Scope" - } - ] - } - ], - "oauth2Permissions": [ - { - "adminConsentDescription": "Allows Teams to call the app's web APIs as the current user.", - "adminConsentDisplayName": "Teams can access app's web APIs", - "id": "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}", - "isEnabled": true, - "type": "User", - "userConsentDescription": "Enable Teams to call this app's web APIs with the same rights that you have", - "userConsentDisplayName": "Teams can access app's web APIs and make requests on your behalf", - "value": "access_as_user" - } - ], - "preAuthorizedApplications": [ - { - "appId": "1fec8e78-bce4-4aaf-ab1b-5451cc387264", - "permissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "5e3ce6c0-2b1f-4285-8d4b-75ee78787346", - "permissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - } - ], - "identifierUris": [ - "api://botid-$\{{BOT_ID}}" - ], - "replyUrlsWithType": [ - { - "url": "https://token.botframework.com/.auth/web/redirect", - "type": "Web" - } - ] -} diff --git a/packages/cli/configs/atk/oauth/python/env/.env.dev b/packages/cli/configs/atk/oauth/python/env/.env.dev deleted file mode 100644 index 7bc662ca9..000000000 --- a/packages/cli/configs/atk/oauth/python/env/.env.dev +++ /dev/null @@ -1,16 +0,0 @@ -# Built-in environment variables -TEAMSFX_ENV=dev -APP_NAME_SUFFIX=dev - -# Updating AZURE_SUBSCRIPTION_ID or AZURE_RESOURCE_GROUP_NAME after provision may also require an update to RESOURCE_SUFFIX, because some services require a globally unique name across subscriptions/resource groups. -AZURE_SUBSCRIPTION_ID= -AZURE_RESOURCE_GROUP_NAME= -RESOURCE_SUFFIX= - -TEAMS_APP_ID= -TEAMS_APP_TENANT_ID= -BOT_ID= -AAD_APP_OBJECT_ID= -AAD_APP_TENANT_ID= -BOT_AZURE_APP_SERVICE_RESOURCE_ID= -BOT_DOMAIN= diff --git a/packages/cli/configs/atk/oauth/python/infra/azure.bicep b/packages/cli/configs/atk/oauth/python/infra/azure.bicep deleted file mode 100644 index e86b55ffa..000000000 --- a/packages/cli/configs/atk/oauth/python/infra/azure.bicep +++ /dev/null @@ -1,89 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -@description('Required when create Azure Bot service') -param botAadAppClientId string - -@secure() -@description('Required by Bot Framework package in your bot project') -param botAadAppClientSecret string - -@maxLength(42) -param botDisplayName string - -param webAppSKU string -param linuxFxVersion string -param oauthConnectionName string -param tenantId string - -param serverfarmsName string = resourceBaseName -param webAppName string = resourceBaseName -param location string = resourceGroup().location -param pythonVersion string = linuxFxVersion - -// Compute resources for your Web App -resource serverfarm 'Microsoft.Web/serverfarms@2021-02-01' = { - kind: 'app,linux' - location: location - name: serverfarmsName - sku: { - name: webAppSKU - } - properties:{ - reserved: true - } -} - -// Web App that hosts your agent -// Web App that hosts your bot -resource webApp 'Microsoft.Web/sites@2021-02-01' = { - kind: 'app,linux' - location: location - name: webAppName - properties: { - serverFarmId: serverfarm.id - siteConfig: { - alwaysOn: true - appCommandLine: 'python main.py' - linuxFxVersion: pythonVersion - appSettings: [ - { - name: 'SCM_DO_BUILD_DURING_DEPLOYMENT' - value: 'true' - } - { - name: 'CLIENT_ID' - value: botAadAppClientId - } - { - name: 'CLIENT_SECRET' - value: botAadAppClientSecret - } - { - name: 'TENANT_ID' - value: tenantId - } - ] - ftpsState: 'FtpsOnly' - } - } -} - -// Register your web service as a bot with the Bot Framework -module azureBotRegistration './botRegistration/azurebot.bicep' = { - name: 'Azure-Bot-registration' - params: { - resourceBaseName: resourceBaseName - botAadAppClientId: botAadAppClientId - botAddAppClientSecret: botAadAppClientSecret - botAppDomain: webApp.properties.defaultHostName - botDisplayName: botDisplayName - oauthConnectionName: oauthConnectionName - tenantId: tenantId - } -} - -output BOT_AZURE_APP_SERVICE_RESOURCE_ID string = webApp.id -output BOT_DOMAIN string = webApp.properties.defaultHostName diff --git a/packages/cli/configs/atk/oauth/python/infra/azure.local.bicep b/packages/cli/configs/atk/oauth/python/infra/azure.local.bicep deleted file mode 100644 index 3579b84c6..000000000 --- a/packages/cli/configs/atk/oauth/python/infra/azure.local.bicep +++ /dev/null @@ -1,31 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -@description('Required when create Azure Bot service') -param botAadAppClientId string - -@secure() -@description('Required by Bot Framework package in your bot project') -param botAadAppClientSecret string - -@maxLength(42) -param botDisplayName string - -param botAppDomain string -param oauthConnectionName string -param tenantId string - -module azureBotRegistration './botRegistration/azurebot.bicep' = { - name: 'Azure-Bot-registration' - params: { - resourceBaseName: resourceBaseName - botAadAppClientId: botAadAppClientId - botAppDomain: botAppDomain - botDisplayName: botDisplayName - botAddAppClientSecret: botAadAppClientSecret - oauthConnectionName: oauthConnectionName - tenantId: tenantId - } -} diff --git a/packages/cli/configs/atk/oauth/python/infra/azure.parameters.json.hbs b/packages/cli/configs/atk/oauth/python/infra/azure.parameters.json.hbs deleted file mode 100644 index 522a48fe0..000000000 --- a/packages/cli/configs/atk/oauth/python/infra/azure.parameters.json.hbs +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "resourceBaseName": { - "value": "bot-$\{{RESOURCE_SUFFIX}}-$\{{TEAMSFX_ENV}}" - }, - "webAppSKU": { - "value": "B1" - }, - "botAadAppClientId": { - "value": "$\{{BOT_ID}}" - }, - "botAadAppClientSecret": { - "value": "$\{{SECRET_BOT_PASSWORD}}" - }, - "oauthConnectionName": { - "value": "$\{{OAUTH_CONNECTION_NAME}}" - }, - "tenantId": { - "value": "$\{{AAD_APP_TENANT_ID}}" - }, - "linuxFxVersion": { - "value": "PYTHON|3.12" - }, - "botDisplayName": { - "value": "{{ toPascalCase name }}Infra" - } - - } -} diff --git a/packages/cli/configs/atk/oauth/python/infra/azure.parameters.local.json.hbs b/packages/cli/configs/atk/oauth/python/infra/azure.parameters.local.json.hbs deleted file mode 100644 index eae4d85c0..000000000 --- a/packages/cli/configs/atk/oauth/python/infra/azure.parameters.local.json.hbs +++ /dev/null @@ -1,27 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "resourceBaseName": { - "value": "bot-$\{{RESOURCE_SUFFIX}}-$\{{TEAMSFX_ENV}}" - }, - "botAadAppClientId": { - "value": "$\{{BOT_ID}}" - }, - "botAadAppClientSecret": { - "value": "$\{{SECRET_BOT_PASSWORD}}" - }, - "botDisplayName": { - "value": "{{ toPascalCase name }}-$\{{TEAMSFX_ENV}}" - }, - "botAppDomain": { - "value": "$\{{BOT_DOMAIN}}" - }, - "oauthConnectionName": { - "value": "$\{{OAUTH_CONNECTION_NAME}}" - }, - "tenantId": { - "value": "$\{{AAD_APP_TENANT_ID}}" - } - } -} diff --git a/packages/cli/configs/atk/oauth/python/infra/botRegistration/azurebot.bicep b/packages/cli/configs/atk/oauth/python/infra/botRegistration/azurebot.bicep deleted file mode 100644 index 148b0bada..000000000 --- a/packages/cli/configs/atk/oauth/python/infra/botRegistration/azurebot.bicep +++ /dev/null @@ -1,67 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -@maxLength(42) -param botDisplayName string - -param botServiceName string = resourceBaseName -param botServiceSku string = 'F0' -param botAadAppClientId string -param botAppDomain string -param oauthConnectionName string -param tenantId string - -@secure() -param botAddAppClientSecret string - -// Register your web service as a bot with the Bot Framework -resource botService 'Microsoft.BotService/botServices@2021-03-01' = { - kind: 'azurebot' - location: 'global' - name: botServiceName - properties: { - displayName: botDisplayName - endpoint: 'https://${botAppDomain}/api/messages' - msaAppId: botAadAppClientId - msaAppType: 'SingleTenant' - msaAppTenantId: tenantId - } - sku: { - name: botServiceSku - } -} - -// Connect the bot service to Microsoft Teams -resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = { - parent: botService - location: 'global' - name: 'MsTeamsChannel' - properties: { - channelName: 'MsTeamsChannel' - } -} - -resource botServicesMicrosoftGraphConnection 'Microsoft.BotService/botServices/connections@2022-09-15' = { - parent: botService - name: oauthConnectionName - location: 'global' - properties: { - serviceProviderDisplayName: 'Azure Active Directory v2' - serviceProviderId: '30dd229c-58e3-4a48-bdfd-91ec48eb906c' - clientId: botAadAppClientId - clientSecret: botAddAppClientSecret - scopes: 'User.Read' - parameters: [ - { - key: 'tenantID' - value: 'common' - } - { - key: 'tokenExchangeUrl' - value: 'api://botid-${botAadAppClientId}' - } - ] - } -} diff --git a/packages/cli/configs/atk/oauth/python/teamsapp.local.yml.hbs b/packages/cli/configs/atk/oauth/python/teamsapp.local.yml.hbs deleted file mode 100644 index 662955de2..000000000 --- a/packages/cli/configs/atk/oauth/python/teamsapp.local.yml.hbs +++ /dev/null @@ -1,109 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/1.0.0/yaml.schema.json -# -# The teamsapp.local.yml composes automation tasks for M365 Agents Toolkit when running locally. -# This file is used when running Start Debugging (F5) from Visual Studio Code or with the TeamsFx CLI commands. -# i.e. `teamsfx provision --env local` or `teamsfx deploy --env local`. -# -# You can customize this file. Visit https://aka.ms/teamsfx-v5.0-guide for more info about M365 Agents Toolkit project files. -version: 1.0.0 - -environmentFolderPath: ./env - -# Defines what the `provision` lifecycle step does with M365 Agents Toolkit. -# Runs first during Start Debugging (F5) or run manually using `teamsfx provision --env local`. -provision: - # Automates the creation of a Teams app registration and saves the App ID to an environment file. - - uses: teamsApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID - - # Creates a new Microsoft Entra app to authenticate users if - # the environment variable that stores clientId is empty - - uses: aadApp/create - with: - # Note: when you run aadApp/update, the Microsoft Entra app name will be updated - # based on the definition in manifest. If you don't want to change the - # name, make sure the name in Microsoft Entra manifest is the same with the name - # defined here. - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - # If the value is false, the driver will not generate client secret for you - generateClientSecret: true - # organization's Microsoft Entra tenant (for example, single tenant). - signInAudience: AzureADMultipleOrgs - # Write the information of created resources into environment file for the - # specified environment variable(s). - writeToEnvironmentFile: - clientId: BOT_ID - # Environment variable that starts with `SECRET_` will be stored to the - # .env.{envName}.user environment file - clientSecret: SECRET_BOT_PASSWORD - objectId: AAD_APP_OBJECT_ID - tenantId: AAD_APP_TENANT_ID - - # Apply the Microsoft Entra manifest to an existing Microsoft Entra app. Will use the object id in - # manifest file to determine which Microsoft Entra app to update. - - uses: aadApp/update - with: - # Relative path to this file. Environment variables in manifest will - # be replaced before apply to Microsoft Entra app - manifestPath: ./aad.manifest.json - outputFilePath: ./build/aad.manifest.$\{{TEAMSFX_ENV}}.json - - - uses: arm/deploy # Deploy given ARM templates parallelly. - env: - # an arbitrary name for the connection - OAUTH_CONNECTION_NAME: graph - with: - # AZURE_SUBSCRIPTION_ID is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select a subscription. - # Referencing other environment variables with empty values - # will skip the subscription selection prompt. - subscriptionId: $\{{AZURE_SUBSCRIPTION_ID}} - # AZURE_RESOURCE_GROUP_NAME is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select or create one - # resource group. - # Referencing other environment variables with empty values - # will skip the resource group selection prompt. - resourceGroupName: $\{{AZURE_RESOURCE_GROUP_NAME}} - templates: - - path: ./infra/azure.local.bicep # Relative path to this file - # Relative path to this yaml file. - # Placeholders will be replaced with corresponding environment - # variable before ARM deployment. - parameters: ./infra/azure.parameters.local.json - # Required when deploying ARM template - deploymentName: Create-resources-for-{{ toKebabCase name }}-$\{{TEAMSFX_ENV}} - bicepCliVersion: v0.9.1 - - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates the creation of a Teams app package (.zip). - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - # Relative path to this file. This is the path for built zip file. - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - -deploy: - - uses: file/createOrUpdateEnvironmentFile - with: - target: ./.env - envs: - PORT: 3978 - CLIENT_ID: $\{{BOT_ID}} - CLIENT_SECRET: $\{{SECRET_BOT_PASSWORD}} - TENANT_ID: $\{{AAD_APP_TENANT_ID}} - # an arbitrary name for the connection - OAUTH_CONNECTION_NAME: graph diff --git a/packages/cli/configs/atk/oauth/python/teamsapp.yml.hbs b/packages/cli/configs/atk/oauth/python/teamsapp.yml.hbs deleted file mode 100644 index a9f8302ab..000000000 --- a/packages/cli/configs/atk/oauth/python/teamsapp.yml.hbs +++ /dev/null @@ -1,144 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/1.0.0/yaml.schema.json -# -# The teamsapp.yml composes automation tasks for M365 Agents Toolkit when running other environment configurations. -# This file is used when selecting the Provision, Deploy, or Publish menu items in the M365 Agents Toolkit for Visual Studio Code window -# or with the TeamsFx CLI commands. -# i.e. `teamsfx provision --env {environment name}` or `teamsfx deploy --env {environment name}`. -# -# You can customize this file. Visit https://aka.ms/teamsfx-v5.0-guide for more info about M365 Agents Toolkit project files. -version: 1.0.0 - -environmentFolderPath: ./env - -# Defines what the `provision` lifecycle step does with M365 Agents Toolkit. -# Runs with the Provision menu or CLI using `teamsfx provision --env {environment name}`. -provision: - # Automates the creation of a Teams app registration and saves the App ID to an environment file. - - uses: teamsApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID - - # Creates a new Microsoft Entra app to authenticate users if - # the environment variable that stores clientId is empty - - uses: aadApp/create - with: - # Note: when you run aadApp/update, the Microsoft Entra app name will be updated - # based on the definition in manifest. If you don't want to change the - # name, make sure the name in Microsoft Entra manifest is the same with the name - # defined here. - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - # If the value is false, the driver will not generate client secret for you - generateClientSecret: true - # organization's Microsoft Entra tenant (for example, single tenant). - signInAudience: AzureADMultipleOrgs - # Write the information of created resources into environment file for the - # specified environment variable(s). - writeToEnvironmentFile: - clientId: BOT_ID - # Environment variable that starts with `SECRET_` will be stored to the - # .env.{envName}.user environment file - clientSecret: SECRET_BOT_PASSWORD - objectId: AAD_APP_OBJECT_ID - tenantId: AAD_APP_TENANT_ID - - # Apply the Microsoft Entra manifest to an existing Microsoft Entra app. Will use the object id in - # manifest file to determine which Microsoft Entra app to update. - - uses: aadApp/update - with: - # Relative path to this file. Environment variables in manifest will - # be replaced before apply to Microsoft Entra app - manifestPath: ./aad.manifest.json - outputFilePath: ./build/aad.manifest.$\{{TEAMSFX_ENV}}.json - - - uses: arm/deploy # Deploy given ARM templates parallelly. - env: - # an arbitrary name for the connection - OAUTH_CONNECTION_NAME: graph - with: - # AZURE_SUBSCRIPTION_ID is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select a subscription. - # Referencing other environment variables with empty values - # will skip the subscription selection prompt. - subscriptionId: $\{{AZURE_SUBSCRIPTION_ID}} - # AZURE_RESOURCE_GROUP_NAME is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select or create one - # resource group. - # Referencing other environment variables with empty values - # will skip the resource group selection prompt. - resourceGroupName: $\{{AZURE_RESOURCE_GROUP_NAME}} - templates: - - path: ./infra/azure.bicep # Relative path to this file - # Relative path to this yaml file. - # Placeholders will be replaced with corresponding environment - # variable before ARM deployment. - parameters: ./infra/azure.parameters.json - # Required when deploying ARM template - deploymentName: Create-resources-for-{{ toKebabCase name }}-$\{{TEAMSFX_ENV}} - bicepCliVersion: v0.9.1 - - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates creating a final app package (.zip) by replacing any variables in the manifest.json file for the current environment. - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Optional: Automates an app package check for errors that would prevent the app from being published and reports any problems. - - uses: teamsApp/validateAppPackage - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - -deploy: - # Deploy to an Azure App Service using the zip file created in the provision step. - - uses: script - with: - run: | - pip install . - pip freeze > src/requirements.txt - - uses: azureAppService/zipDeploy - with: - artifactFolder: src - ignoreFile: .webappignore - # This example uses the env var thats generated by the arm/deploy action. - # You can replace it with an existing Azure Resource ID or other - # custom environment variable. - resourceId: $\{{BOT_AZURE_APP_SERVICE_RESOURCE_ID}} - -# Defines what the `publish` lifecycle step does with M365 Agents Toolkit. -# Runs with the Deploy menu or CLI using `teamsfx publish --env {environment name}`. -publish: - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates creating a final app package (.zip) by replacing any variables in the manifest.json file for the current environment. - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Optional: Automates an app package check for errors that would prevent the app from being published and reports any problems. - - uses: teamsApp/validateAppPackage - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip diff --git a/packages/cli/configs/atk/oauth/typescript/.vscode/launch.json b/packages/cli/configs/atk/oauth/typescript/.vscode/launch.json deleted file mode 100644 index 4f6e6a549..000000000 --- a/packages/cli/configs/atk/oauth/typescript/.vscode/launch.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Launch Remote (Edge)", - "type": "msedge", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "remote", - "order": 1 - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch Remote (Chrome)", - "type": "chrome", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "presentation": { - "group": "remote", - "order": 2 - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch App (Edge)", - "type": "msedge", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "cascadeTerminateToConfigurations": ["Attach to Local Service"], - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Launch App (Chrome)", - "type": "chrome", - "request": "launch", - "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", - "cascadeTerminateToConfigurations": ["Attach to Local Service"], - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - }, - { - "name": "Attach to Local Service", - "type": "node", - "request": "attach", - "port": 9239, - "restart": true, - "presentation": { - "group": "all", - "hidden": true - }, - "internalConsoleOptions": "neverOpen" - } - ], - "compounds": [ - { - "name": "Debug (Edge)", - "configurations": ["Launch App (Edge)", "Attach to Local Service"], - "preLaunchTask": "Start Teams App Locally", - "presentation": { - "group": "all", - "order": 1 - }, - "stopAll": true - }, - { - "name": "Debug (Chrome)", - "configurations": ["Launch App (Chrome)", "Attach to Local Service"], - "preLaunchTask": "Start Teams App Locally", - "presentation": { - "group": "all", - "order": 2 - }, - "stopAll": true - }, - { - "name": "Debug in Test Tool", - "configurations": ["Attach to Local Service"], - "preLaunchTask": "Start Teams App (Test Tool)", - "presentation": { - "group": "local", - "order": 1 - }, - "stopAll": true - } - ] -} diff --git a/packages/cli/configs/atk/oauth/typescript/.vscode/tasks.json b/packages/cli/configs/atk/oauth/typescript/.vscode/tasks.json deleted file mode 100644 index 1bce0df16..000000000 --- a/packages/cli/configs/atk/oauth/typescript/.vscode/tasks.json +++ /dev/null @@ -1,204 +0,0 @@ -// This file is automatically generated by M365 Agents Toolkit. -// The teamsfx tasks defined in this file require M365 Agents Toolkit version >= 5.0.0. -// See https://aka.ms/teamsfx-tasks for details on how to customize each task. -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Start Teams App Locally", - "dependsOn": [ - "Validate prerequisites", - "Start local tunnel", - "Provision", - "Deploy", - "Start application" - ], - "dependsOrder": "sequence" - }, - { - // Check all required prerequisites. - // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. - "label": "Validate prerequisites", - "type": "teamsfx", - "command": "debug-check-prerequisites", - "args": { - "prerequisites": [ - "nodejs", // Validate if Node.js is installed. - "m365Account", // Sign-in prompt for Microsoft 365 account, then validate if the account enables the sideloading permission. - "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. - ], - "portOccupancy": [ - 3978, // app service port - 9239 // app inspector port for Node.js debugger - ] - } - }, - { - // Start the local tunnel service to forward public URL to local port and inspect traffic. - // See https://aka.ms/teamsfx-tasks/local-tunnel for the detailed args definitions. - "label": "Start local tunnel", - "type": "teamsfx", - "command": "debug-start-local-tunnel", - "args": { - "type": "dev-tunnel", - "ports": [ - { - "portNumber": 3978, - "protocol": "http", - "access": "public", - "writeToEnvironmentFile": { - "endpoint": "BOT_ENDPOINT", // output tunnel endpoint as BOT_ENDPOINT - "domain": "BOT_DOMAIN" // output tunnel domain as BOT_DOMAIN - } - } - ], - "env": "local" - }, - "isBackground": true, - "problemMatcher": "$teamsfx-local-tunnel-watch" - }, - { - // Create the debug resources. - // See https://aka.ms/teamsfx-tasks/provision to know the details and how to customize the args. - "label": "Provision", - "type": "teamsfx", - "command": "provision", - "args": { - "env": "local" - } - }, - { - // Build project. - // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. - "label": "Deploy", - "type": "teamsfx", - "command": "deploy", - "args": { - "env": "local" - } - }, - { - "label": "Start application", - "type": "shell", - "command": "npm run dev:teamsfx", - "isBackground": true, - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": { - "pattern": [ - { - "regexp": "^.*$", - "file": 0, - "location": 1, - "message": 2 - } - ], - "background": { - "activeOnStart": true, - "beginsPattern": "[nodemon] starting", - "endsPattern": "listening|[nodemon] app crashed" - } - } - }, - { - "label": "Start Teams App (Test Tool)", - "dependsOn": [ - "Validate prerequisites (Test Tool)", - "Deploy (Test Tool)", - "Start application (Test Tool)", - "Start Test Tool" - ], - "dependsOrder": "sequence" - }, - { - // Check all required prerequisites. - // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. - "label": "Validate prerequisites (Test Tool)", - "type": "teamsfx", - "command": "debug-check-prerequisites", - "args": { - "prerequisites": [ - "nodejs", // Validate if Node.js is installed. - "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. - ], - "portOccupancy": [ - 3978, // app service port - 9239, // app inspector port for Node.js debugger - 56150 // test tool port - ] - } - }, - { - // Build project. - // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. - "label": "Deploy (Test Tool)", - "type": "teamsfx", - "command": "deploy", - "args": { - "env": "testtool" - } - }, - { - "label": "Start application (Test Tool)", - "type": "shell", - "command": "npm run dev:teamsfx:testtool", - "isBackground": true, - "options": { - "cwd": "${workspaceFolder}" - }, - "problemMatcher": { - "pattern": [ - { - "regexp": "^.*$", - "file": 0, - "location": 1, - "message": 2 - } - ], - "background": { - "activeOnStart": true, - "beginsPattern": "[nodemon] starting", - "endsPattern": "listening|[nodemon] app crashed" - } - } - }, - { - "label": "Start Test Tool", - "type": "shell", - "command": "npm run dev:teamsfx:launch-testtool", - "isBackground": true, - "options": { - "env": { - "PATH": "${workspaceFolder}/devTools/teamsapptester/node_modules/.bin:${env:PATH}" - } - }, - "windows": { - "options": { - "env": { - "PATH": "${workspaceFolder}/devTools/teamsapptester/node_modules/.bin;${env:PATH}" - } - } - }, - "problemMatcher": { - "pattern": [ - { - "regexp": "^.*$", - "file": 0, - "location": 1, - "message": 2 - } - ], - "background": { - "activeOnStart": true, - "beginsPattern": ".*", - "endsPattern": "listening on" - } - }, - "presentation": { - "panel": "dedicated", - "reveal": "silent" - } - } - ] -} diff --git a/packages/cli/configs/atk/oauth/typescript/README.md b/packages/cli/configs/atk/oauth/typescript/README.md deleted file mode 100644 index 0a9cbe7b1..000000000 --- a/packages/cli/configs/atk/oauth/typescript/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# M365 Agents Toolkit Configuration: Oauth - -Use this if you want to enable user authentication in your Teams application. - -## How to update scopes - -1. In the `aad.manifest.json` file, update the `requiredResourceAccess` list to add the required scopes. - -2. In the `infra/botRegistration/azurebot.bicep` file, under the `botServicesMicrosoftGraphConnection` resource, update the `properties.scopes` string to be a comma-delimited list of the required scopes. - -### Example - -If you want to add the `People.Read.All` and `User.ReadBasic.All` scopes. - -1. Your `requiredResourceAccess` property should look like: - -```json -"requiredResourceAccess": [ - { - "resourceAppId": "Microsoft Graph", - "resourceAccess": [ - { - "id": "People.Read.All", - "type": "Scope" - } - ] - }, - { - "resourceAppId": "Microsoft Graph", - "resourceAccess": [ - { - "id": "User.ReadBasic.All", - "type": "Scope" - } - ] - }, -] -``` - -2. Update the `properties.scopes` to be `People.Read.All,User.ReadBasic.All`. diff --git a/packages/cli/configs/atk/oauth/typescript/aad.manifest.json.hbs b/packages/cli/configs/atk/oauth/typescript/aad.manifest.json.hbs deleted file mode 100644 index 0ad1502dd..000000000 --- a/packages/cli/configs/atk/oauth/typescript/aad.manifest.json.hbs +++ /dev/null @@ -1,101 +0,0 @@ -{ - "id": "$\{{AAD_APP_OBJECT_ID}}", - "appId": "$\{{BOT_ID}}", - "name": "{{ toPascalCase name }}$\{{APP_NAME_SUFFIX}}", - "accessTokenAcceptedVersion": 2, - "signInAudience": "AzureADMultipleOrgs", - "optionalClaims": { - "idToken": [], - "accessToken": [ - { - "name": "idtyp", - "source": null, - "essential": false, - "additionalProperties": [] - } - ], - "saml2Token": [] - }, - "requiredResourceAccess": [ - { - "resourceAppId": "Microsoft Graph", - "resourceAccess": [ - { - "id": "User.ReadBasic.All", - "type": "Scope" - } - ] - } - ], - "oauth2Permissions": [ - { - "adminConsentDescription": "Allows Teams to call the app's web APIs as the current user.", - "adminConsentDisplayName": "Teams can access app's web APIs", - "id": "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}", - "isEnabled": true, - "type": "User", - "userConsentDescription": "Enable Teams to call this app's web APIs with the same rights that you have", - "userConsentDisplayName": "Teams can access app's web APIs and make requests on your behalf", - "value": "access_as_user" - } - ], - "preAuthorizedApplications": [ - { - "appId": "1fec8e78-bce4-4aaf-ab1b-5451cc387264", - "permissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "5e3ce6c0-2b1f-4285-8d4b-75ee78787346", - "permissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "d3590ed6-52b3-4102-aeff-aad2292ab01c", - "permissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "00000002-0000-0ff1-ce00-000000000000", - "permissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "bc59ab01-8403-45c6-8796-ac3ef710b3e3", - "permissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "0ec893e0-5785-4de6-99da-4ed124e5296c", - "permissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "4765445b-32c6-49b0-83e6-1d93765276ca", - "permissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - }, - { - "appId": "4345a7b9-9a63-4910-a426-35363201d503", - "permissionIds": [ - "$\{{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}" - ] - } - ], - "identifierUris": [ - "api://botid-$\{{BOT_ID}}" - ], - "replyUrlsWithType": [ - { - "url": "https://token.botframework.com/.auth/web/redirect", - "type": "Web" - } - ] -} diff --git a/packages/cli/configs/atk/oauth/typescript/env/.env.dev b/packages/cli/configs/atk/oauth/typescript/env/.env.dev deleted file mode 100644 index 7bc662ca9..000000000 --- a/packages/cli/configs/atk/oauth/typescript/env/.env.dev +++ /dev/null @@ -1,16 +0,0 @@ -# Built-in environment variables -TEAMSFX_ENV=dev -APP_NAME_SUFFIX=dev - -# Updating AZURE_SUBSCRIPTION_ID or AZURE_RESOURCE_GROUP_NAME after provision may also require an update to RESOURCE_SUFFIX, because some services require a globally unique name across subscriptions/resource groups. -AZURE_SUBSCRIPTION_ID= -AZURE_RESOURCE_GROUP_NAME= -RESOURCE_SUFFIX= - -TEAMS_APP_ID= -TEAMS_APP_TENANT_ID= -BOT_ID= -AAD_APP_OBJECT_ID= -AAD_APP_TENANT_ID= -BOT_AZURE_APP_SERVICE_RESOURCE_ID= -BOT_DOMAIN= diff --git a/packages/cli/configs/atk/oauth/typescript/env/.env.testtool b/packages/cli/configs/atk/oauth/typescript/env/.env.testtool deleted file mode 100644 index c82bc5257..000000000 --- a/packages/cli/configs/atk/oauth/typescript/env/.env.testtool +++ /dev/null @@ -1,5 +0,0 @@ -TEAMSFX_ENV=testtool - -# Environment variables used by test tool -TEAMSAPPTESTER_PORT=56150 -TEAMSFX_NOTIFICATION_STORE_FILENAME=.notification.testtoolstore.json diff --git a/packages/cli/configs/atk/oauth/typescript/infra/azure.bicep b/packages/cli/configs/atk/oauth/typescript/infra/azure.bicep deleted file mode 100644 index 2771a31a7..000000000 --- a/packages/cli/configs/atk/oauth/typescript/infra/azure.bicep +++ /dev/null @@ -1,91 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -@description('Required when create Azure Bot service') -param botAadAppClientId string - -@secure() -@description('Required by Bot Framework package in your bot project') -param botAadAppClientSecret string - -param webAppSKU string - -@maxLength(42) -param botDisplayName string - -param serverfarmsName string = resourceBaseName -param webAppName string = resourceBaseName -param location string = resourceGroup().location -param oauthConnectionName string -param tenantId string - -// Compute resources for your Web App -resource serverfarm 'Microsoft.Web/serverfarms@2021-02-01' = { - kind: 'app' - location: location - name: serverfarmsName - sku: { - name: webAppSKU - } -} - -// Web App that hosts your agent -resource webApp 'Microsoft.Web/sites@2021-02-01' = { - kind: 'app' - location: location - name: webAppName - properties: { - serverFarmId: serverfarm.id - httpsOnly: true - siteConfig: { - alwaysOn: true - appSettings: [ - { - name: 'WEBSITE_RUN_FROM_PACKAGE' - value: '1' // Run Azure APP Service from a package file - } - { - name: 'WEBSITE_NODE_DEFAULT_VERSION' - value: '~20' // Set NodeJS version to 20.x for your site - } - { - name: 'RUNNING_ON_AZURE' - value: '1' - } - { - name: 'CLIENT_ID' - value: botAadAppClientId - } - { - name: 'CLIENT_SECRET' - value: botAadAppClientSecret - } - { - name: 'TENANT_ID' - value: tenantId - } - ] - ftpsState: 'FtpsOnly' - } - } -} - -// Register your web service as a bot with the Bot Framework -module azureBotRegistration './botRegistration/azurebot.bicep' = { - name: 'Azure-Bot-registration' - params: { - resourceBaseName: resourceBaseName - botAadAppClientId: botAadAppClientId - botAddAppClientSecret: botAadAppClientSecret - botAppDomain: webApp.properties.defaultHostName - botDisplayName: botDisplayName - oauthConnectionName: oauthConnectionName - tenantId: tenantId - } -} - -// The output will be persisted in .env.{envName}. Visit https://aka.ms/teamsfx-actions/arm-deploy for more details. -output BOT_AZURE_APP_SERVICE_RESOURCE_ID string = webApp.id -output BOT_DOMAIN string = webApp.properties.defaultHostName diff --git a/packages/cli/configs/atk/oauth/typescript/infra/azure.local.bicep b/packages/cli/configs/atk/oauth/typescript/infra/azure.local.bicep deleted file mode 100644 index 3579b84c6..000000000 --- a/packages/cli/configs/atk/oauth/typescript/infra/azure.local.bicep +++ /dev/null @@ -1,31 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -@description('Required when create Azure Bot service') -param botAadAppClientId string - -@secure() -@description('Required by Bot Framework package in your bot project') -param botAadAppClientSecret string - -@maxLength(42) -param botDisplayName string - -param botAppDomain string -param oauthConnectionName string -param tenantId string - -module azureBotRegistration './botRegistration/azurebot.bicep' = { - name: 'Azure-Bot-registration' - params: { - resourceBaseName: resourceBaseName - botAadAppClientId: botAadAppClientId - botAppDomain: botAppDomain - botDisplayName: botDisplayName - botAddAppClientSecret: botAadAppClientSecret - oauthConnectionName: oauthConnectionName - tenantId: tenantId - } -} diff --git a/packages/cli/configs/atk/oauth/typescript/infra/azure.parameters.json.hbs b/packages/cli/configs/atk/oauth/typescript/infra/azure.parameters.json.hbs deleted file mode 100644 index adb44433f..000000000 --- a/packages/cli/configs/atk/oauth/typescript/infra/azure.parameters.json.hbs +++ /dev/null @@ -1,27 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "resourceBaseName": { - "value": "bot$\{{RESOURCE_SUFFIX}}" - }, - "botAadAppClientId": { - "value": "$\{{BOT_ID}}" - }, - "botAadAppClientSecret": { - "value": "$\{{SECRET_BOT_PASSWORD}}" - }, - "webAppSKU": { - "value": "B1" - }, - "botDisplayName": { - "value": "{{ toPascalCase name }}" - }, - "oauthConnectionName": { - "value": "$\{{OAUTH_CONNECTION_NAME}}" - }, - "tenantId": { - "value": "$\{{AAD_APP_TENANT_ID}}" - } - } -} diff --git a/packages/cli/configs/atk/oauth/typescript/infra/azure.parameters.local.json.hbs b/packages/cli/configs/atk/oauth/typescript/infra/azure.parameters.local.json.hbs deleted file mode 100644 index eae4d85c0..000000000 --- a/packages/cli/configs/atk/oauth/typescript/infra/azure.parameters.local.json.hbs +++ /dev/null @@ -1,27 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "resourceBaseName": { - "value": "bot-$\{{RESOURCE_SUFFIX}}-$\{{TEAMSFX_ENV}}" - }, - "botAadAppClientId": { - "value": "$\{{BOT_ID}}" - }, - "botAadAppClientSecret": { - "value": "$\{{SECRET_BOT_PASSWORD}}" - }, - "botDisplayName": { - "value": "{{ toPascalCase name }}-$\{{TEAMSFX_ENV}}" - }, - "botAppDomain": { - "value": "$\{{BOT_DOMAIN}}" - }, - "oauthConnectionName": { - "value": "$\{{OAUTH_CONNECTION_NAME}}" - }, - "tenantId": { - "value": "$\{{AAD_APP_TENANT_ID}}" - } - } -} diff --git a/packages/cli/configs/atk/oauth/typescript/infra/botRegistration/azurebot.bicep b/packages/cli/configs/atk/oauth/typescript/infra/botRegistration/azurebot.bicep deleted file mode 100644 index 4e3258df3..000000000 --- a/packages/cli/configs/atk/oauth/typescript/infra/botRegistration/azurebot.bicep +++ /dev/null @@ -1,67 +0,0 @@ -@maxLength(20) -@minLength(4) -@description('Used to generate names for all resources in this file') -param resourceBaseName string - -@maxLength(42) -param botDisplayName string - -param botServiceName string = resourceBaseName -param botServiceSku string = 'F0' -param botAadAppClientId string -param botAppDomain string -param oauthConnectionName string -param tenantId string - -@secure() -param botAddAppClientSecret string - -// Register your web service as a bot with the Bot Framework -resource botService 'Microsoft.BotService/botServices@2021-03-01' = { - kind: 'azurebot' - location: 'global' - name: botServiceName - properties: { - displayName: botDisplayName - endpoint: 'https://${botAppDomain}/api/messages' - msaAppId: botAadAppClientId - msaAppType: 'SingleTenant' - msaAppTenantId: tenantId - } - sku: { - name: botServiceSku - } -} - -// Connect the bot service to Microsoft Teams -resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = { - parent: botService - location: 'global' - name: 'MsTeamsChannel' - properties: { - channelName: 'MsTeamsChannel' - } -} - -resource botServicesMicrosoftGraphConnection 'Microsoft.BotService/botServices/connections@2022-09-15' = { - parent: botService - name: oauthConnectionName - location: 'global' - properties: { - serviceProviderDisplayName: 'Azure Active Directory v2' - serviceProviderId: '30dd229c-58e3-4a48-bdfd-91ec48eb906c' - clientId: botAadAppClientId - clientSecret: botAddAppClientSecret - scopes: 'User.ReadBasic.All' - parameters: [ - { - key: 'tenantID' - value: 'common' - } - { - key: 'tokenExchangeUrl' - value: 'api://botid-${botAadAppClientId}' - } - ] - } -} diff --git a/packages/cli/configs/atk/oauth/typescript/teamsapp.local.yml.hbs b/packages/cli/configs/atk/oauth/typescript/teamsapp.local.yml.hbs deleted file mode 100644 index fbbedcd64..000000000 --- a/packages/cli/configs/atk/oauth/typescript/teamsapp.local.yml.hbs +++ /dev/null @@ -1,117 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/1.0.0/yaml.schema.json -# -# The teamsapp.local.yml composes automation tasks for M365 Agents Toolkit when running locally. -# This file is used when running Start Debugging (F5) from Visual Studio Code or with the TeamsFx CLI commands. -# i.e. `teamsfx provision --env local` or `teamsfx deploy --env local`. -# -# You can customize this file. Visit https://aka.ms/teamsfx-v5.0-guide for more info about M365 Agents Toolkit project files. -version: 1.0.0 - -environmentFolderPath: ./env - -# Defines what the `provision` lifecycle step does with M365 Agents Toolkit. -# Runs first during Start Debugging (F5) or run manually using `teamsfx provision --env local`. -provision: - # Automates the creation of a Teams app registration and saves the App ID to an environment file. - - uses: teamsApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID - - # Creates a new Microsoft Entra app to authenticate users if - # the environment variable that stores clientId is empty - - uses: aadApp/create - with: - # Note: when you run aadApp/update, the Microsoft Entra app name will be updated - # based on the definition in manifest. If you don't want to change the - # name, make sure the name in Microsoft Entra manifest is the same with the name - # defined here. - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - # If the value is false, the driver will not generate client secret for you - generateClientSecret: true - # organization's Microsoft Entra tenant (for example, single tenant). - signInAudience: AzureADMultipleOrgs - # Write the information of created resources into environment file for the - # specified environment variable(s). - writeToEnvironmentFile: - clientId: BOT_ID - # Environment variable that starts with `SECRET_` will be stored to the - # .env.{envName}.user environment file - clientSecret: SECRET_BOT_PASSWORD - objectId: AAD_APP_OBJECT_ID - tenantId: AAD_APP_TENANT_ID - - # Apply the Microsoft Entra manifest to an existing Microsoft Entra app. Will use the object id in - # manifest file to determine which Microsoft Entra app to update. - - uses: aadApp/update - with: - # Relative path to this file. Environment variables in manifest will - # be replaced before apply to Microsoft Entra app - manifestPath: ./aad.manifest.json - outputFilePath: ./build/aad.manifest.$\{{TEAMSFX_ENV}}.json - - - uses: arm/deploy # Deploy given ARM templates parallelly. - env: - # an arbitrary name for the connection - OAUTH_CONNECTION_NAME: graph - with: - # AZURE_SUBSCRIPTION_ID is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select a subscription. - # Referencing other environment variables with empty values - # will skip the subscription selection prompt. - subscriptionId: $\{{AZURE_SUBSCRIPTION_ID}} - # AZURE_RESOURCE_GROUP_NAME is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select or create one - # resource group. - # Referencing other environment variables with empty values - # will skip the resource group selection prompt. - resourceGroupName: $\{{AZURE_RESOURCE_GROUP_NAME}} - templates: - - path: ./infra/azure.local.bicep # Relative path to this file - # Relative path to this yaml file. - # Placeholders will be replaced with corresponding environment - # variable before ARM deployment. - parameters: ./infra/azure.parameters.local.json - # Required when deploying ARM template - deploymentName: Create-resources-for-{{ toKebabCase name }}-$\{{TEAMSFX_ENV}} - bicepCliVersion: v0.9.1 - - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates the creation of a Teams app package (.zip). - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - # Relative path to this file. This is the path for built zip file. - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - -# Defines what the `deploy` lifecycle step does with M365 Agents Toolkit. -# Runs after `provision` during Start Debugging (F5) or run manually using `teamsfx deploy --env local`. -deploy: - # Install any dependencies and build the web app using NPM - - uses: cli/runNpmCommand - name: install dependencies - with: - args: install --no-audit --workspaces=false - # Provides the M365 Agents Toolkit .env file values to the apps runtime so they can be accessed with `process.env`. - - uses: file/createOrUpdateEnvironmentFile - with: - target: ./.env - envs: - PORT: 3978 - CLIENT_ID: $\{{BOT_ID}} - CLIENT_SECRET: $\{{SECRET_BOT_PASSWORD}} - TENANT_ID: $\{{AAD_APP_TENANT_ID}} - # an arbitrary name for the connection - OAUTH_CONNECTION_NAME: graph diff --git a/packages/cli/configs/atk/oauth/typescript/teamsapp.testtool.yml b/packages/cli/configs/atk/oauth/typescript/teamsapp.testtool.yml deleted file mode 100644 index e9dab22c2..000000000 --- a/packages/cli/configs/atk/oauth/typescript/teamsapp.testtool.yml +++ /dev/null @@ -1,26 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/v1.5/yaml.schema.json -# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file -# Visit https://aka.ms/teamsfx-actions for details on actions -version: v1.5 - -deploy: - # Install development tool(s) - - uses: devTool/install - with: - testTool: - version: ~0.2.1 - symlinkDir: ./devTools/teamsapptester - - # Run npm command - - uses: cli/runNpmCommand - with: - args: install --no-audit --workspaces=false - - # Generate runtime environment variables - - uses: file/createOrUpdateEnvironmentFile - with: - target: ./.env - envs: - NODE_ENV: local - PORT: 3978 - TEAMSFX_NOTIFICATION_STORE_FILENAME: ${{TEAMSFX_NOTIFICATION_STORE_FILENAME}} diff --git a/packages/cli/configs/atk/oauth/typescript/teamsapp.yml.hbs b/packages/cli/configs/atk/oauth/typescript/teamsapp.yml.hbs deleted file mode 100644 index 4227094c3..000000000 --- a/packages/cli/configs/atk/oauth/typescript/teamsapp.yml.hbs +++ /dev/null @@ -1,152 +0,0 @@ -# yaml-language-server: $schema=https://aka.ms/teams-toolkit/1.0.0/yaml.schema.json -# -# The teamsapp.yml composes automation tasks for M365 Agents Toolkit when running other environment configurations. -# This file is used when selecting the Provision, Deploy, or Publish menu items in the M365 Agents Toolkit for Visual Studio Code window -# or with the TeamsFx CLI commands. -# i.e. `teamsfx provision --env {environment name}` or `teamsfx deploy --env {environment name}`. -# -# You can customize this file. Visit https://aka.ms/teamsfx-v5.0-guide for more info about M365 Agents Toolkit project files. -version: 1.0.0 - -environmentFolderPath: ./env - -# Defines what the `provision` lifecycle step does with M365 Agents Toolkit. -# Runs with the Provision menu or CLI using `teamsfx provision --env {environment name}`. -provision: - # Automates the creation of a Teams app registration and saves the App ID to an environment file. - - uses: teamsApp/create - with: - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - writeToEnvironmentFile: - teamsAppId: TEAMS_APP_ID - - # Creates a new Microsoft Entra app to authenticate users if - # the environment variable that stores clientId is empty - - uses: aadApp/create - with: - # Note: when you run aadApp/update, the Microsoft Entra app name will be updated - # based on the definition in manifest. If you don't want to change the - # name, make sure the name in Microsoft Entra manifest is the same with the name - # defined here. - name: {{ toPascalCase name }}$\{{APP_NAME_SUFFIX}} - # If the value is false, the driver will not generate client secret for you - generateClientSecret: true - # organization's Microsoft Entra tenant (for example, single tenant). - signInAudience: AzureADMultipleOrgs - # Write the information of created resources into environment file for the - # specified environment variable(s). - writeToEnvironmentFile: - clientId: BOT_ID - # Environment variable that starts with `SECRET_` will be stored to the - # .env.{envName}.user environment file - clientSecret: SECRET_BOT_PASSWORD - objectId: AAD_APP_OBJECT_ID - tenantId: AAD_APP_TENANT_ID - - # Apply the Microsoft Entra manifest to an existing Microsoft Entra app. Will use the object id in - # manifest file to determine which Microsoft Entra app to update. - - uses: aadApp/update - with: - # Relative path to this file. Environment variables in manifest will - # be replaced before apply to Microsoft Entra app - manifestPath: ./aad.manifest.json - outputFilePath: ./build/aad.manifest.$\{{TEAMSFX_ENV}}.json - - - uses: arm/deploy # Deploy given ARM templates parallelly. - env: - # an arbitrary name for the connection - OAUTH_CONNECTION_NAME: graph - with: - # AZURE_SUBSCRIPTION_ID is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select a subscription. - # Referencing other environment variables with empty values - # will skip the subscription selection prompt. - subscriptionId: $\{{AZURE_SUBSCRIPTION_ID}} - # AZURE_RESOURCE_GROUP_NAME is a built-in environment variable, - # if its value is empty, TeamsFx will prompt you to select or create one - # resource group. - # Referencing other environment variables with empty values - # will skip the resource group selection prompt. - resourceGroupName: $\{{AZURE_RESOURCE_GROUP_NAME}} - templates: - - path: ./infra/azure.bicep # Relative path to this file - # Relative path to this yaml file. - # Placeholders will be replaced with corresponding environment - # variable before ARM deployment. - parameters: ./infra/azure.parameters.json - # Required when deploying ARM template - deploymentName: Create-resources-for-{{ toKebabCase name }}-$\{{TEAMSFX_ENV}} - bicepCliVersion: v0.9.1 - - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates creating a final app package (.zip) by replacing any variables in the manifest.json file for the current environment. - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Optional: Automates an app package check for errors that would prevent the app from being published and reports any problems. - - uses: teamsApp/validateAppPackage - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - -# Defines what the `deploy` lifecycle step does with M365 Agents Toolkit. -# Runs with the Deploy menu or CLI using `teamsfx deploy --env {environment name}`. -deploy: - # Install any dependencies and build the web app using NPM - - uses: cli/runNpmCommand - name: install dependencies - with: - args: install - - - uses: cli/runNpmCommand - name: build app - with: - args: run build --if-present - - # Deploy to an Azure App Service using the zip file created in the provision step. - - uses: azureAppService/zipDeploy - with: - artifactFolder: . - ignoreFile: .webappignore - # This example uses the env var thats generated by the arm/deploy action. - # You can replace it with an existing Azure Resource ID or other - # custom environment variable. - resourceId: $\{{BOT_AZURE_APP_SERVICE_RESOURCE_ID}} - -# Defines what the `publish` lifecycle step does with M365 Agents Toolkit. -# Runs with the Deploy menu or CLI using `teamsfx publish --env {environment name}`. -publish: - # Optional: Automates schema and error checking of the Teams app manifest and outputs the results in the console. - - uses: teamsApp/validateManifest - with: - manifestPath: ./appPackage/manifest.json - - # Automates creating a final app package (.zip) by replacing any variables in the manifest.json file for the current environment. - - uses: teamsApp/zipAppPackage - with: - manifestPath: ./appPackage/manifest.json - outputZipPath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - outputJsonPath: ./appPackage/build/manifest.$\{{TEAMSFX_ENV}}.json - - # Optional: Automates an app package check for errors that would prevent the app from being published and reports any problems. - - uses: teamsApp/validateAppPackage - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip - - # Automates updating the Teams app manifest in Teams Developer Portal using the App ID from the manifest file. - # This action ensures that any manifest changes are reflected when launching the app again in Teams. - - uses: teamsApp/update - with: - appPackagePath: ./appPackage/build/appPackage.$\{{TEAMSFX_ENV}}.zip diff --git a/packages/cli/configs/atk/oauth/typescript/web.config b/packages/cli/configs/atk/oauth/typescript/web.config deleted file mode 100644 index 806357751..000000000 --- a/packages/cli/configs/atk/oauth/typescript/web.config +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/cli/eslint.config.js b/packages/cli/eslint.config.js deleted file mode 100644 index 5ccf8112f..000000000 --- a/packages/cli/eslint.config.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('@microsoft/teams.config/eslint.config').default; diff --git a/packages/cli/jest.config.js b/packages/cli/jest.config.js deleted file mode 100644 index 0decac4af..000000000 --- a/packages/cli/jest.config.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('@microsoft/teams.config/jest.config'); diff --git a/packages/cli/package.json b/packages/cli/package.json deleted file mode 100644 index 05628ab76..000000000 --- a/packages/cli/package.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "@microsoft/teams.cli", - "version": "0.0.0", - "license": "MIT", - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", - "homepage": "https://github.com/microsoft/teams.ts", - "bugs": "https://github.com/microsoft/teams.ts/issues", - "bin": { - "teams": "./dist/index.js" - }, - "files": [ - "dist", - "templates", - "configs", - "README.md" - ], - "engines": { - "node": ">=20" - }, - "repository": { - "type": "git", - "url": "https://github.com/microsoft/teams.ts.git", - "directory": "packages/cli" - }, - "keywords": [ - "microsoft", - "teams", - "msteams", - "copilot", - "ai", - "cli" - ], - "scripts": { - "clean": "npx rimraf ./dist", - "lint": "npx eslint", - "lint:fix": "npx eslint --fix", - "build": "npx tsup", - "test": "npx jest" - }, - "dependencies": { - "@microsoft/teams.common": "*", - "change-case": "^5.4.4", - "handlebars": "^4.7.9", - "yaml": "^2.8.3", - "yargs": "^17.7.2", - "zod": "^3.24.2" - }, - "devDependencies": { - "@microsoft/teams.config": "*", - "@types/jest": "^29.5.12", - "@types/node": "^22.10.7", - "@types/yargs": "^17.0.33", - "jest": "^29.7.0", - "rimraf": "^6.0.1", - "ts-jest": "^29.2.5", - "tsup": "^8.4.0", - "typescript": "^5.4.5" - } -} diff --git a/packages/cli/src/commands/config/add.ts b/packages/cli/src/commands/config/add.ts deleted file mode 100644 index f704ba95a..000000000 --- a/packages/cli/src/commands/config/add.ts +++ /dev/null @@ -1,61 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import url from 'node:url'; - -import { CommandModule } from 'yargs'; - -import { String } from '@microsoft/teams.common'; - -import { IContext } from '../../context'; -import { Project } from '../../project'; - -type Args = { - name: string; -}; - -export function Add(_: IContext): CommandModule<{}, Args> { - const configsPath = path.resolve(url.fileURLToPath(import.meta.url), '../..', 'configs'); - - return { - command: 'add ', - describe: 'add a configuration', - builder: (b) => { - return b.positional('name', { - type: 'string', - demandOption: true, - choices: fs - .readdirSync(configsPath) - .map((name) => { - // If no language is detected, default to configs available for typescript - const language = Project.detectLanguage() ?? 'typescript'; - const atkPath = path.join(configsPath, name); - - return fs.readdirSync(atkPath) - .filter((type) => fs.existsSync(path.join(atkPath, type, language))) - .map((type) => `${name}.${type}`); - }) - .flat(), - }).check(() => { - if (!Project.detectLanguage()) { - throw new Error('Are you in the right folder? Expected a package.json (Typescript) or .sln (C#) file or pyproject.toml (Python).'); - } - - return true; - }); - }, - handler: async ({ name }) => { - const [type, subType] = name.split('.'); - const builder = Project.load(); - - if (type === 'atk') { - builder.addAgentsToolkit(subType); - } - - const project = builder.build(); - await project.up(); - console.log( - new String().bold(new String().green(`✅ config "${name}" successfully added`)).toString() - ); - }, - }; -} diff --git a/packages/cli/src/commands/config/index.ts b/packages/cli/src/commands/config/index.ts deleted file mode 100644 index 83666432b..000000000 --- a/packages/cli/src/commands/config/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { CommandModule } from 'yargs'; - -import { IContext } from '../../context'; - -import { Add } from './add'; -import { Remove } from './remove'; - -export function Config(context: IContext): CommandModule<{}, {}> { - return { - command: 'config', - aliases: 'c', - describe: 'configure a project', - builder: (b) => { - return b.command(Add(context)).command(Remove(context)).demandCommand(1); - }, - handler: () => {}, - }; -} diff --git a/packages/cli/src/commands/config/remove.ts b/packages/cli/src/commands/config/remove.ts deleted file mode 100644 index 7207eb68e..000000000 --- a/packages/cli/src/commands/config/remove.ts +++ /dev/null @@ -1,55 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import url from 'node:url'; - -import { CommandModule } from 'yargs'; - -import { String } from '@microsoft/teams.common'; - -import { IContext } from '../../context'; -import { Project } from '../../project'; - -type Args = { - name: string; -}; - -export function Remove(_: IContext): CommandModule<{}, Args> { - const configsPath = path.resolve(url.fileURLToPath(import.meta.url), '../..', 'configs'); - - return { - command: 'remove ', - describe: 'remove a configuration', - builder: (b) => { - return b.positional('name', { - type: 'string', - demandOption: true, - choices: fs - .readdirSync(configsPath) - .map((name) => { - // If no language is detected, default to configs available for typescript - const language = Project.detectLanguage() ?? 'typescript'; - const atkPath = path.join(configsPath, name); - - return fs.readdirSync(atkPath) - .filter((type) => fs.existsSync(path.join(atkPath, type, language))) - .map((type) => `${name}.${type}`); - }) - .flat(), - }); - }, - handler: async ({ name }) => { - const [type, subType] = name.split('.'); - const builder = Project.load(); - - if (type === 'atk') { - builder.addAgentsToolkit(subType); - } - - const project = builder.build(); - await project.down(); - console.log( - new String().bold(new String().green(`✅ config "${name}" successfully removed`)).toString() - ); - }, - }; -} diff --git a/packages/cli/src/commands/env/del.ts b/packages/cli/src/commands/env/del.ts deleted file mode 100644 index 70a819a43..000000000 --- a/packages/cli/src/commands/env/del.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { CommandModule } from 'yargs'; - -import { IContext } from '../../context'; - -type Args = { - key: string; -}; - -export function Del({ envs }: IContext): CommandModule<{}, Args> { - return { - command: 'del ', - describe: 'delete an environment key', - builder: (b) => { - return b.positional('key', { - type: 'string', - demandOption: true, - }); - }, - handler: ({ key }) => { - envs.del(key); - - if (envs.active.list().length === 0 && envs.active.name !== 'dev') { - const toDelete = envs.active.name; - envs.select('dev'); - envs.remove(toDelete); - return; - } - }, - }; -} diff --git a/packages/cli/src/commands/env/export.ts b/packages/cli/src/commands/env/export.ts deleted file mode 100644 index db097865f..000000000 --- a/packages/cli/src/commands/env/export.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { CommandModule } from 'yargs'; - -import { IContext } from '../../context'; -import { Project } from '../../project'; - -type Args = { - name?: string; -}; - -export function Export({ envs }: IContext): CommandModule<{}, Args> { - return { - command: 'export [name]', - describe: 'export an environment to an environment file in your project', - builder: (b) => { - return b.positional('name', { - type: 'string', - describe: 'the environment name to export (defaults to active)', - choices: envs.list().map(e => e.name) - }); - }, - handler: async ({ name = envs.active.name }) => { - const builder = Project.load(); - const env = envs.getByName(name); - - if (!env) { - console.error('environment not found'); - return; - } - - for (const { key, value } of env.list()) { - builder.addEnv(key, value); - } - - const project = builder.build(); - await project.up(); - }, - }; -} diff --git a/packages/cli/src/commands/env/index.ts b/packages/cli/src/commands/env/index.ts deleted file mode 100644 index 452d68a5e..000000000 --- a/packages/cli/src/commands/env/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { CommandModule } from 'yargs'; - -import { IContext } from '../../context'; - -import { Del } from './del'; -import { Export } from './export'; -import { List } from './list'; -import { Select } from './select'; -import { Set } from './set'; - -export function Env(context: IContext): CommandModule<{}, {}> { - return { - command: 'env', - aliases: 'e', - describe: 'manage environments', - builder: (b) => { - return b - .command(List(context)) - .command(Select(context)) - .command(Set(context)) - .command(Del(context)) - .command(Export(context)) - .demandCommand(1); - }, - handler: () => {}, - }; -} diff --git a/packages/cli/src/commands/env/list.ts b/packages/cli/src/commands/env/list.ts deleted file mode 100644 index c97614d29..000000000 --- a/packages/cli/src/commands/env/list.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { CommandModule } from 'yargs'; - -import { IContext } from '../../context'; - -type Args = { - name?: string; -}; - -export function List({ envs }: IContext): CommandModule<{}, Args> { - return { - command: 'list [name]', - aliases: 'ls', - describe: 'list environments', - builder: (b) => { - return b.positional('name', { - type: 'string', - describe: 'env name, if provided variables will be listed', - choices: envs.list().map(e => e.name) - }); - }, - handler: ({ name }) => { - if (name) { - const env = envs.getByName(name); - - if (!env) { - console.error('environment not found'); - return; - } - - for (const { key, value } of env.list()) { - console.log(`${key}: ${value}`); - } - - return; - } - - console.log(`active: ${envs.active.name}\n`); - - for (const env of envs.list()) { - console.log(`${env.name}: ${env.list().length}`); - } - }, - }; -} diff --git a/packages/cli/src/commands/env/select.ts b/packages/cli/src/commands/env/select.ts deleted file mode 100644 index e93669fd9..000000000 --- a/packages/cli/src/commands/env/select.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { CommandModule } from 'yargs'; - -import { IContext } from '../../context'; - -type Args = { - name: string; -}; - -export function Select({ envs }: IContext): CommandModule<{}, Args> { - return { - command: 'select ', - describe: 'select an environment', - builder: (b) => { - return b.positional('name', { - type: 'string', - demandOption: true, - coerce: (name: string) => { - return name - .trim() - .toLowerCase() - .replace(/\s+/g, '-') - .replace(/^[._]/, '') - .replace(/[^a-z\d\-~]+/g, '-'); - }, - }); - }, - handler: ({ name }) => { - envs.select(name); - }, - }; -} diff --git a/packages/cli/src/commands/env/set.ts b/packages/cli/src/commands/env/set.ts deleted file mode 100644 index 747074d03..000000000 --- a/packages/cli/src/commands/env/set.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { CommandModule } from 'yargs'; - -import { IContext } from '../../context'; - -type Args = { - key: string; - value: string; -}; - -export function Set({ envs }: IContext): CommandModule<{}, Args> { - return { - command: 'set [value]', - describe: 'set an environment key', - builder: (b) => { - return b - .positional('key', { - type: 'string', - demandOption: true, - }) - .positional('value', { - type: 'string', - demandOption: true, - }); - }, - handler: ({ key, value }) => { - envs.set(key, value); - }, - }; -} diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts deleted file mode 100644 index 2e7072653..000000000 --- a/packages/cli/src/commands/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './new'; -export * from './config'; -export * from './env'; -export * from './set-lang'; diff --git a/packages/cli/src/commands/new/csharp.ts b/packages/cli/src/commands/new/csharp.ts deleted file mode 100644 index 43720b2e5..000000000 --- a/packages/cli/src/commands/new/csharp.ts +++ /dev/null @@ -1,136 +0,0 @@ -import cp from 'node:child_process'; -import fs from 'node:fs'; -import path from 'node:path'; -import url from 'node:url'; - -import { CommandModule } from 'yargs'; -import { z } from 'zod'; - -import { IContext } from '../../context'; -import { Project } from '../../project'; -import { Settings } from '../../settings'; - -const ArgsSchema = z.object({ - name: z.string(), - template: z.string(), - atk: z.string().optional(), - start: z.boolean().optional(), - clientId: z.string().optional(), - clientSecret: z.string().optional(), -}); - -export function CSharp(_: IContext): CommandModule<{}, z.infer> { - const isCSharp = Settings.load().language == 'csharp'; - const atkPath = path.resolve(url.fileURLToPath(import.meta.url), '../..', 'configs', 'atk'); - - return { - command: ['csharp ', ...(isCSharp ? ['$0 '] : [])], - aliases: ['cs'], - describe: 'create a new csharp app project', - builder: async (b) => { - const changeCase = await import('change-case'); - - return b - .positional('name', { - alias: 'n', - type: 'string', - describe: 'the apps name', - demandOption: true, - coerce: (name: string) => { - return changeCase.pascalCase(name.trim(), { - delimiter: '.', - }); - }, - }) - .option('template', { - alias: 't', - type: 'string', - describe: 'the app template to use', - default: 'echo', - choices: fs.readdirSync( - path.resolve(url.fileURLToPath(import.meta.url), '../..', 'templates', 'csharp') - ), - }) - .option('start', { - alias: 's', - type: 'boolean', - describe: 'start the project', - default: false, - }) - .option('toolkit', { - alias: 'atk', - type: 'string', - describe: 'include M365 Agents Toolkit configuration', - choices: fs.readdirSync(atkPath) - .filter((type) => fs.existsSync(path.join(atkPath, type, 'csharp'))) - .flat() - }) - .option('client-id', { - type: 'string', - describe: 'the apps client id (app id)', - default: process.env.CLIENT_ID, - }) - .option('client-secret', { - type: 'string', - describe: 'the apps client secret', - default: process.env.CLIENT_SECRET, - }) - .check(({ name }) => { - if (fs.existsSync(path.join(process.cwd(), name))) { - throw new Error(`"${name}" already exists!`); - } - - return true; - }); - }, - handler: async ({ name, template, start, atk, clientId, clientSecret }) => { - const projectDir = path.join(process.cwd(), name); - const builder = Project.builder() - .withPath(projectDir) - .withName(name) - .withLanguage('csharp') - .addTemplate(template); - - if (atk) { - builder.addAgentsToolkit(atk); - } - - const appSettingsPath = `${name}/appsettings.Development.json`; - - if (clientId) { - builder.addEnv('Teams.ClientId', clientId, appSettingsPath); - } - - if (clientSecret) { - builder.addEnv('Teams.ClientSecret', clientSecret, appSettingsPath); - } - - if (process.env.OPENAI_API_KEY) { - builder.addEnv('OPENAI_API_KEY', process.env.OPENAI_API_KEY, appSettingsPath); - } - - if (process.env.AZURE_OPENAI_API_KEY) { - builder.addEnv('OPENAI_API_KEY', process.env.AZURE_OPENAI_API_KEY, appSettingsPath); - } - - if (process.env.AZURE_OPENAI_ENDPOINT) { - builder.addEnv('OPENAI_ENDPOINT', process.env.AZURE_OPENAI_ENDPOINT, appSettingsPath); - } - - const project = builder.build(); - await project.up(); - console.log(`✅ App "${name}" created successfully at ${projectDir}`); - - if (start) { - console.log(`cd ${name}/${name} && dotnet run`); - cp.spawnSync(`cd ${name}/${name} && dotnet run`, { - stdio: 'inherit', - shell: true, - }); - } else { - console.log('Next steps to start the app:'); - console.log(`cd ${name}/${name} && dotnet run`); - } - }, - }; -} diff --git a/packages/cli/src/commands/new/index.ts b/packages/cli/src/commands/new/index.ts deleted file mode 100644 index 5817a25b0..000000000 --- a/packages/cli/src/commands/new/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { CommandModule } from 'yargs'; - -import { IContext } from '../../context'; - -import { Settings } from '../../settings'; - -import { CSharp } from './csharp'; -import { Python } from './python'; -import { Typescript } from './typescript'; - -export function New(context: IContext): CommandModule<{}, {}> { - const language = Settings.load().language ?? ''; - - return { - command: 'new', - aliases: 'n', - describe: `create a new app project${language ? ` in ${language}` : ''}. You can update language with the "set-lang" command.`, - builder: (b) => { - const builder = b - .command(Typescript(context)) - .command(CSharp(context)) - .command(Python(context)); - return builder - .strict() - .demandCommand(1, 'You must specify a project type'); - }, - handler: () => { }, - }; -} diff --git a/packages/cli/src/commands/new/python.ts b/packages/cli/src/commands/new/python.ts deleted file mode 100644 index 92161f608..000000000 --- a/packages/cli/src/commands/new/python.ts +++ /dev/null @@ -1,140 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import url from 'node:url'; - -import { CommandModule } from 'yargs'; -import { z } from 'zod'; - -import { String } from '@microsoft/teams.common'; - -import { IContext } from '../../context'; -import { Project } from '../../project'; -import { Settings } from '../../settings'; - -const ArgsSchema = z.object({ - name: z.string(), - template: z.string(), - atk: z.string().optional(), - clientId: z.string().optional(), - clientSecret: z.string().optional(), -}); - -/** - * Prints next steps to start the app. - */ -function printNextSteps(name: string): void { - console.log(new String().bold('Next steps to start the app:').toString()); - console.log(new String().cyan(` cd ${name}`).toString()); - console.log(new String().cyan(' python -m venv .venv').toString()); - console.log(new String().gray(' # activate your venv, then:').toString()); - console.log(new String().cyan(' pip install -e .').toString()); - console.log(new String().cyan(' python src/main.py').toString()); -} - -export function Python(_: IContext): CommandModule<{}, z.infer> { - const isPython = Settings.load().language == 'python'; - const atkPath = path.resolve(url.fileURLToPath(import.meta.url), '../..', 'configs', 'atk'); - - return { - command: ['python ', ...(isPython ? ['$0 '] : [])], - aliases: 'py', - describe: 'create a new python app project', - builder: (b) => { - return b - .positional('name', { - alias: 'n', - type: 'string', - describe: 'the apps name', - demandOption: true, - coerce: (name: string) => { - return name // normalize: trim, lowercase, replace spaces and invalid chars for package naming - .trim() - .toLowerCase() - .replace(/\s+/g, '-') - .replace(/^[._]/, '') - .replace(/[^a-z\d\-~]+/g, '-'); - }, - }) - .option('template', { - alias: 't', - type: 'string', - describe: 'the app template to use', - default: 'echo', - choices: fs.readdirSync( - path.resolve(url.fileURLToPath(import.meta.url), '../..', 'templates', 'python') - ), - }) - .option('toolkit', { - alias: 'atk', - type: 'string', - describe: 'include M365 Agents Toolkit configuration', - choices: fs.readdirSync(atkPath) - .filter((type) => fs.existsSync(path.join(atkPath, type, 'python'))) - .flat() - }) - .option('client-id', { - type: 'string', - describe: 'the apps client id (app id)', - default: process.env.CLIENT_ID, - }) - .option('client-secret', { - type: 'string', - describe: 'the apps client secret', - default: process.env.CLIENT_SECRET, - }) - .check((args: z.infer) => { - const res = ArgsSchema.safeParse(args); - - if (res.error) { - throw new Error( - res.error.errors.map((err) => `${err.path.join('.')} => ${err.message}`).join('\n') - ); - } - - return true; - }) - .check(({ name }) => { - if (fs.existsSync(path.join(process.cwd(), name))) { - throw new Error(`"${name}" already exists!`); - } - - if (!/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(name)) { - throw new Error(`"${name}" is not a valid package name`); - } - - return true; - }); - }, - handler: async ({ name, template, atk, clientId, clientSecret }) => { - const projectDir = path.join(process.cwd(), name); - const builder = Project.builder() - .withPath(projectDir) - .withName(name) - .withLanguage('python') - .addTemplate(template); - - if (atk) { - builder.addAgentsToolkit(atk); - } - - if (clientId) { - builder.addEnv('CLIENT_ID', clientId); - } - - if (clientSecret) { - builder.addEnv('CLIENT_SECRET', clientSecret); - } - - const project = builder.build(); - await project.up(); - - console.log( - new String() - .bold(new String().green(`✅ App "${name}" created successfully at ${projectDir}`)) - .toString() - ); - - printNextSteps(name); - }, - }; -} diff --git a/packages/cli/src/commands/new/typescript.ts b/packages/cli/src/commands/new/typescript.ts deleted file mode 100644 index f9955a048..000000000 --- a/packages/cli/src/commands/new/typescript.ts +++ /dev/null @@ -1,156 +0,0 @@ -import cp from 'node:child_process'; -import fs from 'node:fs'; -import path from 'node:path'; -import url from 'node:url'; - -import { CommandModule } from 'yargs'; -import { z } from 'zod'; - -import { String } from '@microsoft/teams.common'; - -import { IContext } from '../../context'; -import { Project } from '../../project'; -import { Settings } from '../../settings'; - -const ArgsSchema = z.object({ - name: z.string(), - template: z.string(), - atk: z.string().optional(), - start: z.boolean().optional(), - clientId: z.string().optional(), - clientSecret: z.string().optional(), -}); - -export function Typescript(_: IContext): CommandModule<{}, z.infer> { - const isTypescript = Settings.load().language == 'typescript'; - const atkPath = path.resolve(url.fileURLToPath(import.meta.url), '../..', 'configs', 'atk'); - - return { - command: ['typescript ', ...(isTypescript ? ['$0 '] : [])], - aliases: 'ts', - describe: 'create a new typescript app project', - builder: (b) => { - return b - .positional('name', { - alias: 'n', - type: 'string', - describe: 'the apps name', - demandOption: true, - coerce: (name: string) => { - return name - .trim() - .toLowerCase() - .replace(/\s+/g, '-') - .replace(/^[._]/, '') - .replace(/[^a-z\d\-~]+/g, '-'); - }, - }) - .option('template', { - alias: 't', - type: 'string', - describe: 'the app template to use', - default: 'echo', - choices: fs.readdirSync( - path.resolve(url.fileURLToPath(import.meta.url), '../..', 'templates', 'typescript') - ), - }) - .option('start', { - alias: 's', - type: 'boolean', - describe: 'start the project', - default: false, - }) - .option('toolkit', { - alias: 'atk', - type: 'string', - describe: 'include M365 Agents Toolkit configuration', - choices: fs.readdirSync(atkPath) - .filter((type) => fs.existsSync(path.join(atkPath, type, 'typescript'))) - .flat() - }) - .option('client-id', { - type: 'string', - describe: 'the apps client id (app id)', - default: process.env.CLIENT_ID, - }) - .option('client-secret', { - type: 'string', - describe: 'the apps client secret', - default: process.env.CLIENT_SECRET, - }) - .check((args: z.infer) => { - const res = ArgsSchema.safeParse(args); - - if (res.error) { - throw new Error( - res.error.errors.map((err) => `${err.path.join('.')} => ${err.message}`).join('\n') - ); - } - - return true; - }) - .check(({ name }) => { - if (fs.existsSync(path.join(process.cwd(), name))) { - throw new Error(`"${name}" already exists!`); - } - - if (!/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(name)) { - throw new Error(`"${name}" is not a valid package name`); - } - - return true; - }); - }, - handler: async ({ name, template, atk, start, clientId, clientSecret }) => { - const projectDir = path.join(process.cwd(), name); - const builder = Project.builder() - .withPath(projectDir) - .withName(name) - .withLanguage('typescript') - .addTemplate(template); - - if (atk) { - builder.addAgentsToolkit(atk); - } - - if (clientId) { - builder.addEnv('CLIENT_ID', clientId); - } - - if (clientSecret) { - builder.addEnv('CLIENT_SECRET', clientSecret); - } - - if (process.env.OPENAI_API_KEY) { - builder.addEnv('OPENAI_API_KEY', process.env.OPENAI_API_KEY); - } - - if (process.env.AZURE_OPENAI_API_KEY) { - builder.addEnv('AZURE_OPENAI_API_KEY', process.env.AZURE_OPENAI_API_KEY); - } - - if (process.env.AZURE_OPENAI_ENDPOINT) { - builder.addEnv('AZURE_OPENAI_ENDPOINT', process.env.AZURE_OPENAI_ENDPOINT); - } - - const project = builder.build(); - await project.up(); - console.log( - new String() - .bold(new String().green(`✅ App "${name}" created successfully at ${projectDir}`)) - .toString() - ); - - if (start) { - console.log(`cd ${name} && npm install && npm run dev`); - cp.spawnSync(`cd ${name} && npm install && npm run dev`, { - stdio: 'inherit', - shell: true, - }); - } else { - console.log('Next steps to start the app:'); - console.log(`cd ${name} && npm install && npm run dev`); - } - }, - }; -} diff --git a/packages/cli/src/commands/set-lang/index.ts b/packages/cli/src/commands/set-lang/index.ts deleted file mode 100644 index df19a7531..000000000 --- a/packages/cli/src/commands/set-lang/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { CommandModule } from 'yargs'; - -import { z } from 'zod'; - -import { IContext } from '../../context'; -import { Settings } from '../../settings'; - -const ArgsSchema = z.object({ - language: z.string(), -}); - -export function SetLang(_: IContext): CommandModule<{}, z.infer> { - const language = Settings.load().language ?? ''; - const currentLanguage = language ? `It is currently set to ${language}.` : ''; - - const choices = ['ts', 'cs', 'py', 'typescript', 'csharp', 'python']; - return { - command: 'set-lang ', - describe: `set the programming language for the project (typescript, csharp or python). ${currentLanguage}`, - builder: (b) => { - return b - .positional('language', { - describe: 'programming language to use (typescript, csharp or python)', - type: 'string', - choices, - demandOption: true, - }); - }, - handler: async ({ language }) => { - const settings = Settings.load(); - if (['ts', 'typescript'].includes(language)) { - settings.language = 'typescript'; - } else if (['cs', 'csharp'].includes(language)) { - settings.language = 'csharp'; - } else if (['py', 'python'].includes(language)) { - settings.language = 'python'; - } - - settings.save(); - console.log(`Language set to ${settings.language}`); - }, - }; -} diff --git a/packages/cli/src/context.ts b/packages/cli/src/context.ts deleted file mode 100644 index dd4f2de07..000000000 --- a/packages/cli/src/context.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { EnvStorage } from './environment'; -import { Settings } from './settings'; - -export interface IContext { - readonly settings: Settings; - readonly envs: EnvStorage; -} diff --git a/packages/cli/src/environment/env-storage.ts b/packages/cli/src/environment/env-storage.ts deleted file mode 100644 index 7644ffc46..000000000 --- a/packages/cli/src/environment/env-storage.ts +++ /dev/null @@ -1,87 +0,0 @@ -import fs from 'fs'; -import os from 'os'; -import path from 'path'; - -import { Settings } from '../settings'; - -import { Env, IEnv } from './env'; - -export class EnvStorage { - get active() { - return this._active; - } - protected _active: IEnv; - protected _store: Map = new Map(); - protected _settings: Settings; - - constructor(settings: Settings) { - const dev = Env.load(settings.env); - this._store.set('dev', dev); - this._active = dev; - this._settings = settings; - } - - static load(settings: Settings) { - const storage = new EnvStorage(settings); - const base = path.join(os.homedir(), 'teams.cli', 'environments'); - - if (!fs.existsSync(base)) { - return storage; - } - - for (const name of fs.readdirSync(base, { recursive: true })) { - const env = Env.load(path.basename(name.toString(), '.env')); - storage.add(env); - } - - return storage; - } - - getByName(name: string) { - return this._store.get(name); - } - - select(name: string) { - let env = this._store.get(name); - - if (!env) { - env = new Env(name); - env.activate(); - env.save(); - this.add(env); - } - - this._active.deactivate(); - this._active = env; - this._settings.env = env.name; - this._settings.save(); - return env; - } - - add(env: IEnv) { - this._store.set(env.name, env); - } - - remove(name: string) { - this._store.get(name)?.delete(); - this._store.delete(name); - } - - get(key: string) { - return this._active.get(key); - } - - set(key: string, value: string) { - this._active.set(key, value); - this._active.save(); - } - - del(key: string) { - this._active.del(key); - this._active.save(); - } - - list(where?: (item: IEnv, i: number) => boolean) { - return Array.from(this._store.values()).filter((item, i) => (where ? where(item, i) : true)); - } -} diff --git a/packages/cli/src/environment/env.ts b/packages/cli/src/environment/env.ts deleted file mode 100644 index 1a433409a..000000000 --- a/packages/cli/src/environment/env.ts +++ /dev/null @@ -1,110 +0,0 @@ -import fs from 'fs'; -import os from 'os'; -import path from 'path'; - -export type KeyValue = { - readonly key: string; - readonly value: string; -}; - -export interface IEnv { - readonly name: string; - - get(key: string): string | undefined; - set(key: string, value: string): void; - del(key: string): void; - list(where?: (item: KeyValue, i: number) => boolean): Array; - - activate(): void; - deactivate(): void; - - save(): void; - delete(): void; -} - -export class Env implements IEnv { - readonly name: string; - - protected items: Map = new Map(); - - constructor(name: string) { - this.name = name; - } - - static load(name: string) { - const env = new Env(name); - const base = path.join(os.homedir(), 'teams.cli', 'environments'); - const file = path.join(base, `${name}.env`); - - if (!fs.existsSync(file)) { - return env; - } - - const content = fs.readFileSync(file, 'utf8'); - const lines = content.split('\n'); - - for (const [key, value] of lines.map((line) => - line - .trim() - .split('=', 2) - .map((v) => v.trim()) - )) { - if (!key) continue; - env.set(key, value); - } - - return env; - } - - get(key: string) { - return this.items.get(key); - } - - set(key: string, value: string) { - this.items.set(key, value); - } - - del(key: string) { - this.items.delete(key); - } - - list(where?: (item: KeyValue, i: number) => boolean) { - return Array.from(this.items.entries()) - .map(([key, value]) => ({ key, value })) - .filter((item, i) => (where ? where(item, i) : true)); - } - - activate() { - for (const { key, value } of this.list()) { - process.env[key] = value; - } - } - - deactivate() { - for (const { key } of this.list()) { - delete process.env[key]; - } - } - - save() { - const base = path.join(os.homedir(), 'teams.cli', 'environments'); - - if (!fs.existsSync(base)) { - fs.mkdirSync(base, { recursive: true }); - } - - const file = path.join(base, `${this.name}.env`); - fs.writeFileSync(file, this.toString(), 'utf8'); - } - - delete() { - const base = path.join(os.homedir(), 'teams.cli', 'environments'); - const file = path.join(base, `${this.name}.env`); - - if (!fs.existsSync(file)) { - return; - } - - fs.rmSync(file); - } -} diff --git a/packages/cli/src/environment/index.ts b/packages/cli/src/environment/index.ts deleted file mode 100644 index 217f3807c..000000000 --- a/packages/cli/src/environment/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './env'; -export * from './env-storage'; diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts deleted file mode 100644 index f256a4052..000000000 --- a/packages/cli/src/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -#! /usr/bin/env node - -import yargs from 'yargs'; -import { hideBin } from 'yargs/helpers'; - -import * as commands from './commands'; -import { IContext } from './context'; -import { EnvStorage } from './environment'; -import { Settings } from './settings'; - -(async () => { - const settings = Settings.load(); - const envs = EnvStorage.load(settings); - const context: IContext = { settings, envs }; - - envs.select(settings.env); - - const argv = hideBin(process.argv); - const yargsInstance = yargs(argv) - .scriptName('teams') - .version() - .command(commands.New(context)) - .command(commands.Env(context)) - .command(commands.Config(context)) - .command(commands.SetLang(context)) - .demandCommand(1, 'Please specify a command') - .showHelpOnFail(true) - .recommendCommands(); - - // Show help when no arguments are provided - if (argv.length === 0) { - yargsInstance.showHelp(); - } else { - yargsInstance.parse(); - } -})(); diff --git a/packages/cli/src/project/attributes/atk.ts b/packages/cli/src/project/attributes/atk.ts deleted file mode 100644 index 06a1b5610..000000000 --- a/packages/cli/src/project/attributes/atk.ts +++ /dev/null @@ -1,175 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import url from 'node:url'; - -import { Compound, Copy, FileJsonSet, FileUpdate, FileYamlSet, If } from '../operations'; -import { IProjectAttribute } from '../project-attribute'; - -export class AgentsToolkitAttribute implements IProjectAttribute { - readonly id: string; - readonly name: string; - readonly alias = 'atk'; - readonly description = 'include M365 Agents Toolkit configuration'; - - constructor(name: string) { - this.id = `atk[${name}]`; - this.name = name; - } - - typescript(targetDir: string) { - return new Compound( - new Copy( - path.resolve(url.fileURLToPath(import.meta.url), '../..', 'configs', 'atk', this.name, 'typescript'), - targetDir - ), - new FileJsonSet(targetDir, 'package.json', 'devDependencies.env-cmd', 'latest'), - new FileJsonSet( - targetDir, - 'package.json', - 'scripts.dev:teamsfx', - 'npx cross-env NODE_OPTIONS=\'--inspect=9239\' npx env-cmd -f .env npm run dev' - ), - new FileJsonSet( - targetDir, - 'package.json', - 'scripts.dev:teamsfx:testtool', - 'npx cross-env NODE_OPTIONS=\'--inspect=9239\' npx env-cmd -f .env npm run dev' - ), - new FileJsonSet( - targetDir, - 'package.json', - 'scripts.dev:teamsfx:launch-testtool', - 'npx env-cmd --silent -f env/.env.testtool teamsapptester start' - ), - // optional vite project support - new If(() => { - return ( - fs.existsSync(path.join(targetDir, 'vite.config.js')) || - fs.existsSync(path.join(targetDir, 'vite.config.ts')) - ); - }).then( - new Compound( - new FileYamlSet( - targetDir, - 'teamsapp.local.yml', - 'deploy.1.with.envs.VITE_CLIENT_ID', - '${{BOT_ID}}' - ), - new FileYamlSet( - targetDir, - 'teamsapp.local.yml', - 'deploy.1.with.envs.VITE_CLIENT_SECRET', - '${{SECRET_BOT_PASSWORD}}' - ), - new FileYamlSet( - targetDir, - 'teamsapp.local.yml', - 'deploy.1.with.envs.VITE_TENANT_ID', - '${{AAD_APP_TENANT_ID}}' - ) - ) - ) - ); - } - - csharp(targetDir: string) { - // Get the .sln file in the target directory - const slnFile = fs.readdirSync(targetDir).find((file) => file.endsWith('.sln')); - if (!slnFile) { - throw new Error('No .sln file found in the target directory'); - } - - // Get .sln file name - const slnFileName = path.basename(slnFile, '.sln'); - - // Get the .slnlaunch.user file in the target directory - let launchUserFile = fs.readdirSync(targetDir).find((file) => file.endsWith('.slnlaunch.user')); - if (!launchUserFile) { - // create the file - launchUserFile = `${slnFileName}.slnlaunch.user`; - fs.writeFileSync(path.join(targetDir, launchUserFile), JSON.stringify([], null, 2)); - } - - return new Compound( - new Copy( - path.resolve(url.fileURLToPath(import.meta.url), '../..', 'configs', 'atk', this.name, 'csharp'), - targetDir - ), - new FileUpdate(targetDir, launchUserFile, (content) => { - const jsonArray = JSON.parse(content); - const atkDebugProfiles = [ - { - 'Name': 'Microsoft Teams (browser)', - 'Projects': [ - { - 'Path': 'TeamsApp\\TeamsApp.ttkproj', - 'Action': 'StartWithoutDebugging', - 'DebugTarget': 'Microsoft Teams (browser)' - }, - { - 'Path': `${slnFileName}\\${slnFileName}.csproj`, - 'Action': 'Start', - 'DebugTarget': 'Start Project' - } - ] - }, - { - 'Name': 'Microsoft Teams (browser) (skip update Teams App)', - 'Projects': [ - { - 'Path': 'TeamsApp\\TeamsApp.ttkproj', - 'Action': 'StartWithoutDebugging', - 'DebugTarget': 'Microsoft Teams (browser) (skip update Teams App)' - }, - { - 'Path': `${slnFileName}\\${slnFileName}.csproj`, - 'Action': 'Start', - 'DebugTarget': 'Start Project' - } - ] - } - ]; - - jsonArray.push(...atkDebugProfiles); - return JSON.stringify(jsonArray, null, 2); - }), - new FileUpdate(targetDir, slnFile, (content) => { - const lines = content.split(/\r?\n/); - const insertIndex = lines.findIndex(line => line.trim().startsWith('Global')); - - if (insertIndex === -1) { - console.error('Error: Global section not found in .sln'); - throw new Error('Global section not found in .sln'); - } - - const projectTypeGuid = '{GAE04EC0-301F-11D3-BF4B-00C04F79EFBD}'; - const projectName = 'TeamsApp'; - const projectPath = 'TeamsApp\\TeamsApp.ttkproj'; - const projectInstanceGuid = '{HAJ04EC0-301F-11D3-BF4B-00C04F79EFCE}'; - - const projectBlock = [ - `Project("${projectTypeGuid}") = "${projectName}", "${projectPath}", "${projectInstanceGuid}"`, - 'EndProject' - ]; - - lines.splice(insertIndex, 0, ...projectBlock); - - return lines.join('\r\n'); - }) - ); - } - - python(targetDir: string) { - return new Copy( - path.resolve( - url.fileURLToPath(import.meta.url), - '../..', - 'configs', - 'atk', - this.name, - 'python' - ), - targetDir - ); - } -} diff --git a/packages/cli/src/project/attributes/env.ts b/packages/cli/src/project/attributes/env.ts deleted file mode 100644 index ad037034b..000000000 --- a/packages/cli/src/project/attributes/env.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Compound, FileEnvSet, FileJsonSet } from '../operations'; -import { IProjectAttribute } from '../project-attribute'; - -export class EnvAttribute implements IProjectAttribute { - readonly id = 'env'; - readonly name = 'environment'; - readonly alias = 'env'; - readonly description = 'add environment variables'; - - private readonly _filename: string; - private readonly _key: string; - private readonly _value: string; - - constructor(filename: string, key: string, value: string) { - this._filename = filename; - this._key = key; - this._value = value; - } - - typescript(targetDir: string) { - return new Compound(new FileEnvSet(targetDir, this._filename, this._key, this._value)); - } - - async csharp(targetDir: string) { - const changeCase = await import('change-case'); - // Ensures keys like "teams.clientId" are converted to "Teams.ClientId" - // It follows the C# convention for environment variables - const key = this._key.split('.') - .map(part => changeCase.pascalCase(part)) - .join('.'); - - return new Compound(new FileJsonSet(targetDir, this._filename, key, this._value)); - } - - python(targetDir: string) { - return new Compound(new FileEnvSet(targetDir, this._filename, this._key, this._value)); - } -} diff --git a/packages/cli/src/project/attributes/index.ts b/packages/cli/src/project/attributes/index.ts deleted file mode 100644 index c784a7ecd..000000000 --- a/packages/cli/src/project/attributes/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './env'; -export * from './template'; -export * from './atk'; diff --git a/packages/cli/src/project/attributes/template.ts b/packages/cli/src/project/attributes/template.ts deleted file mode 100644 index 535813814..000000000 --- a/packages/cli/src/project/attributes/template.ts +++ /dev/null @@ -1,63 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import url from 'node:url'; - -import { Copy } from '../operations'; -import { IProjectAttribute } from '../project-attribute'; - -export class TemplateAttribute implements IProjectAttribute { - readonly id: string; - readonly name: string; - readonly alias = 't'; - readonly description = 'the app template to use'; - - constructor(name: string) { - this.id = `template[${name}]`; - this.name = name; - } - - typescript(targetDir: string) { - fs.mkdirSync(targetDir, { recursive: true }); - - return new Copy( - path.resolve( - url.fileURLToPath(import.meta.url), - '../..', - 'templates', - 'typescript', - this.name - ), - targetDir - ); - } - - csharp(targetDir: string) { - fs.mkdirSync(targetDir, { recursive: true }); - - return new Copy( - path.resolve( - url.fileURLToPath(import.meta.url), - '../..', - 'templates', - 'csharp', - this.name - ), - targetDir - ); - } - - python(targetDir: string) { - fs.mkdirSync(targetDir, { recursive: true }); - - return new Copy( - path.resolve( - url.fileURLToPath(import.meta.url), - '../..', - 'templates', - 'python', - this.name - ), - targetDir - ); - } -} diff --git a/packages/cli/src/project/handlebars.ts b/packages/cli/src/project/handlebars.ts deleted file mode 100644 index b5e89c606..000000000 --- a/packages/cli/src/project/handlebars.ts +++ /dev/null @@ -1,24 +0,0 @@ -import Handlebars from 'handlebars'; - -import { IProject } from './project'; - -export class HandlebarsTemplate { - static async render(input: any, options?: CompileOptions, project?: IProject) { - const template = Handlebars.compile(input, options); - const runtimeOptions = await this._getRuntimeOptions(); - return template(project, runtimeOptions); - } - - private static async _getRuntimeOptions(): Promise { - const changeCase = await import('change-case'); - - return { - helpers: { - capitalize: (text: string) => !text ? '' : changeCase.capitalCase(text), - toPascalCase: (text: string) => !text ? '' : changeCase.pascalCase(text), - toDotCase: (text: string) => !text ? '' : changeCase.dotCase(text), - toKebabCase: (text: string) => !text ? '' : changeCase.kebabCase(text), - }, - }; - } -} \ No newline at end of file diff --git a/packages/cli/src/project/index.ts b/packages/cli/src/project/index.ts deleted file mode 100644 index 287cdb7f2..000000000 --- a/packages/cli/src/project/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './project'; -export * from './project-builder'; diff --git a/packages/cli/src/project/operations/compound.ts b/packages/cli/src/project/operations/compound.ts deleted file mode 100644 index fb459bc0b..000000000 --- a/packages/cli/src/project/operations/compound.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { IProject } from '../project'; -import { IProjectAttributeOperation } from '../project-attribute'; - -export class Compound implements IProjectAttributeOperation { - readonly name = 'compound'; - - private _operations: Array = []; - - constructor(...operations: Array) { - this._operations = operations; - } - - async up(project: IProject) { - for (const op of this._operations) { - await op.up(project); - } - } - - async down(project: IProject) { - for (const op of this._operations.toReversed()) { - await op.down(project); - } - } -} diff --git a/packages/cli/src/project/operations/copy.ts b/packages/cli/src/project/operations/copy.ts deleted file mode 100644 index 52ebad661..000000000 --- a/packages/cli/src/project/operations/copy.ts +++ /dev/null @@ -1,47 +0,0 @@ -import fs from 'node:fs'; - -import { IProject } from '../project'; -import { IProjectAttributeOperation } from '../project-attribute'; - -import { DirectoryCopy } from './directory-copy'; -import { FileCopy } from './file-copy'; - -export class Copy implements IProjectAttributeOperation { - readonly name = 'copy'; - - private _from: string; - private _to: string; - - constructor(from: string, to: string) { - this._from = from; - this._to = to; - } - - up(project: IProject) { - if (!fs.existsSync(this._from)) { - throw new Error(`"${this._from}" does not exist`); - } - - const stat = fs.statSync(this._from); - - if (stat.isDirectory()) { - return new DirectoryCopy(this._from, this._to).up(project); - } - - return new FileCopy(this._from, this._to).up(project); - } - - down(project: IProject) { - if (!fs.existsSync(this._to)) { - return; - } - - const stat = fs.statSync(this._to); - - if (stat.isDirectory()) { - return new DirectoryCopy(this._from, this._to).down(project); - } - - return new FileCopy(this._from, this._to).down(project); - } -} diff --git a/packages/cli/src/project/operations/directory-copy.ts b/packages/cli/src/project/operations/directory-copy.ts deleted file mode 100644 index 42cdc7c21..000000000 --- a/packages/cli/src/project/operations/directory-copy.ts +++ /dev/null @@ -1,125 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; - -import { HandlebarsTemplate } from '../handlebars'; -import { IProject } from '../project'; -import { IProjectAttributeOperation } from '../project-attribute'; - -import { FileCopy } from './file-copy'; -import { FileTemplateHandlebars } from './file-template-handlebars'; - -export class DirectoryCopy implements IProjectAttributeOperation { - readonly name = 'directory.copy'; - - private _from: string; - private _to: string; - - constructor(from: string, to: string) { - this._from = from; - this._to = to; - } - - async up(project: IProject) { - const operations: Array = []; - - if (!fs.existsSync(this._from)) { - throw new Error(`"${this._from}" does not exist`); - } - - if (!fs.statSync(this._from).isDirectory()) { - throw new Error(`"${this._from}" is not a directory`); - } - - if (!fs.existsSync(this._to)) { - fs.mkdirSync(this._to, { recursive: true }); - } - - const items = fs.readdirSync(this._from); - - for (const item of items) { - const stat = fs.statSync(path.resolve(this._from, item)); - const isHandlebars = item.endsWith('.hbs'); - - let toItem = item; - if (isHandlebars) { - toItem = await HandlebarsTemplate.render(item, { strict: true }, project); - toItem = toItem.replace('.hbs', ''); - } - - if (stat.isDirectory()) { - operations.push( - new DirectoryCopy(path.resolve(this._from, item), path.resolve(this._to, toItem)) - ); - } else { - if (isHandlebars) { - operations.push( - new FileTemplateHandlebars( - path.resolve(this._from, item), - path.resolve(this._to, toItem) - ) - ); - } else { - operations.push( - new FileCopy(path.resolve(this._from, item), path.resolve(this._to, toItem)) - ); - } - } - } - - for (const op of operations) { - await op.up(project); - } - } - - async down(project: IProject) { - const operations: Array = []; - - if (!fs.existsSync(this._from)) { - throw new Error(`"${this._from}" does not exist`); - } - - if (!fs.statSync(this._from).isDirectory()) { - throw new Error(`"${this._from}" is not a directory`); - } - - if (!fs.existsSync(this._to)) { - fs.mkdirSync(this._to, { recursive: true }); - } - - const items = fs.readdirSync(this._from); - - for (const item of items) { - const stat = fs.statSync(path.resolve(this._from, item)); - const isHandlebars = item.endsWith('.hbs'); - - let toItem = item; - if (isHandlebars) { - toItem = await HandlebarsTemplate.render(item, { strict: true }, project); - toItem = toItem.replace('.hbs', ''); - } - - if (stat.isDirectory()) { - operations.push( - new DirectoryCopy(path.resolve(this._from, item), path.resolve(this._to, toItem)) - ); - } else { - if (isHandlebars) { - operations.push( - new FileTemplateHandlebars( - path.resolve(this._from, item), - path.resolve(this._to, toItem) - ) - ); - } else { - operations.push( - new FileCopy(path.resolve(this._from, item), path.resolve(this._to, toItem)) - ); - } - } - } - - for (const op of operations.toReversed()) { - await op.down(project); - } - } -} diff --git a/packages/cli/src/project/operations/file-copy.ts b/packages/cli/src/project/operations/file-copy.ts deleted file mode 100644 index 84bd6fc37..000000000 --- a/packages/cli/src/project/operations/file-copy.ts +++ /dev/null @@ -1,53 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; - -import { String } from '@microsoft/teams.common'; - -import { IProject } from '../project'; -import { IProjectAttributeOperation } from '../project-attribute'; - -export class FileCopy implements IProjectAttributeOperation { - readonly name = 'file.copy'; - - private _from: string; - private _to: string; - - constructor(from: string, to: string) { - this._from = from; - this._to = to; - } - - up(_: IProject) { - const relativeTo = path.relative(process.cwd(), this._to); - - if (!fs.existsSync(this._from)) { - throw new Error(`"${this._from}" does not exist`); - } - - process.stdout.write( - new String().cyan(`copying "${path.basename(this._from)}" => "${relativeTo}"...`).toString() - ); - fs.copyFileSync(this._from, this._to); - process.stdout.write('✔️\n'); - } - - down(_: IProject) { - const relativeTo = path.relative(process.cwd(), this._to); - - if (!fs.existsSync(this._to)) { - return; - } - - process.stdout.write(new String().yellow(`deleting "${relativeTo}"...`).toString()); - fs.rmSync(this._to, { recursive: true }); - - if ( - fs.existsSync(path.dirname(this._to)) && - fs.readdirSync(path.dirname(this._to), { recursive: true }).length === 0 - ) { - fs.rmdirSync(path.dirname(this._to)); - } - - process.stdout.write('✔️\n'); - } -} diff --git a/packages/cli/src/project/operations/file-create.ts b/packages/cli/src/project/operations/file-create.ts deleted file mode 100644 index ca8e2429f..000000000 --- a/packages/cli/src/project/operations/file-create.ts +++ /dev/null @@ -1,59 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; - -import { String } from '@microsoft/teams.common'; - -import { IProject } from '../project'; -import { IProjectAttributeOperation } from '../project-attribute'; - -export class FileCreate implements IProjectAttributeOperation { - readonly name = 'file.create'; - - private _path: string; - private _filename: string; - private _content?: string; - - constructor(path: string, filename: string, content?: string) { - this._path = path; - this._filename = filename; - this._content = content; - } - - up(_: IProject) { - const filePath = path.join(this._path, this._filename); - const relativeFilePath = path.relative(process.cwd(), filePath); - - if (!fs.existsSync(this._path)) { - fs.mkdirSync(this._path, { recursive: true }); - } - - if (fs.existsSync(filePath)) { - throw new Error(`"${filePath}" already exists`); - } - - process.stdout.write(new String().cyan(`creating "${relativeFilePath}"...`).toString()); - fs.writeFileSync(filePath, this._content || '', 'utf8'); - process.stdout.write('✔️\n'); - } - - down(_: IProject) { - const filePath = path.join(this._path, this._filename); - const relativeFilePath = path.relative(process.cwd(), filePath); - - if (!fs.existsSync(filePath)) { - return; - } - - process.stdout.write(new String().yellow(`deleting "${relativeFilePath}"...`).toString()); - fs.rmSync(filePath, { recursive: true }); - - if ( - fs.existsSync(path.dirname(filePath)) && - fs.readdirSync(path.dirname(filePath), { recursive: true }).length === 0 - ) { - fs.rmdirSync(path.dirname(filePath)); - } - - process.stdout.write('✔️\n'); - } -} diff --git a/packages/cli/src/project/operations/file-env-set.ts b/packages/cli/src/project/operations/file-env-set.ts deleted file mode 100644 index f3a986d02..000000000 --- a/packages/cli/src/project/operations/file-env-set.ts +++ /dev/null @@ -1,78 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; - -import { String } from '@microsoft/teams.common'; - -import { IProject } from '../project'; -import { IProjectAttributeOperation } from '../project-attribute'; - -export class FileEnvSet implements IProjectAttributeOperation { - readonly name = 'file.env.set'; - - private _path: string; - private _filename: string; - private _key: string; - private _value: any; - - constructor(path: string, filename: string, key: string, value: any) { - this._path = path; - this._filename = filename; - this._key = key; - this._value = value; - } - - up(_: IProject) { - const filePath = path.join(this._path, this._filename); - const relativeFilePath = path.relative(process.cwd(), filePath); - process.stdout.write( - new String().cyan(`setting "${this._key}" in "${relativeFilePath}"...`).toString() - ); - let lines: string[] = []; - - if (fs.existsSync(filePath)) { - lines = fs.readFileSync(filePath, 'utf8').split('\n'); - } - - const env: Record = {}; - - for (const line of lines) { - const [key, value] = line.split('='); - env[key] = value; - } - - env[this._key] = this._value; - lines = Object.entries(env).map(([key, value]) => `${key}=${value}`); - fs.writeFileSync(filePath, lines.join('\n'), 'utf8'); - process.stdout.write('✔️\n'); - } - - down(_: IProject) { - const filePath = path.join(this._path, this._filename); - const relativeFilePath = path.relative(process.cwd(), filePath); - - if (!fs.existsSync(filePath)) { - return; - } - - process.stdout.write( - new String().yellow(`deleting "${this._key}" from "${relativeFilePath}"...`).toString() - ); - let lines: string[] = []; - - if (fs.existsSync(filePath)) { - lines = fs.readFileSync(filePath, 'utf8').split('\n'); - } - - const env: Record = {}; - - for (const line of lines) { - const [key, value] = line.split('='); - env[key] = value; - } - - delete env[this._key]; - lines = Object.entries(env).map(([key, value]) => `${key}=${value}`); - fs.writeFileSync(filePath, lines.join('\n'), 'utf8'); - process.stdout.write('✔️\n'); - } -} diff --git a/packages/cli/src/project/operations/file-json-set.ts b/packages/cli/src/project/operations/file-json-set.ts deleted file mode 100644 index 727d5d5fd..000000000 --- a/packages/cli/src/project/operations/file-json-set.ts +++ /dev/null @@ -1,126 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; - -import { String } from '@microsoft/teams.common'; - -import { IProject } from '../project'; -import { IProjectAttributeOperation } from '../project-attribute'; - -export class FileJsonSet implements IProjectAttributeOperation { - readonly name = 'file.json.set'; - - private _path: string; - private _filename: string; - private _key: string; - private _value: any; - - constructor(path: string, filename: string, key: string, value: any) { - this._path = path; - this._filename = filename; - this._key = key; - this._value = value; - } - - up(_: IProject) { - const ext = path.extname(this._filename).toLowerCase(); - const filePath = path.join(this._path, this._filename); - const relativeFilePath = path.relative(process.cwd(), filePath); - - if (!fs.existsSync(filePath)) { - throw new Error(`"${filePath}" does not exist`); - } - - if (ext !== '.json') { - throw new Error(`"${filePath}" is not a json type`); - } - - process.stdout.write( - new String().cyan(`setting "${this._key}" in "${relativeFilePath}"...`).toString() - ); - let json = {}; - - try { - const content = fs.readFileSync(filePath, 'utf8'); - json = JSON.parse(content); - } catch (err) { - throw new Error(`"${filePath}" could not be parsed`); - } - - json = this._set(json, this._key, this._value); - fs.writeFileSync(filePath, JSON.stringify(json, null, 2) + '\n', 'utf8'); - process.stdout.write('✔️\n'); - } - - down(_: IProject) { - const ext = path.extname(this._filename).toLowerCase(); - const filePath = path.join(this._path, this._filename); - const relativeFilePath = path.relative(process.cwd(), filePath); - - if (!fs.existsSync(filePath)) { - return; - } - - if (ext !== '.json') { - throw new Error(`"${filePath}" is not a json type`); - } - - let json = {}; - - try { - const content = fs.readFileSync(filePath, 'utf8'); - json = JSON.parse(content); - } catch (err) { - throw new Error(`"${filePath}" could not be parsed`); - } - - if (!this._exists(json, this._key)) { - return; - } - - process.stdout.write( - new String().yellow(`removing "${this._key}" in "${relativeFilePath}"...`).toString() - ); - - json = this._set(json, this._key); - fs.writeFileSync(filePath, JSON.stringify(json, null, 2) + '\n', 'utf8'); - process.stdout.write('✔️\n'); - } - - private _exists(object: any, path: string) { - const parts = path.split('.'); - let current = object; - - while (parts.length) { - const key = parts.shift(); - - if (!key) continue; - if (!current[key]) return false; - current = current[key]; - } - - return current !== undefined; - } - - private _set(object: any, path: string, value?: any) { - const parts = path.split('.'); - let current = object; - - while (parts.length) { - const key = parts.shift(); - - if (!key) continue; - - if (!parts.length) { - current[key] = value; - } else { - if (!current[key]) { - current[key] = {}; - } - - current = current[key]; - } - } - - return object; - } -} diff --git a/packages/cli/src/project/operations/file-template-handlebars.ts b/packages/cli/src/project/operations/file-template-handlebars.ts deleted file mode 100644 index 689ad5ca6..000000000 --- a/packages/cli/src/project/operations/file-template-handlebars.ts +++ /dev/null @@ -1,62 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; - -import { String } from '@microsoft/teams.common'; - -import { HandlebarsTemplate } from '../handlebars'; - -import { IProject } from '../project'; -import { IProjectAttributeOperation } from '../project-attribute'; - -export class FileTemplateHandlebars implements IProjectAttributeOperation { - readonly name = 'file.template.handlebars'; - - private _from: string; - private _to: string; - - constructor(from: string, to: string) { - this._from = from; - this._to = to; - } - - async up(project: IProject) { - const relativeTo = path.relative(process.cwd(), this._to); - - if (!fs.existsSync(this._from)) { - throw new Error(`"${this._from}" does not exist`); - } - - const content = fs.readFileSync(this._from, 'utf8'); - - process.stdout.write( - new String() - .cyan(`rendering "${path.basename(this._from, '.hbs')}" => "${relativeTo}"...`) - .toString() - ); - - const rendered = await HandlebarsTemplate.render(content, { strict: true }, project); - - fs.writeFileSync(this._to, rendered, 'utf8'); - process.stdout.write('✔️\n'); - } - - down(_: IProject) { - const relativeTo = path.relative(process.cwd(), this._to); - - if (!fs.existsSync(this._to)) { - return; - } - - process.stdout.write(new String().yellow(`deleting "${relativeTo}"...`).toString()); - fs.rmSync(this._to, { recursive: true }); - - if ( - fs.existsSync(path.dirname(this._to)) && - fs.readdirSync(path.dirname(this._to), { recursive: true }).length === 0 - ) { - fs.rmdirSync(path.dirname(this._to)); - } - - process.stdout.write('✔️\n'); - } -} diff --git a/packages/cli/src/project/operations/file-update.ts b/packages/cli/src/project/operations/file-update.ts deleted file mode 100644 index 5c58dceba..000000000 --- a/packages/cli/src/project/operations/file-update.ts +++ /dev/null @@ -1,46 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; - -import { String } from '@microsoft/teams.common'; - -import { IProject } from '../project'; -import { IProjectAttributeOperation } from '../project-attribute'; - -export class FileUpdate implements IProjectAttributeOperation { - readonly name = 'file.update'; - - private _path: string; - private _filename: string; - private _content?: string | ((content: string) => string); - - constructor(path: string, filename: string, content?: string | ((content: string) => string)) { - this._path = path; - this._filename = filename; - this._content = content; - } - - up(_: IProject) { - const filePath = path.join(this._path, this._filename); - const relativeFilePath = path.relative(process.cwd(), filePath); - - if (!fs.existsSync(filePath)) { - throw new Error(`"${filePath}" does not exist`); - } - - let content = ''; - if (this._content) { - if (typeof this._content === 'function') { - const fileContent = fs.readFileSync(filePath, 'utf8'); - content = this._content(fileContent); - } else { - content = this._content; - } - } - - process.stdout.write(new String().cyan(`updating "${relativeFilePath}"...`).toString()); - fs.writeFileSync(filePath, content, 'utf8'); - process.stdout.write('✔️\n'); - } - - down(_: IProject) {} -} diff --git a/packages/cli/src/project/operations/file-yaml-set.ts b/packages/cli/src/project/operations/file-yaml-set.ts deleted file mode 100644 index 3ea678f3a..000000000 --- a/packages/cli/src/project/operations/file-yaml-set.ts +++ /dev/null @@ -1,124 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; - -import yaml from 'yaml'; - -import { String } from '@microsoft/teams.common'; - -import { IProject } from '../project'; -import { IProjectAttributeOperation } from '../project-attribute'; - -export class FileYamlSet implements IProjectAttributeOperation { - readonly name = 'file.yaml.set'; - - private _path: string; - private _filename: string; - private _key: string; - private _value: any; - - constructor(path: string, filename: string, key: string, value: any) { - this._path = path; - this._filename = filename; - this._key = key; - this._value = value; - } - - up(_: IProject) { - const ext = path.extname(this._filename).toLowerCase(); - const filePath = path.join(this._path, this._filename); - const relativeFilePath = path.relative(process.cwd(), filePath); - - if (!fs.existsSync(filePath)) { - throw new Error(`"${filePath}" does not exist`); - } - - if (ext !== '.yml' && ext !== '.yaml') { - throw new Error(`"${filePath}" is not a yaml type`); - } - - process.stdout.write( - new String().cyan(`setting "${this._key}" in "${relativeFilePath}"...`).toString() - ); - let object = {}; - - try { - const content = fs.readFileSync(filePath, 'utf8'); - object = yaml.parse(content); - } catch (err) { - throw new Error(`"${filePath}" could not be parsed`); - } - - object = this._set(object, this._key, this._value); - fs.writeFileSync(filePath, yaml.stringify(object, null, 2) + '\n', 'utf8'); - process.stdout.write('✔️\n'); - } - - down(_: IProject) { - const ext = path.extname(this._filename).toLowerCase(); - const filePath = path.join(this._path, this._filename); - const relativeFilePath = path.relative(process.cwd(), filePath); - - if (!fs.existsSync(filePath)) { - return; - } - - if (ext !== '.yml' && ext !== '.yaml') { - throw new Error(`"${filePath}" is not a yaml type`); - } - - let object = {}; - - try { - const content = fs.readFileSync(filePath, 'utf8'); - object = yaml.parse(content); - } catch (err) { - throw new Error(`"${filePath}" could not be parsed`); - } - - if (!this._exists(object, this._key)) { - return; - } - - process.stdout.write( - new String().yellow(`removing "${this._key}" in "${relativeFilePath}"...`).toString() - ); - - object = this._set(object, this._key); - fs.writeFileSync(filePath, yaml.stringify(object, null, 2) + '\n', 'utf8'); - process.stdout.write('✔️\n'); - } - - private _exists(object: any, path: string) { - const parts = path.split('.'); - let current = object; - - while (parts.length) { - const key = parts.shift(); - - if (!key) continue; - if (!current[key]) return false; - current = current[key]; - } - - return current !== undefined; - } - - private _set(object: any, path: string, value?: any) { - const parts = path.split('.'); - let current = object; - - while (parts.length) { - const key = parts.shift(); - - if (!key) continue; - - if (!parts.length) { - current[key] = value; - } else { - current = current[key] || {}; - } - } - - return object; - } -} diff --git a/packages/cli/src/project/operations/if.ts b/packages/cli/src/project/operations/if.ts deleted file mode 100644 index 64cb9611c..000000000 --- a/packages/cli/src/project/operations/if.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { IProject } from '../project'; -import { IProjectAttributeOperation } from '../project-attribute'; - -export class If implements IProjectAttributeOperation { - readonly name = 'if'; - - private _conditions: Array<() => boolean | Promise> = []; - private _then?: IProjectAttributeOperation; - private _else?: IProjectAttributeOperation; - - constructor(...conditions: Array<() => boolean | Promise>) { - this._conditions = conditions; - } - - then(operation: IProjectAttributeOperation) { - this._then = operation; - return this; - } - - else(operation: IProjectAttributeOperation) { - this._else = operation; - return this; - } - - async up(project: IProject) { - const res = await Promise.all(this._conditions.map((condition) => condition())); - - if (res.includes(false)) { - await this._else?.up(project); - return; - } - - await this._then?.up(project); - } - - async down(project: IProject) { - const res = await Promise.all(this._conditions.map((condition) => condition())); - - if (res.includes(false)) { - await this._else?.down(project); - return; - } - - await this._then?.down(project); - } -} diff --git a/packages/cli/src/project/operations/index.ts b/packages/cli/src/project/operations/index.ts deleted file mode 100644 index 666437ad3..000000000 --- a/packages/cli/src/project/operations/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -export * from './compound'; -export * from './copy'; -export * from './directory-copy'; -export * from './file-copy'; -export * from './file-create'; -export * from './file-update'; -export * from './file-json-set'; -export * from './file-yaml-set'; -export * from './file-env-set'; -export * from './if'; diff --git a/packages/cli/src/project/project-attribute.ts b/packages/cli/src/project/project-attribute.ts deleted file mode 100644 index 21e0c1b0a..000000000 --- a/packages/cli/src/project/project-attribute.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { IProject } from './project'; - -export interface IProjectAttribute { - readonly id: string; - readonly name: string; - readonly alias?: string; - readonly description: string; - - typescript(targetDir: string): IProjectAttributeOperation | Promise; - csharp(targetDir: string): IProjectAttributeOperation | Promise; - python(targetDir: string): IProjectAttributeOperation | Promise; -} - -export interface IProjectAttributeOperation { - readonly name: string; - - up(project: IProject): void | Promise; - down(project: IProject): void | Promise; -} diff --git a/packages/cli/src/project/project-builder.ts b/packages/cli/src/project/project-builder.ts deleted file mode 100644 index eec95539f..000000000 --- a/packages/cli/src/project/project-builder.ts +++ /dev/null @@ -1,73 +0,0 @@ -import * as attributes from './attributes'; -import { Project, ProjectLanguage } from './project'; -import { IProjectAttribute } from './project-attribute'; - -export class ProjectBuilder { - get path() { return this._path; } - private _path?: string; - - get name() { return this._name; } - private _name?: string; - - get language() { return this._language; } - private _language: ProjectLanguage = 'typescript'; - - private readonly _attributes: Array = []; - - withPath(path: string) { - this._path = path; - return this; - } - - withName(name: string) { - this._name = name; - return this; - } - - withLanguage(language: ProjectLanguage) { - this._language = language; - return this; - } - - addEnv(key: string, value: string, filename?: string) { - if (!filename) { - if (this._language === 'typescript' || this._language === 'python') { - filename = '.env'; - } else { - filename = 'appsettings.Development.json'; - } - } - this._attributes.push(new attributes.EnvAttribute(filename, key, value)); - return this; - } - - addTemplate(name: string) { - if (this._attributes.some((attr) => attr.id === `template[${name}]`)) { - return this; - } - - this._attributes.push(new attributes.TemplateAttribute(name)); - return this; - } - - addAgentsToolkit(name: string) { - this._attributes.push(new attributes.AgentsToolkitAttribute(name)); - return this; - } - - build() { - if (!this._path) { - throw new Error('path is required'); - } - - if (!this._name) { - throw new Error('name is required'); - } - - if (!this._language) { - throw new Error('language is required'); - } - - return new Project(this._path, this._name, this._language, this._attributes); - } -} diff --git a/packages/cli/src/project/project.ts b/packages/cli/src/project/project.ts deleted file mode 100644 index 53f497889..000000000 --- a/packages/cli/src/project/project.ts +++ /dev/null @@ -1,98 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; - -import { IProjectAttribute } from './project-attribute'; -import { ProjectBuilder } from './project-builder'; - -export type ProjectLanguage = 'typescript' | 'csharp' | 'python'; - -export interface IProject { - readonly path: string; - readonly name: string; - readonly language: ProjectLanguage; -} - -export class Project implements IProject { - get path() { - return this._path; - } - private _path: string; - - get name() { - return this._name; - } - private _name: string; - - get language() { - return this._language; - } - private _language: ProjectLanguage; - - private readonly _attributes: Array = []; - - constructor( - path: string, - name: string, - language: ProjectLanguage, - attributes: Array = [] - ) { - this._path = path; - this._name = name; - this._language = language; - this._attributes = attributes; - } - - static detectLanguage(): ProjectLanguage | undefined { - if (fs.existsSync(path.join(process.cwd(), 'package.json'))) { - return 'typescript'; - } - if (fs.readdirSync(process.cwd()).some(file => file.endsWith('.sln'))) { - return 'csharp'; - } - if ( - fs.existsSync(path.join(process.cwd(), 'pyproject.toml')) - ) { - return 'python'; - } - return undefined; - } - - static builder() { - return new ProjectBuilder(); - } - - static load() { - const language = this.detectLanguage(); - - if (!language) { - throw new Error('Are you in the right folder? Expected a package.json (Typescript), .sln (C#), or pyproject.toml (Python).'); - } - - return new ProjectBuilder() - .withPath(process.cwd()) - .withName(path.basename(process.cwd())) - .withLanguage(language); - } - - async up() { - for (const attribute of this._attributes) { - const op = await attribute[this._language](this._path); - await op.up({ - path: this.path, - name: this.name, - language: this.language, - }); - } - } - - async down() { - for (const attribute of this._attributes.toReversed()) { - const op = await attribute[this._language](this._path); - await op.down({ - path: this.path, - name: this.name, - language: this.language, - }); - } - } -} diff --git a/packages/cli/src/settings.ts b/packages/cli/src/settings.ts deleted file mode 100644 index db65eba40..000000000 --- a/packages/cli/src/settings.ts +++ /dev/null @@ -1,48 +0,0 @@ -import fs from 'fs'; -import os from 'os'; -import path from 'path'; - -import { z } from 'zod'; - -import { ProjectLanguage } from './project/project'; - -const languageEnum = z.enum(['typescript', 'csharp', 'python']); - -const Schema = z.object({ - env: z.string(), - language: languageEnum.optional(), -}); - -export type ISettings = z.infer; -export class Settings implements ISettings { - env: string; - language?: ProjectLanguage; - - constructor(value?: ISettings) { - this.env = value?.env || 'dev'; - this.language = value?.language; - } - - static load() { - const base = path.join(os.homedir(), 'teams.cli'); - const file = path.join(base, 'settings.json'); - - if (!fs.existsSync(file)) { - return new Settings(); - } - - const value: ISettings = JSON.parse(fs.readFileSync(file, 'utf8')); - return new Settings(value); - } - - save() { - const base = path.join(os.homedir(), 'teams.cli'); - const file = path.join(base, 'settings.json'); - - if (!fs.existsSync(base)) { - fs.mkdirSync(base, { recursive: true }); - } - - fs.writeFileSync(file, JSON.stringify(this), 'utf8'); - } -} diff --git a/packages/cli/templates/csharp/echo/{{name}}.hbs/.editorconfig b/packages/cli/templates/csharp/echo/{{name}}.hbs/.editorconfig deleted file mode 100644 index 3868bd791..000000000 --- a/packages/cli/templates/csharp/echo/{{name}}.hbs/.editorconfig +++ /dev/null @@ -1,378 +0,0 @@ -root = true - -# All files -[*] -indent_style = space - -# Xml files -[*.xml] -indent_size = 2 - -# C# files -[*.cs] - -#### Core EditorConfig Options #### - -# Indentation and spacing -indent_size = 4 -tab_width = 4 - -# New line preferences -insert_final_newline = false - -#### .NET Coding Conventions #### -[*.{cs,vb}] - -# Organize usings -dotnet_separate_import_directive_groups = true -dotnet_sort_system_directives_first = true -file_header_template = unset - -# this. and Me. preferences -dotnet_style_qualification_for_event = false:silent -dotnet_style_qualification_for_field = false:silent -dotnet_style_qualification_for_method = false:silent -dotnet_style_qualification_for_property = false:silent - -# Language keywords vs BCL types preferences -dotnet_style_predefined_type_for_locals_parameters_members = true:silent -dotnet_style_predefined_type_for_member_access = true:silent - -# Parentheses preferences -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent - -# Modifier preferences -dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent - -# Expression-level preferences -dotnet_style_coalesce_expression = true:suggestion -dotnet_style_collection_initializer = true:suggestion -dotnet_style_explicit_tuple_names = true:suggestion -dotnet_style_namespace_match_folder = true:suggestion -dotnet_style_null_propagation = true:suggestion -dotnet_style_object_initializer = true:suggestion -dotnet_style_operator_placement_when_wrapping = beginning_of_line -dotnet_style_prefer_auto_properties = true:suggestion -dotnet_style_prefer_collection_expression = when_types_loosely_match:suggestion -dotnet_style_prefer_compound_assignment = true:suggestion -dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion -dotnet_style_prefer_conditional_expression_over_return = true:suggestion -dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed:suggestion -dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion -dotnet_style_prefer_inferred_tuple_names = true:suggestion -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion -dotnet_style_prefer_simplified_boolean_expressions = true:suggestion -dotnet_style_prefer_simplified_interpolation = true:suggestion - -# Field preferences -dotnet_style_readonly_field = true:warning - -# Parameter preferences -dotnet_code_quality_unused_parameters = all:suggestion - -# Suppression preferences -dotnet_remove_unnecessary_suppression_exclusions = none - -#### C# Coding Conventions #### -[*.cs] - -# var preferences -csharp_style_var_elsewhere = false:silent -csharp_style_var_for_built_in_types = false:silent -csharp_style_var_when_type_is_apparent = false:silent - -# Expression-bodied members -csharp_style_expression_bodied_accessors = true:silent -csharp_style_expression_bodied_constructors = false:silent -csharp_style_expression_bodied_indexers = true:silent -csharp_style_expression_bodied_lambdas = true:suggestion -csharp_style_expression_bodied_local_functions = false:silent -csharp_style_expression_bodied_methods = false:silent -csharp_style_expression_bodied_operators = false:silent -csharp_style_expression_bodied_properties = true:silent - -# Pattern matching preferences -csharp_style_pattern_matching_over_as_with_null_check = true:suggestion -csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion -csharp_style_prefer_extended_property_pattern = true:suggestion -csharp_style_prefer_not_pattern = true:suggestion -csharp_style_prefer_pattern_matching = true:silent -csharp_style_prefer_switch_expression = true:suggestion - -# Null-checking preferences -csharp_style_conditional_delegate_call = true:suggestion - -# Modifier preferences -csharp_prefer_static_anonymous_function = true:suggestion -csharp_prefer_static_local_function = true:warning -csharp_preferred_modifier_order = public,private,protected,internal,file,const,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:suggestion -csharp_style_prefer_readonly_struct = true:suggestion -csharp_style_prefer_readonly_struct_member = true:suggestion - -# Code-block preferences -csharp_prefer_braces = true:silent -csharp_prefer_simple_using_statement = true:suggestion -csharp_style_namespace_declarations = file_scoped:suggestion -csharp_style_prefer_method_group_conversion = true:silent -csharp_style_prefer_primary_constructors = true:suggestion -csharp_style_prefer_top_level_statements = true:silent - -# Expression-level preferences -csharp_prefer_simple_default_expression = true:suggestion -csharp_style_deconstructed_variable_declaration = true:suggestion -csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion -csharp_style_inlined_variable_declaration = true:suggestion -csharp_style_prefer_index_operator = true:suggestion -csharp_style_prefer_local_over_anonymous_function = true:suggestion -csharp_style_prefer_null_check_over_type_check = true:suggestion -csharp_style_prefer_range_operator = true:suggestion -csharp_style_prefer_tuple_swap = true:suggestion -csharp_style_prefer_utf8_string_literals = true:suggestion -csharp_style_throw_expression = true:suggestion -csharp_style_unused_value_assignment_preference = discard_variable:suggestion -csharp_style_unused_value_expression_statement_preference = discard_variable:silent - -# 'using' directive preferences -csharp_using_directive_placement = outside_namespace:silent - -#### C# Formatting Rules #### - -# New line preferences -csharp_new_line_before_catch = true -csharp_new_line_before_else = true -csharp_new_line_before_finally = true -csharp_new_line_before_members_in_anonymous_types = true -csharp_new_line_before_members_in_object_initializers = true -csharp_new_line_before_open_brace = all -csharp_new_line_between_query_expression_clauses = true - -# Indentation preferences -csharp_indent_block_contents = true -csharp_indent_braces = false -csharp_indent_case_contents = true -csharp_indent_case_contents_when_block = true -csharp_indent_labels = one_less_than_current -csharp_indent_switch_labels = true - -# Space preferences -csharp_space_after_cast = false -csharp_space_after_colon_in_inheritance_clause = true -csharp_space_after_comma = true -csharp_space_after_dot = false -csharp_space_after_keywords_in_control_flow_statements = true -csharp_space_after_semicolon_in_for_statement = true -csharp_space_around_binary_operators = before_and_after -csharp_space_around_declaration_statements = false -csharp_space_before_colon_in_inheritance_clause = true -csharp_space_before_comma = false -csharp_space_before_dot = false -csharp_space_before_open_square_brackets = false -csharp_space_before_semicolon_in_for_statement = false -csharp_space_between_empty_square_brackets = false -csharp_space_between_method_call_empty_parameter_list_parentheses = false -csharp_space_between_method_call_name_and_opening_parenthesis = false -csharp_space_between_method_call_parameter_list_parentheses = false -csharp_space_between_method_declaration_empty_parameter_list_parentheses = false -csharp_space_between_method_declaration_name_and_open_parenthesis = false -csharp_space_between_method_declaration_parameter_list_parentheses = false -csharp_space_between_parentheses = false -csharp_space_between_square_brackets = false - -# Wrapping preferences -csharp_preserve_single_line_blocks = true -csharp_preserve_single_line_statements = true - -#### Naming styles #### -[*.{cs,vb}] - -# Naming rules - -dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.severity = suggestion -dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.symbols = types_and_namespaces -dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.style = pascalcase - -dotnet_naming_rule.interfaces_should_be_ipascalcase.severity = suggestion -dotnet_naming_rule.interfaces_should_be_ipascalcase.symbols = interfaces -dotnet_naming_rule.interfaces_should_be_ipascalcase.style = ipascalcase - -dotnet_naming_rule.type_parameters_should_be_tpascalcase.severity = suggestion -dotnet_naming_rule.type_parameters_should_be_tpascalcase.symbols = type_parameters -dotnet_naming_rule.type_parameters_should_be_tpascalcase.style = tpascalcase - -dotnet_naming_rule.methods_should_be_pascalcase.severity = suggestion -dotnet_naming_rule.methods_should_be_pascalcase.symbols = methods -dotnet_naming_rule.methods_should_be_pascalcase.style = pascalcase - -dotnet_naming_rule.properties_should_be_pascalcase.severity = suggestion -dotnet_naming_rule.properties_should_be_pascalcase.symbols = properties -dotnet_naming_rule.properties_should_be_pascalcase.style = pascalcase - -dotnet_naming_rule.events_should_be_pascalcase.severity = suggestion -dotnet_naming_rule.events_should_be_pascalcase.symbols = events -dotnet_naming_rule.events_should_be_pascalcase.style = pascalcase - -dotnet_naming_rule.local_variables_should_be_camelcase.severity = suggestion -dotnet_naming_rule.local_variables_should_be_camelcase.symbols = local_variables -dotnet_naming_rule.local_variables_should_be_camelcase.style = camelcase - -dotnet_naming_rule.local_constants_should_be_camelcase.severity = suggestion -dotnet_naming_rule.local_constants_should_be_camelcase.symbols = local_constants -dotnet_naming_rule.local_constants_should_be_camelcase.style = camelcase - -dotnet_naming_rule.parameters_should_be_camelcase.severity = suggestion -dotnet_naming_rule.parameters_should_be_camelcase.symbols = parameters -dotnet_naming_rule.parameters_should_be_camelcase.style = camelcase - -dotnet_naming_rule.public_fields_should_be_pascalcase.severity = suggestion -dotnet_naming_rule.public_fields_should_be_pascalcase.symbols = public_fields -dotnet_naming_rule.public_fields_should_be_pascalcase.style = pascalcase - -dotnet_naming_rule.private_fields_should_be__camelcase.severity = suggestion -dotnet_naming_rule.private_fields_should_be__camelcase.symbols = private_fields -dotnet_naming_rule.private_fields_should_be__camelcase.style = _camelcase - -dotnet_naming_rule.private_static_fields_should_be_s_camelcase.severity = suggestion -dotnet_naming_rule.private_static_fields_should_be_s_camelcase.symbols = private_static_fields -dotnet_naming_rule.private_static_fields_should_be_s_camelcase.style = s_camelcase - -dotnet_naming_rule.public_constant_fields_should_be_pascalcase.severity = suggestion -dotnet_naming_rule.public_constant_fields_should_be_pascalcase.symbols = public_constant_fields -dotnet_naming_rule.public_constant_fields_should_be_pascalcase.style = pascalcase - -dotnet_naming_rule.private_constant_fields_should_be_pascalcase.severity = suggestion -dotnet_naming_rule.private_constant_fields_should_be_pascalcase.symbols = private_constant_fields -dotnet_naming_rule.private_constant_fields_should_be_pascalcase.style = pascalcase - -dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.severity = suggestion -dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.symbols = public_static_readonly_fields -dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.style = pascalcase - -dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.severity = suggestion -dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.symbols = private_static_readonly_fields -dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.style = pascalcase - -dotnet_naming_rule.enums_should_be_pascalcase.severity = suggestion -dotnet_naming_rule.enums_should_be_pascalcase.symbols = enums -dotnet_naming_rule.enums_should_be_pascalcase.style = pascalcase - -dotnet_naming_rule.local_functions_should_be_pascalcase.severity = suggestion -dotnet_naming_rule.local_functions_should_be_pascalcase.symbols = local_functions -dotnet_naming_rule.local_functions_should_be_pascalcase.style = pascalcase - -dotnet_naming_rule.non_field_members_should_be_pascalcase.severity = suggestion -dotnet_naming_rule.non_field_members_should_be_pascalcase.symbols = non_field_members -dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase - -# Symbol specifications - -dotnet_naming_symbols.interfaces.applicable_kinds = interface -dotnet_naming_symbols.interfaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.interfaces.required_modifiers = - -dotnet_naming_symbols.enums.applicable_kinds = enum -dotnet_naming_symbols.enums.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.enums.required_modifiers = - -dotnet_naming_symbols.events.applicable_kinds = event -dotnet_naming_symbols.events.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.events.required_modifiers = - -dotnet_naming_symbols.methods.applicable_kinds = method -dotnet_naming_symbols.methods.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.methods.required_modifiers = - -dotnet_naming_symbols.properties.applicable_kinds = property -dotnet_naming_symbols.properties.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.properties.required_modifiers = - -dotnet_naming_symbols.public_fields.applicable_kinds = field -dotnet_naming_symbols.public_fields.applicable_accessibilities = public, internal -dotnet_naming_symbols.public_fields.required_modifiers = - -dotnet_naming_symbols.private_fields.applicable_kinds = field -dotnet_naming_symbols.private_fields.applicable_accessibilities = private, protected, protected_internal, private_protected -dotnet_naming_symbols.private_fields.required_modifiers = - -dotnet_naming_symbols.private_static_fields.applicable_kinds = field -dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private, protected, protected_internal, private_protected -dotnet_naming_symbols.private_static_fields.required_modifiers = static - -dotnet_naming_symbols.types_and_namespaces.applicable_kinds = namespace, class, struct, interface, enum -dotnet_naming_symbols.types_and_namespaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.types_and_namespaces.required_modifiers = - -dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method -dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.non_field_members.required_modifiers = - -dotnet_naming_symbols.type_parameters.applicable_kinds = namespace -dotnet_naming_symbols.type_parameters.applicable_accessibilities = * -dotnet_naming_symbols.type_parameters.required_modifiers = - -dotnet_naming_symbols.private_constant_fields.applicable_kinds = field -dotnet_naming_symbols.private_constant_fields.applicable_accessibilities = private, protected, protected_internal, private_protected -dotnet_naming_symbols.private_constant_fields.required_modifiers = const - -dotnet_naming_symbols.local_variables.applicable_kinds = local -dotnet_naming_symbols.local_variables.applicable_accessibilities = local -dotnet_naming_symbols.local_variables.required_modifiers = - -dotnet_naming_symbols.local_constants.applicable_kinds = local -dotnet_naming_symbols.local_constants.applicable_accessibilities = local -dotnet_naming_symbols.local_constants.required_modifiers = const - -dotnet_naming_symbols.parameters.applicable_kinds = parameter -dotnet_naming_symbols.parameters.applicable_accessibilities = * -dotnet_naming_symbols.parameters.required_modifiers = - -dotnet_naming_symbols.public_constant_fields.applicable_kinds = field -dotnet_naming_symbols.public_constant_fields.applicable_accessibilities = public, internal -dotnet_naming_symbols.public_constant_fields.required_modifiers = const - -dotnet_naming_symbols.public_static_readonly_fields.applicable_kinds = field -dotnet_naming_symbols.public_static_readonly_fields.applicable_accessibilities = public, internal -dotnet_naming_symbols.public_static_readonly_fields.required_modifiers = readonly, static - -dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field -dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private, protected, protected_internal, private_protected -dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = readonly, static - -dotnet_naming_symbols.local_functions.applicable_kinds = local_function -dotnet_naming_symbols.local_functions.applicable_accessibilities = * -dotnet_naming_symbols.local_functions.required_modifiers = - -# Naming styles - -dotnet_naming_style.pascalcase.required_prefix = -dotnet_naming_style.pascalcase.required_suffix = -dotnet_naming_style.pascalcase.word_separator = -dotnet_naming_style.pascalcase.capitalization = pascal_case - -dotnet_naming_style.ipascalcase.required_prefix = I -dotnet_naming_style.ipascalcase.required_suffix = -dotnet_naming_style.ipascalcase.word_separator = -dotnet_naming_style.ipascalcase.capitalization = pascal_case - -dotnet_naming_style.tpascalcase.required_prefix = T -dotnet_naming_style.tpascalcase.required_suffix = -dotnet_naming_style.tpascalcase.word_separator = -dotnet_naming_style.tpascalcase.capitalization = pascal_case - -dotnet_naming_style._camelcase.required_prefix = _ -dotnet_naming_style._camelcase.required_suffix = -dotnet_naming_style._camelcase.word_separator = -dotnet_naming_style._camelcase.capitalization = camel_case - -dotnet_naming_style.camelcase.required_prefix = -dotnet_naming_style.camelcase.required_suffix = -dotnet_naming_style.camelcase.word_separator = -dotnet_naming_style.camelcase.capitalization = camel_case - -dotnet_naming_style.s_camelcase.required_prefix = s_ -dotnet_naming_style.s_camelcase.required_suffix = -dotnet_naming_style.s_camelcase.word_separator = -dotnet_naming_style.s_camelcase.capitalization = camel_case - diff --git a/packages/cli/templates/csharp/echo/{{name}}.hbs/Program.cs.hbs b/packages/cli/templates/csharp/echo/{{name}}.hbs/Program.cs.hbs deleted file mode 100644 index 2cbc5c678..000000000 --- a/packages/cli/templates/csharp/echo/{{name}}.hbs/Program.cs.hbs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.Teams.Apps.Activities; -using Microsoft.Teams.Apps.Extensions; -using Microsoft.Teams.Plugins.AspNetCore.Extensions; -using Microsoft.Teams.Plugins.AspNetCore.DevTools.Extensions; - -var builder = WebApplication.CreateBuilder(args); -builder.AddTeams().AddTeamsDevTools(); -var app = builder.Build(); -var teams = app.UseTeams(); - -teams.OnMessage(async (context, cancellationToken) => -{ - await context.Typing(cancellationToken); - await context.Send($"you said '{context.Activity.Text}'", cancellationToken); -}); - -app.Run(); \ No newline at end of file diff --git a/packages/cli/templates/csharp/echo/{{name}}.hbs/Properties/launchSettings.json b/packages/cli/templates/csharp/echo/{{name}}.hbs/Properties/launchSettings.json deleted file mode 100644 index 51cb88704..000000000 --- a/packages/cli/templates/csharp/echo/{{name}}.hbs/Properties/launchSettings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "http://localhost:3978/devtools", - "applicationUrl": "http://localhost:3978", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} \ No newline at end of file diff --git a/packages/cli/templates/csharp/echo/{{name}}.hbs/appsettings.Development.json b/packages/cli/templates/csharp/echo/{{name}}.hbs/appsettings.Development.json deleted file mode 100644 index 08514a177..000000000 --- a/packages/cli/templates/csharp/echo/{{name}}.hbs/appsettings.Development.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - }, - "Microsoft.Teams": { - "Level": "info" - } - }, - "AllowedHosts": "*" -} diff --git a/packages/cli/templates/csharp/echo/{{name}}.hbs/appsettings.json b/packages/cli/templates/csharp/echo/{{name}}.hbs/appsettings.json deleted file mode 100644 index 08514a177..000000000 --- a/packages/cli/templates/csharp/echo/{{name}}.hbs/appsettings.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - }, - "Microsoft.Teams": { - "Level": "info" - } - }, - "AllowedHosts": "*" -} diff --git a/packages/cli/templates/csharp/echo/{{name}}.hbs/{{name}}.csproj.hbs b/packages/cli/templates/csharp/echo/{{name}}.hbs/{{name}}.csproj.hbs deleted file mode 100644 index 7787f2116..000000000 --- a/packages/cli/templates/csharp/echo/{{name}}.hbs/{{name}}.csproj.hbs +++ /dev/null @@ -1,18 +0,0 @@ - - - - net10.0 - enable - enable - - - - - - - - - - - - diff --git a/packages/cli/templates/csharp/echo/{{name}}.sln.hbs b/packages/cli/templates/csharp/echo/{{name}}.sln.hbs deleted file mode 100644 index 389b3cc44..000000000 --- a/packages/cli/templates/csharp/echo/{{name}}.sln.hbs +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.14.36017.23 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "{{name}}", "{{name}}\\{{name}}.csproj", "{3DF7DBBF-6757-C96E-D6EC-3928332DA969}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3DF7DBBF-6757-C96E-D6EC-3928332DA969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3DF7DBBF-6757-C96E-D6EC-3928332DA969}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3DF7DBBF-6757-C96E-D6EC-3928332DA969}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3DF7DBBF-6757-C96E-D6EC-3928332DA969}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7F4500E6-9ADE-4E92-BF1B-8B085F426E6E} - EndGlobalSection -EndGlobal diff --git a/packages/cli/templates/csharp/echo/{{name}}.slnlaunch.user.hbs b/packages/cli/templates/csharp/echo/{{name}}.slnlaunch.user.hbs deleted file mode 100644 index fb541d6c0..000000000 --- a/packages/cli/templates/csharp/echo/{{name}}.slnlaunch.user.hbs +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "Name": "DevTools (browser)", - "Projects": [ - { - "Path": "{{name}}\\{{name}}.csproj", - "Action": "Start", - "DebugTarget": "http" - } - ] - } -] \ No newline at end of file diff --git a/packages/cli/templates/python/echo/README.md b/packages/cli/templates/python/echo/README.md deleted file mode 100644 index 341bccba0..000000000 --- a/packages/cli/templates/python/echo/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Python Teams Echo Bot - -This is a minimal Microsoft Teams echo bot template using [microsoft-teams](https://github.com/microsoft/teams.py). - -## Structure - -- `src/main.py`: Main application code for the Teams bot. -- `pyproject.toml`: Project dependencies and metadata. -- `apppackage/`: Teams app manifest and related files. - -## Getting Started - -1. Create a virtual environment: `python -m venv .venv` -2. Activate it: `. .venv/bin/activate` (Unix) or `.venv\Scripts\activate` (Windows) -3. Install dependencies: `pip install -e .` -4. Run the app: `python src/main.py` diff --git a/packages/cli/templates/python/echo/appPackage/color.png b/packages/cli/templates/python/echo/appPackage/color.png deleted file mode 100644 index 4ab158588..000000000 --- a/packages/cli/templates/python/echo/appPackage/color.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:67c7c063ba4dc41c977080c1f1fa17c897e1c72ec4a6412ed5e681b5d4cb9680 -size 1066 diff --git a/packages/cli/templates/python/echo/appPackage/manifest.json.hbs b/packages/cli/templates/python/echo/appPackage/manifest.json.hbs deleted file mode 100644 index 4c97c274d..000000000 --- a/packages/cli/templates/python/echo/appPackage/manifest.json.hbs +++ /dev/null @@ -1,55 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.25/MicrosoftTeams.schema.json", - "version": "1.0.0", - "manifestVersion": "1.25", - "id": "$\{{TEAMS_APP_ID}}", - "name": { - "short": "{{ toKebabCase name }}-$\{{APP_NAME_SUFFIX}}", - "full": "{{ capitalize name }}" - }, - "developer": { - "name": "Microsoft", - "mpnId": "", - "websiteUrl": "https://microsoft.com", - "privacyUrl": "https://privacy.microsoft.com/privacystatement", - "termsOfUseUrl": "https://www.microsoft.com/legal/terms-of-use" - }, - "description": { - "short": "Sample Python bot that repeats back what you say", - "full": "Sample Python bot that repeats back what you say" - }, - "icons": { - "outline": "outline.png", - "color": "color.png" - }, - "accentColor": "#FFFFFF", - "staticTabs": [ - { - "entityId": "conversations", - "scopes": ["personal"] - }, - { - "entityId": "about", - "scopes": ["personal"] - } - ], - "bots": [ - { - "botId": "$\{{BOT_ID}}", - "scopes": ["personal", "team", "groupChat"], - "isNotificationOnly": false, - "supportsCalling": false, - "supportsVideo": false, - "supportsFiles": false - } - ], - "validDomains": [ - "$\{{BOT_DOMAIN}}", - "*.botframework.com" - ], - "webApplicationInfo": { - "id": "$\{{BOT_ID}}", - "resource": "api://botid-$\{{BOT_ID}}" - }, - "supportsChannelFeatures": "tier1" -} diff --git a/packages/cli/templates/python/echo/appPackage/outline.png b/packages/cli/templates/python/echo/appPackage/outline.png deleted file mode 100644 index 458549f6d..000000000 --- a/packages/cli/templates/python/echo/appPackage/outline.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b1ddc76f79027d9c0300689721649ce1f1950271a5fc4ca50ae56545228fb566 -size 249 diff --git a/packages/cli/templates/python/echo/pyproject.toml.hbs b/packages/cli/templates/python/echo/pyproject.toml.hbs deleted file mode 100644 index a698fa58c..000000000 --- a/packages/cli/templates/python/echo/pyproject.toml.hbs +++ /dev/null @@ -1,28 +0,0 @@ -[project] -name = "{{ toKebabCase name }}" -version = "0.1.0" -description = "A Microsoft Teams echo bot" -authors = [{ name = "Your Name", email = "you@example.com" }] -readme = "README.md" -requires-python = ">=3.12" - -dependencies = [ - "dotenv>=0.9.9", - "microsoft-teams-apps" -] - -[dependency-groups] -dev = [ - "pyright>=1.1.406", -] - -[project.scripts] -start = "src.main:main" -typecheck = "pyright.cli:entrypoint" - -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[tool.hatch.build.targets.wheel] -packages = ["src"] diff --git a/packages/cli/templates/python/echo/src/main.py b/packages/cli/templates/python/echo/src/main.py deleted file mode 100644 index 3ac840795..000000000 --- a/packages/cli/templates/python/echo/src/main.py +++ /dev/null @@ -1,32 +0,0 @@ -import asyncio -import re - -from microsoft_teams.api import MessageActivity, TypingActivityInput -from microsoft_teams.apps import ActivityContext, App - -app = App() - - -@app.on_message_pattern(re.compile(r"hello|hi|greetings")) -async def handle_greeting(ctx: ActivityContext[MessageActivity]) -> None: - """Handle greeting messages.""" - await ctx.send("Hello! How can I assist you today?") - - -@app.on_message -async def handle_message(ctx: ActivityContext[MessageActivity]): - """Handle message activities using the new generated handler system.""" - await ctx.reply(TypingActivityInput()) - - if "reply" in ctx.activity.text.lower(): - await ctx.reply("Hello! How can I assist you today?") - else: - await ctx.send(f"You said '{ctx.activity.text}'") - - -def main(): - asyncio.run(app.start()) - - -if __name__ == "__main__": - main() diff --git a/packages/cli/templates/python/graph/README.md b/packages/cli/templates/python/graph/README.md deleted file mode 100644 index c090a6277..000000000 --- a/packages/cli/templates/python/graph/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Python Teams Graph Bot - -This is a minimal Microsoft Teams graph bot template using [microsoft-teams](https://github.com/microsoft/teams.py). - -## Structure - -- `src/main.py`: Main application code for the Teams bot. -- `pyproject.toml`: Project dependencies and metadata. -- `apppackage/`: Teams app manifest and related files. - -## Getting Started - -1. Create a virtual environment: `python -m venv .venv` -2. Activate it: `. .venv/bin/activate` (Unix) or `.venv\Scripts\activate` (Windows) -3. Install dependencies: `pip install -e .` -4. Run the app: `python src/main.py` diff --git a/packages/cli/templates/python/graph/appPackage/color.png b/packages/cli/templates/python/graph/appPackage/color.png deleted file mode 100644 index 4ab158588..000000000 --- a/packages/cli/templates/python/graph/appPackage/color.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:67c7c063ba4dc41c977080c1f1fa17c897e1c72ec4a6412ed5e681b5d4cb9680 -size 1066 diff --git a/packages/cli/templates/python/graph/appPackage/manifest.json.hbs b/packages/cli/templates/python/graph/appPackage/manifest.json.hbs deleted file mode 100644 index 2b757f797..000000000 --- a/packages/cli/templates/python/graph/appPackage/manifest.json.hbs +++ /dev/null @@ -1,55 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.25/MicrosoftTeams.schema.json", - "version": "1.0.0", - "manifestVersion": "1.25", - "id": "$\{{TEAMS_APP_ID}}", - "name": { - "short": "{{ toKebabCase name }}-$\{{APP_NAME_SUFFIX}}", - "full": "{{ capitalize name }}" - }, - "developer": { - "name": "Microsoft", - "mpnId": "", - "websiteUrl": "https://microsoft.com", - "privacyUrl": "https://privacy.microsoft.com/privacystatement", - "termsOfUseUrl": "https://www.microsoft.com/legal/terms-of-use" - }, - "description": { - "short": "Sample Python bot that uses MS Graph", - "full": "Sample Python bot that uses MS Graph" - }, - "icons": { - "outline": "outline.png", - "color": "color.png" - }, - "accentColor": "#FFFFFF", - "staticTabs": [ - { - "entityId": "conversations", - "scopes": ["personal"] - }, - { - "entityId": "about", - "scopes": ["personal"] - } - ], - "bots": [ - { - "botId": "$\{{BOT_ID}}", - "scopes": ["personal", "team", "groupChat"], - "isNotificationOnly": false, - "supportsCalling": false, - "supportsVideo": false, - "supportsFiles": false - } - ], - "validDomains": [ - "$\{{BOT_DOMAIN}}", - "*.botframework.com" - ], - "webApplicationInfo": { - "id": "$\{{BOT_ID}}", - "resource": "api://botid-$\{{BOT_ID}}" - }, - "supportsChannelFeatures": "tier1" -} diff --git a/packages/cli/templates/python/graph/appPackage/outline.png b/packages/cli/templates/python/graph/appPackage/outline.png deleted file mode 100644 index 458549f6d..000000000 --- a/packages/cli/templates/python/graph/appPackage/outline.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b1ddc76f79027d9c0300689721649ce1f1950271a5fc4ca50ae56545228fb566 -size 249 diff --git a/packages/cli/templates/python/graph/pyproject.toml.hbs b/packages/cli/templates/python/graph/pyproject.toml.hbs deleted file mode 100644 index 6cabf67a6..000000000 --- a/packages/cli/templates/python/graph/pyproject.toml.hbs +++ /dev/null @@ -1,27 +0,0 @@ -[project] -name = "{{ toKebabCase name }}" -version = "0.1.0" -description = "A Microsoft Teams bot with Azure Graph integration" -readme = "README.md" -requires-python = ">=3.12" -dependencies = [ - "microsoft-teams-apps", - "microsoft-teams-graph", - "dotenv" -] - -[dependency-groups] -dev = [ - "pyright>=1.1.406", -] - -[project.scripts] -start = "src.main:main" -typecheck = "pyright.cli:entrypoint" - -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[tool.hatch.build.targets.wheel] -packages = ["src"] diff --git a/packages/cli/templates/python/graph/src/main.py b/packages/cli/templates/python/graph/src/main.py deleted file mode 100644 index 7062db5cf..000000000 --- a/packages/cli/templates/python/graph/src/main.py +++ /dev/null @@ -1,89 +0,0 @@ -""" -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the MIT License. -""" - -import asyncio -import logging -import os - -from microsoft_teams.api import MessageActivity -from microsoft_teams.apps import ActivityContext, App, SignInEvent - -logger = logging.getLogger(__name__) - -# Create app with OAuth connection -app = App(default_connection_name=os.getenv("CONNECTION_NAME", "graph")) - - -@app.on_message_pattern("signout") -async def handle_signout_command(ctx: ActivityContext[MessageActivity]): - """Handle sign-out command.""" - if not ctx.is_signed_in: - await ctx.send("ℹ️ You are not currently signed in.") - else: - await ctx.sign_out() - await ctx.send("👋 You have been signed out successfully!") - - -@app.on_message_pattern("profile") -async def handle_profile_command(ctx: ActivityContext[MessageActivity]): - """Handle profile command using Graph API with TokenProtocol pattern.""" - - if not ctx.is_signed_in: - await ctx.send("🔐 Please sign in first to access Microsoft Graph.") - await ctx.sign_in() - return - - graph = ctx.user_graph - # Fetch user profile - me = None - if graph: - me = await graph.me.get() - - if me: - profile_info = ( - f"👤 **Your Profile**\n\n" - f"**Name:** {me.display_name or 'N/A'}\n\n" - f"**Email:** {me.user_principal_name or 'N/A'}\n\n" - f"**Job Title:** {me.job_title or 'N/A'}\n\n" - f"**Department:** {me.department or 'N/A'}\n\n" - f"**Office:** {me.office_location or 'N/A'}" - ) - await ctx.send(profile_info) - else: - await ctx.send("❌ Could not retrieve your profile information.") - - -@app.on_message -async def handle_default_message(ctx: ActivityContext[MessageActivity]): - """Handle default message - trigger signin.""" - if ctx.is_signed_in: - await ctx.send( - "✅ You are already signed in!\n\n" - "You can now use these commands:\n\n" - "• **profile** - View your profile\n\n" - "• **signout** - Sign out when done" - ) - else: - await ctx.send("🔐 Please sign in to access Microsoft Graph...") - await ctx.sign_in() - - -@app.event("sign_in") -async def handle_sign_in_event(event: SignInEvent): - """Handle successful sign-in events.""" - await event.activity_ctx.send( - "✅ **Successfully signed in!**\n\n" - "You can now use these commands:\n\n" - "• **profile** - View your profile\n\n" - "• **signout** - Sign out when done" - ) - - -def main(): - asyncio.run(app.start()) - - -if __name__ == "__main__": - main() diff --git a/packages/cli/templates/typescript/echo/appPackage/color.png b/packages/cli/templates/typescript/echo/appPackage/color.png deleted file mode 100644 index f27ccf203..000000000 Binary files a/packages/cli/templates/typescript/echo/appPackage/color.png and /dev/null differ diff --git a/packages/cli/templates/typescript/echo/appPackage/manifest.json.hbs b/packages/cli/templates/typescript/echo/appPackage/manifest.json.hbs deleted file mode 100644 index ca10dbe80..000000000 --- a/packages/cli/templates/typescript/echo/appPackage/manifest.json.hbs +++ /dev/null @@ -1,55 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.25/MicrosoftTeams.schema.json", - "version": "1.0.0", - "manifestVersion": "1.25", - "id": "$\{{TEAMS_APP_ID}}", - "name": { - "short": "{{ toKebabCase name }}-$\{{APP_NAME_SUFFIX}}", - "full": "{{ capitalize name }}" - }, - "developer": { - "name": "Microsoft", - "mpnId": "", - "websiteUrl": "https://microsoft.com", - "privacyUrl": "https://privacy.microsoft.com/privacystatement", - "termsOfUseUrl": "https://www.microsoft.com/legal/terms-of-use" - }, - "description": { - "short": "Sample bot that repeats back what you say", - "full": "Sample bot that repeats back what you say" - }, - "icons": { - "outline": "outline.png", - "color": "color.png" - }, - "accentColor": "#FFFFFF", - "staticTabs": [ - { - "entityId": "conversations", - "scopes": ["personal"] - }, - { - "entityId": "about", - "scopes": ["personal"] - } - ], - "bots": [ - { - "botId": "$\{{BOT_ID}}", - "scopes": ["personal", "team", "groupChat"], - "isNotificationOnly": false, - "supportsCalling": false, - "supportsVideo": false, - "supportsFiles": false - } - ], - "validDomains": [ - "$\{{BOT_DOMAIN}}", - "*.botframework.com" - ], - "webApplicationInfo": { - "id": "$\{{BOT_ID}}", - "resource": "api://botid-$\{{BOT_ID}}" - }, - "supportsChannelFeatures": "tier1" -} diff --git a/packages/cli/templates/typescript/echo/appPackage/outline.png b/packages/cli/templates/typescript/echo/appPackage/outline.png deleted file mode 100644 index e8cb4b6ba..000000000 Binary files a/packages/cli/templates/typescript/echo/appPackage/outline.png and /dev/null differ diff --git a/packages/cli/templates/typescript/echo/package.json.hbs b/packages/cli/templates/typescript/echo/package.json.hbs deleted file mode 100644 index 9f88590b4..000000000 --- a/packages/cli/templates/typescript/echo/package.json.hbs +++ /dev/null @@ -1,30 +0,0 @@ -{ -"name": "{{ toKebabCase name }}", -"version": "0.0.0", -"license": "MIT", -"private": true, -"main": "dist/index", -"types": "dist/index", -"files": [ -"dist", -"README.md" -], -"scripts": { -"clean": "npx rimraf ./dist", -"build": "npx tsup", -"start": "node .", -"dev": "tsx watch -r dotenv/config src/index.ts" -}, -"dependencies": { -"@microsoft/teams.apps": "latest", -"@microsoft/teams.dev": "latest" -}, -"devDependencies": { -"@types/node": "^22.5.4", -"dotenv": "^16.4.5", -"rimraf": "^6.0.1", -"tsx": "^4.20.6", -"tsup": "^8.4.0", -"typescript": "^5.4.5" -} -} diff --git a/packages/cli/templates/typescript/echo/src/index.ts b/packages/cli/templates/typescript/echo/src/index.ts deleted file mode 100644 index d84554848..000000000 --- a/packages/cli/templates/typescript/echo/src/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { App } from '@microsoft/teams.apps'; -import { DevtoolsPlugin } from '@microsoft/teams.dev'; - -const app = new App({ - plugins: [new DevtoolsPlugin()], -}); - -app.on('message', async ({ send, activity }) => { - await send({ type: 'typing' }); - await send(`you said "${activity.text}"`); -}); - -app.start(process.env.PORT || 3978).catch(console.error); diff --git a/packages/cli/templates/typescript/echo/tsconfig.json b/packages/cli/templates/typescript/echo/tsconfig.json deleted file mode 100644 index 2c188ac0d..000000000 --- a/packages/cli/templates/typescript/echo/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "module": "NodeNext", - "target": "ESNext", - "moduleResolution": "NodeNext", - "strict": true, - "noImplicitAny": true, - "declaration": true, - "inlineSourceMap": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": false, - "resolveJsonModule": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "pretty": true, - "outDir": "dist", - "rootDir": "src", - "types": ["node"] - } -} diff --git a/packages/cli/templates/typescript/echo/tsup.config.js b/packages/cli/templates/typescript/echo/tsup.config.js deleted file mode 100644 index 32277a72f..000000000 --- a/packages/cli/templates/typescript/echo/tsup.config.js +++ /dev/null @@ -1,13 +0,0 @@ -/** @type {import('tsup').Options} */ -module.exports = { - dts: true, - minify: false, - bundle: false, - sourcemap: true, - treeshake: true, - splitting: true, - clean: true, - outDir: 'dist', - entry: ['src/index.ts'], - format: ['cjs'], -}; diff --git a/packages/cli/templates/typescript/graph/appPackage/color.png b/packages/cli/templates/typescript/graph/appPackage/color.png deleted file mode 100644 index 68bbab747..000000000 --- a/packages/cli/templates/typescript/graph/appPackage/color.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a05cfbf7406319002c07f129309d6e49b5b59fc8135f67efb8d0fdccf15cfd82 -size 1065 diff --git a/packages/cli/templates/typescript/graph/appPackage/manifest.json.hbs b/packages/cli/templates/typescript/graph/appPackage/manifest.json.hbs deleted file mode 100644 index 92d686e81..000000000 --- a/packages/cli/templates/typescript/graph/appPackage/manifest.json.hbs +++ /dev/null @@ -1,56 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.25/MicrosoftTeams.schema.json", - "version": "1.0.0", - "manifestVersion": "1.25", - "id": "$\{{TEAMS_APP_ID}}", - "name": { - "short": "{{ toKebabCase name }}-$\{{APP_NAME_SUFFIX}}", - "full": "{{ capitalize name }}" - }, - "developer": { - "name": "Microsoft", - "mpnId": "", - "websiteUrl": "https://microsoft.com", - "privacyUrl": "https://privacy.microsoft.com/privacystatement", - "termsOfUseUrl": "https://www.microsoft.com/legal/terms-of-use" - }, - "description": { - "short": "Sample bot that uses MS Graph", - "full": "Sample bot that uses MS Graph" - }, - "icons": { - "outline": "outline.png", - "color": "color.png" - }, - "accentColor": "#FFFFFF", - "staticTabs": [ - { - "entityId": "conversations", - "scopes": ["personal"] - }, - { - "entityId": "about", - "scopes": ["personal"] - } - ], - "bots": [ - { - "botId": "$\{{BOT_ID}}", - "scopes": ["personal", "team", "groupChat"], - "isNotificationOnly": false, - "supportsCalling": false, - "supportsVideo": false, - "supportsFiles": false - } - ], - "validDomains": [ - "$\{{BOT_DOMAIN}}", - "*.botframework.com" - ], - "permissions": ["identity"], - "webApplicationInfo": { - "id": "$\{{BOT_ID}}", - "resource": "api://botid-$\{{BOT_ID}}" - }, - "supportsChannelFeatures": "tier1" -} diff --git a/packages/cli/templates/typescript/graph/appPackage/outline.png b/packages/cli/templates/typescript/graph/appPackage/outline.png deleted file mode 100644 index ad4eb5e87..000000000 --- a/packages/cli/templates/typescript/graph/appPackage/outline.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d2ca09e4327563f5d4c51c2dd52b4a159741604e3da038003d0d2ace29e3d300 -size 248 diff --git a/packages/cli/templates/typescript/graph/package.json.hbs b/packages/cli/templates/typescript/graph/package.json.hbs deleted file mode 100644 index 17473ba43..000000000 --- a/packages/cli/templates/typescript/graph/package.json.hbs +++ /dev/null @@ -1,33 +0,0 @@ -{ -"name": "{{ toKebabCase name }}", -"version": "0.0.0", -"license": "MIT", -"private": true, -"main": "dist/index", -"types": "dist/index", -"files": [ -"dist", -"README.md" -], -"scripts": { -"clean": "npx rimraf ./dist", -"build": "npx tsup", -"start": "node .", -"dev": "tsx watch -r dotenv/config src/index.ts" -}, -"dependencies": { -"@microsoft/teams.api": "latest", -"@microsoft/teams.apps": "latest", -"@microsoft/teams.cards": "latest", -"@microsoft/teams.dev": "latest", -"@microsoft/teams.graph-endpoints": "latest" -}, -"devDependencies": { -"@types/node": "^22.5.4", -"dotenv": "^16.4.5", -"rimraf": "^6.0.1", -"tsx": "^4.20.6", -"tsup": "^8.4.0", -"typescript": "^5.4.5" -} -} diff --git a/packages/cli/templates/typescript/graph/src/index.ts b/packages/cli/templates/typescript/graph/src/index.ts deleted file mode 100644 index d007226c7..000000000 --- a/packages/cli/templates/typescript/graph/src/index.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { MessageActivity } from '@microsoft/teams.api'; -import { App } from '@microsoft/teams.apps'; -import { AdaptiveCard, CodeBlock } from '@microsoft/teams.cards'; -import { DevtoolsPlugin } from '@microsoft/teams.dev'; -import * as endpoints from '@microsoft/teams.graph-endpoints'; - -const app = new App({ - plugins: [new DevtoolsPlugin()], - oauth: { - defaultConnectionName: 'graph' - }, -}); - -app.message('/signout', async ({ send, signout, isSignedIn }) => { - if (!isSignedIn) return; - await signout(); // call signout for your auth connection... - await send('you have been signed out!'); -}); - - -app.on('message', async ({ log, signin, isSignedIn }) => { - if (!isSignedIn) { - await signin(); - return; - } - - log.info('user already signed in!'); -}); - -app.event('signin', async ({ send, userGraph }) => { - const me = await userGraph.call(endpoints.me.get); - - await send( - new MessageActivity(`hello ${me.displayName} 👋!`).addCard( - 'adaptive', - new AdaptiveCard( - new CodeBlock({ - codeSnippet: JSON.stringify(me, null, 2), - }) - ) - ) - ); -}); - -app.on('signin.failure', async ({ activity, log, send }) => { - const { code, message } = activity.value; - log.error(`sign-in failed: ${code} - ${message}`); - await send('Sign-in failed.'); -}); - -app.start(process.env.PORT || 3978).catch(console.error); diff --git a/packages/cli/templates/typescript/graph/tsconfig.json b/packages/cli/templates/typescript/graph/tsconfig.json deleted file mode 100644 index 2c188ac0d..000000000 --- a/packages/cli/templates/typescript/graph/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "module": "NodeNext", - "target": "ESNext", - "moduleResolution": "NodeNext", - "strict": true, - "noImplicitAny": true, - "declaration": true, - "inlineSourceMap": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": false, - "resolveJsonModule": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "pretty": true, - "outDir": "dist", - "rootDir": "src", - "types": ["node"] - } -} diff --git a/packages/cli/templates/typescript/graph/tsup.config.js b/packages/cli/templates/typescript/graph/tsup.config.js deleted file mode 100644 index 32277a72f..000000000 --- a/packages/cli/templates/typescript/graph/tsup.config.js +++ /dev/null @@ -1,13 +0,0 @@ -/** @type {import('tsup').Options} */ -module.exports = { - dts: true, - minify: false, - bundle: false, - sourcemap: true, - treeshake: true, - splitting: true, - clean: true, - outDir: 'dist', - entry: ['src/index.ts'], - format: ['cjs'], -}; diff --git a/packages/cli/templates/typescript/tab/appPackage/color.png b/packages/cli/templates/typescript/tab/appPackage/color.png deleted file mode 100644 index f27ccf203..000000000 Binary files a/packages/cli/templates/typescript/tab/appPackage/color.png and /dev/null differ diff --git a/packages/cli/templates/typescript/tab/appPackage/manifest.json.hbs b/packages/cli/templates/typescript/tab/appPackage/manifest.json.hbs deleted file mode 100644 index 9e1c1b95e..000000000 --- a/packages/cli/templates/typescript/tab/appPackage/manifest.json.hbs +++ /dev/null @@ -1,63 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.25/MicrosoftTeams.schema.json", - "version": "1.0.0", - "manifestVersion": "1.25", - "id": "$\{{TEAMS_APP_ID}}", - "name": { - "short": "{{ toKebabCase name }}-$\{{APP_NAME_SUFFIX}}", - "full": "{{ capitalize name }}" - }, - "developer": { - "name": "Microsoft", - "mpnId": "", - "websiteUrl": "https://microsoft.com", - "privacyUrl": "https://privacy.microsoft.com/privacystatement", - "termsOfUseUrl": "https://www.microsoft.com/legal/terms-of-use" - }, - "description": { - "short": "Sample bot with a tab", - "full": "Sample bot with a tab" - }, - "icons": { - "outline": "outline.png", - "color": "color.png" - }, - "accentColor": "#FFFFFF", - "staticTabs": [ - { - "entityId": "conversations", - "scopes": ["personal"] - }, - { - "entityId": "about", - "scopes": ["personal"] - }, - { - "entityId": "test", - "name": "Test", - "contentUrl": "https://$\{{BOT_DOMAIN}}/tabs/test", - "websiteUrl": "https://$\{{BOT_DOMAIN}}/tabs/test", - "scopes": ["personal", "team"] - } - ], - "bots": [ - { - "botId": "$\{{BOT_ID}}", - "scopes": ["personal", "team", "groupChat"], - "isNotificationOnly": false, - "supportsCalling": false, - "supportsVideo": false, - "supportsFiles": false - } - ], - "validDomains": [ - "$\{{BOT_DOMAIN}}", - "*.botframework.com" - ], - "permissions": ["identity"], - "webApplicationInfo": { - "id": "$\{{BOT_ID}}", - "resource": "api://botid-$\{{BOT_ID}}" - }, - "supportsChannelFeatures": "tier1" -} diff --git a/packages/cli/templates/typescript/tab/appPackage/outline.png b/packages/cli/templates/typescript/tab/appPackage/outline.png deleted file mode 100644 index e8cb4b6ba..000000000 Binary files a/packages/cli/templates/typescript/tab/appPackage/outline.png and /dev/null differ diff --git a/packages/cli/templates/typescript/tab/index.html.hbs b/packages/cli/templates/typescript/tab/index.html.hbs deleted file mode 100644 index 09d286c80..000000000 --- a/packages/cli/templates/typescript/tab/index.html.hbs +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - {{ capitalize name }} - - - -
- - - diff --git a/packages/cli/templates/typescript/tab/nodemon.json b/packages/cli/templates/typescript/tab/nodemon.json deleted file mode 100644 index 521eaa9d7..000000000 --- a/packages/cli/templates/typescript/tab/nodemon.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/SchemaStore/schemastore/refs/heads/master/src/schemas/json/nodemon.json", - "watch": ["./src/**"], - "ext": "ts,tsx", - "ignore": ["node_modules"], - "delay": 2, - "exec": "npm run build && npm start" -} diff --git a/packages/cli/templates/typescript/tab/package.json.hbs b/packages/cli/templates/typescript/tab/package.json.hbs deleted file mode 100644 index a6942ba57..000000000 --- a/packages/cli/templates/typescript/tab/package.json.hbs +++ /dev/null @@ -1,39 +0,0 @@ -{ -"name": "{{ toKebabCase name }}", -"version": "0.0.0", -"license": "MIT", -"private": true, -"main": "dist/index", -"types": "dist/index", -"files": [ -"dist", -"README.md" -], -"scripts": { -"clean": "npx rimraf ./dist", -"start": "node -r dotenv/config .", -"dev": "npx nodemon", -"build": "npx tsup && npm run build:client", -"build:client": "npx vite build --outDir dist/client" -}, -"dependencies": { -"@microsoft/teams-js": "^2.35.0", -"@microsoft/teams.apps": "latest", -"@microsoft/teams.client": "latest", -"@microsoft/teams.common": "latest", -"@microsoft/teams.dev": "latest", -"@microsoft/teams.graph-endpoints": "latest", -"react": "^19.2.1", -"react-dom": "^19.2.1" -}, -"devDependencies": { -"@types/node": "^22.5.4", -"@vitejs/plugin-react": "^4.3.4", -"dotenv": "^16.4.5", -"nodemon": "^3.1.4", -"rimraf": "^6.0.1", -"tsup": "^8.4.0", -"typescript": "^5.4.5", -"vite": "^6.2.0" -} -} \ No newline at end of file diff --git a/packages/cli/templates/typescript/tab/src/Tab/App.css b/packages/cli/templates/typescript/tab/src/Tab/App.css deleted file mode 100644 index 4d4a5b580..000000000 --- a/packages/cli/templates/typescript/tab/src/Tab/App.css +++ /dev/null @@ -1,43 +0,0 @@ -body { - margin: 0px; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, "Apple Color Emoji", "Segoe UI Emoji", sans-serif; -} - -a { - color: white; -} - -h1 { - font-size: 3rem; -} - -.App { - color: white; - background-color: #282c34; - display: flex; - flex-direction: column; - row-gap: 1rem; - justify-content: start; - align-items: center; - height: 100vh; - overflow: hidden auto; -} - -.App > * { - max-width: calc(100% - 4rem); -} - -.actions { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - column-gap: 1rem; -} - -.result { - color: white; - background-color: black; - padding: 0 1rem; - overflow: auto; -} diff --git a/packages/cli/templates/typescript/tab/src/Tab/App.tsx b/packages/cli/templates/typescript/tab/src/Tab/App.tsx deleted file mode 100644 index a5f636094..000000000 --- a/packages/cli/templates/typescript/tab/src/Tab/App.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import React from 'react'; -import * as client from '@microsoft/teams.client'; -import { ConsoleLogger } from '@microsoft/teams.common'; -import * as endpoints from '@microsoft/teams.graph-endpoints'; -import * as teamsJs from '@microsoft/teams-js'; - -import './App.css'; - -const clientId = import.meta.env.VITE_CLIENT_ID; - -export default function App() { - const [content, setContent] = React.useState(''); - const [app, setApp] = React.useState(null); - - React.useEffect(() => { - // initialize the app and prompt for Graph scope consent, if not already granted - const app = new client.App(clientId, { - logger: new ConsoleLogger('@tests/tab', { level: 'debug' }), - msalOptions: { - prewarmScopes: ['User.Read', 'Presence.ReadWrite', 'Team.ReadBasic.All'] - } - }); - - app.start().then(() => { - app.log.info('app started'); - setApp(app); - }).catch(console.error); - }, []); - - const showTeamsJsContext = React.useCallback(async () => { - if (!app) { - return; - } - - const context = await teamsJs.app.getContext(); - setContent(JSON.stringify(context, null, 2)); - }, [app]); - - - const postChatMessage = React.useCallback(async () => { - if (!app) { - return; - } - - // get the bot to post a message to the current chat, whichever that is - const { conversationId } = await app.exec<{ conversationId: string }>('post-to-chat', { message: 'Hello from the client!' }); - setContent(`Message posted to conversation ${conversationId}`); - }, [app]); - - - const whoAmI = React.useCallback(async () => { - if (!app) { - return; - } - - // get the current user from the Microsoft Graph - const me = await app.graph.call(endpoints.me.get); - setContent(JSON.stringify(me, null, 2)); - }, [app]); - - - const togglePresentationMode = React.useCallback(async () => { - if (!app) { - return; - } - - // get current presence from the Microsoft Graph - const { availability } = await app.graph.call(endpoints.me.presence.get); - const isAvailable = availability === 'Available'; - - // toggle between Dnd/Presenting and Available/Available - const newPresence = { - sessionId: clientId, - availability: isAvailable ? 'DoNotDisturb' : 'Available', - activity: isAvailable ? 'Presenting' : 'Available' - }; - await app.graph.call(endpoints.me.presence.setPresence.create, newPresence); - setContent(`You're now ${newPresence.activity}`); - - }, [app]); - - return ( -
-

👋 Welcome

-

This test app lets you try out some of the features offered by Teams SDK for Teams Tab app developers.

- -
- - - - -
- - {content && ( -
-
-            {content}
-          
-
- )} - -

For more information, please refer to the Teams SDK documentation.

-
- ); -} diff --git a/packages/cli/templates/typescript/tab/src/Tab/client.tsx b/packages/cli/templates/typescript/tab/src/Tab/client.tsx deleted file mode 100644 index b9f4b6f3f..000000000 --- a/packages/cli/templates/typescript/tab/src/Tab/client.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { StrictMode } from 'react'; -import { createRoot } from 'react-dom/client'; - -import App from './App'; - -createRoot(document.getElementById('root')!).render( - - - -); diff --git a/packages/cli/templates/typescript/tab/src/Tab/vite-env.d.ts b/packages/cli/templates/typescript/tab/src/Tab/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/packages/cli/templates/typescript/tab/src/Tab/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/packages/cli/templates/typescript/tab/src/index.ts b/packages/cli/templates/typescript/tab/src/index.ts deleted file mode 100644 index 3e2d8c479..000000000 --- a/packages/cli/templates/typescript/tab/src/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import path from 'path'; - -import { App } from '@microsoft/teams.apps'; -import { ConsoleLogger } from '@microsoft/teams.common'; -import { DevtoolsPlugin } from '@microsoft/teams.dev'; - -const app = new App({ - logger: new ConsoleLogger('@tests/tab', { level: 'debug' }), - plugins: [new DevtoolsPlugin()], -}); - -app.tab('test', path.resolve('dist/client')); - -app.function<{}, { message: string }>( - 'post-to-chat', - async ({ data, send, getCurrentConversationId }) => { - // post to the current conversation; return the conversation ID to the caller - await send(data.message); - return { - conversationId: await getCurrentConversationId(), - }; - }, -); - -app.on('message', async ({ activity, reply }) => { - // simple echo bot - reply(`You said: ${activity.text}`); -}); - -app.start(process.env.PORT || 3978).catch(console.error); diff --git a/packages/cli/templates/typescript/tab/tsconfig.app.json b/packages/cli/templates/typescript/tab/tsconfig.app.json deleted file mode 100644 index 9420f440d..000000000 --- a/packages/cli/templates/typescript/tab/tsconfig.app.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true, - "forceConsistentCasingInFileNames": false - }, - "include": ["src/Tab"] -} diff --git a/packages/cli/templates/typescript/tab/tsconfig.json b/packages/cli/templates/typescript/tab/tsconfig.json deleted file mode 100644 index d32ff6820..000000000 --- a/packages/cli/templates/typescript/tab/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "files": [], - "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }] -} diff --git a/packages/cli/templates/typescript/tab/tsconfig.node.json b/packages/cli/templates/typescript/tab/tsconfig.node.json deleted file mode 100644 index c4efba63c..000000000 --- a/packages/cli/templates/typescript/tab/tsconfig.node.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "module": "NodeNext", - "target": "ESNext", - "moduleResolution": "NodeNext", - "strict": true, - "noImplicitAny": true, - "declaration": true, - "inlineSourceMap": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": false, - "resolveJsonModule": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "pretty": true, - "outDir": "dist", - "rootDir": "src", - "types": ["node"] - }, - "ts-node": { - "transpileOnly": true - } -} diff --git a/packages/cli/templates/typescript/tab/tsup.config.js b/packages/cli/templates/typescript/tab/tsup.config.js deleted file mode 100644 index dd684244f..000000000 --- a/packages/cli/templates/typescript/tab/tsup.config.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @type {import('tsup').Options} - */ -module.exports = { - dts: true, - minify: false, - bundle: false, - sourcemap: true, - treeshake: true, - splitting: true, - clean: true, - outDir: 'dist', - format: ['cjs', 'esm'], - entry: ['src/index.ts'], - tsconfig: 'tsconfig.node.json', -}; diff --git a/packages/cli/templates/typescript/tab/vite.config.js b/packages/cli/templates/typescript/tab/vite.config.js deleted file mode 100644 index 4ae280b1b..000000000 --- a/packages/cli/templates/typescript/tab/vite.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import fs from 'fs'; -import { defineConfig } from 'vite'; -import react from '@vitejs/plugin-react'; - -export default defineConfig({ - plugins: [react()], - base: '/tabs/test', - esbuild: { - tsconfigRaw: fs.readFileSync('./tsconfig.app.json', 'utf8'), - }, -}); diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json deleted file mode 100644 index 55c9bb095..000000000 --- a/packages/cli/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "@microsoft/teams.config/tsconfig.esm.json", - "compilerOptions": { - "outDir": "dist", - "rootDir": "src" - }, - "include": ["src/**/*.ts"], - "exclude": ["src/**/*.spec.ts"] -} diff --git a/packages/cli/tsup.config.js b/packages/cli/tsup.config.js deleted file mode 100644 index cc8596e99..000000000 --- a/packages/cli/tsup.config.js +++ /dev/null @@ -1,11 +0,0 @@ -const base = require('@microsoft/teams.config/tsup.config'); - -/** - * @type {import('tsup').Options} - */ -module.exports = { - ...base, - minify: true, - bundle: true, - entry: ['src/index.ts'], -}; diff --git a/packages/cli/turbo.json b/packages/cli/turbo.json deleted file mode 100644 index 624837986..000000000 --- a/packages/cli/turbo.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": ["//"], - "tasks": { - "build": { - "inputs": ["$TURBO_DEFAULT$", ".env*"], - "outputs": [".next/**", "!.next/cache/**"], - "cache": false, - "dependsOn": [ - "@microsoft/teams.ai#build", - "@microsoft/teams.common#build", - "@microsoft/teams.openai#build" - ] - } - } -} diff --git a/turbo/generators/templates/examples/README.md.hbs b/turbo/generators/templates/examples/README.md.hbs index 8cec62130..98cf1b998 100644 --- a/turbo/generators/templates/examples/README.md.hbs +++ b/turbo/generators/templates/examples/README.md.hbs @@ -13,12 +13,20 @@ npm install ``` -To run on teams, run: +## Teams CLI + +Use the official Teams CLI (`@microsoft/teams.cli`) to create and manage the Teams app for this sample: ```bash -npx @microsoft/teams.cli config add atk.basic +npm install -g @microsoft/teams.cli +teams --version +teams login ``` -This will add all the atk related configs. +Expose this sample's local `/api/messages` endpoint with a tunnel, then create the Teams app: + +```bash +teams app create --name "{{name}}" --endpoint "https:///api/messages" --env .env --json +``` -Then run the sample via atk. +The CLI writes `CLIENT_ID`, `CLIENT_SECRET`, and `TENANT_ID` to your `.env` file and prints an install link for Teams.