@ekanos/cli 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/README.md +25 -8
  2. package/dist/agents-api.d.ts +11 -2
  3. package/dist/agents-api.js +39 -3
  4. package/dist/agents-api.js.map +1 -1
  5. package/dist/apps-api.js +2 -2
  6. package/dist/apps-api.js.map +1 -1
  7. package/dist/auth/ekanos-api.d.ts +16 -2
  8. package/dist/auth/ekanos-api.js +101 -15
  9. package/dist/auth/ekanos-api.js.map +1 -1
  10. package/dist/auth/host-trust.d.ts +46 -0
  11. package/dist/auth/host-trust.js +79 -0
  12. package/dist/auth/host-trust.js.map +1 -0
  13. package/dist/auth/session.d.ts +10 -1
  14. package/dist/auth/session.js +28 -28
  15. package/dist/auth/session.js.map +1 -1
  16. package/dist/commands/agents-edit.d.ts +6 -2
  17. package/dist/commands/agents-edit.js +57 -26
  18. package/dist/commands/agents-edit.js.map +1 -1
  19. package/dist/commands/agents.d.ts +13 -2
  20. package/dist/commands/agents.js +140 -35
  21. package/dist/commands/agents.js.map +1 -1
  22. package/dist/commands/apps.d.ts +2 -0
  23. package/dist/commands/apps.js +16 -12
  24. package/dist/commands/apps.js.map +1 -1
  25. package/dist/commands/catalog.js +7 -6
  26. package/dist/commands/catalog.js.map +1 -1
  27. package/dist/commands/knowledge.d.ts +19 -0
  28. package/dist/commands/knowledge.js +119 -27
  29. package/dist/commands/knowledge.js.map +1 -1
  30. package/dist/commands/login.d.ts +4 -0
  31. package/dist/commands/login.js +30 -2
  32. package/dist/commands/login.js.map +1 -1
  33. package/dist/commands/logout.d.ts +9 -1
  34. package/dist/commands/logout.js +56 -7
  35. package/dist/commands/logout.js.map +1 -1
  36. package/dist/commands/publish.js +3 -3
  37. package/dist/commands/publish.js.map +1 -1
  38. package/dist/commands/reviewers.d.ts +2 -0
  39. package/dist/commands/reviewers.js +7 -3
  40. package/dist/commands/reviewers.js.map +1 -1
  41. package/dist/commands/routes.d.ts +2 -0
  42. package/dist/commands/routes.js +42 -9
  43. package/dist/commands/routes.js.map +1 -1
  44. package/dist/commands/runs.d.ts +13 -2
  45. package/dist/commands/runs.js +99 -16
  46. package/dist/commands/runs.js.map +1 -1
  47. package/dist/commands/scope-notice.d.ts +21 -0
  48. package/dist/commands/scope-notice.js +35 -0
  49. package/dist/commands/scope-notice.js.map +1 -0
  50. package/dist/commands/skills.d.ts +7 -1
  51. package/dist/commands/skills.js +80 -24
  52. package/dist/commands/skills.js.map +1 -1
  53. package/dist/commands/sources.d.ts +1 -1
  54. package/dist/commands/sources.js +126 -12
  55. package/dist/commands/sources.js.map +1 -1
  56. package/dist/commands/status.js +5 -4
  57. package/dist/commands/status.js.map +1 -1
  58. package/dist/commands/team-agent-readiness.d.ts +49 -0
  59. package/dist/commands/team-agent-readiness.js +308 -0
  60. package/dist/commands/team-agent-readiness.js.map +1 -0
  61. package/dist/commands/team-agents-agents.d.ts +24 -3
  62. package/dist/commands/team-agents-agents.js +314 -35
  63. package/dist/commands/team-agents-agents.js.map +1 -1
  64. package/dist/commands/team-agents-mcp.js +32 -3
  65. package/dist/commands/team-agents-mcp.js.map +1 -1
  66. package/dist/commands/team-agents-triggers.js +230 -55
  67. package/dist/commands/team-agents-triggers.js.map +1 -1
  68. package/dist/commands/team-agents.d.ts +3 -1
  69. package/dist/commands/team-agents.js +27 -7
  70. package/dist/commands/team-agents.js.map +1 -1
  71. package/dist/commands/teams-channel-install.d.ts +24 -0
  72. package/dist/commands/teams-channel-install.js +94 -0
  73. package/dist/commands/teams-channel-install.js.map +1 -0
  74. package/dist/commands/teams-connect.d.ts +41 -0
  75. package/dist/commands/teams-connect.js +212 -57
  76. package/dist/commands/teams-connect.js.map +1 -1
  77. package/dist/commands/teams-events.d.ts +12 -0
  78. package/dist/commands/teams-events.js +138 -0
  79. package/dist/commands/teams-events.js.map +1 -0
  80. package/dist/commands/teams-onboard.d.ts +11 -3
  81. package/dist/commands/teams-onboard.js +60 -7
  82. package/dist/commands/teams-onboard.js.map +1 -1
  83. package/dist/commands/teams-overview.d.ts +11 -0
  84. package/dist/commands/teams-overview.js +160 -0
  85. package/dist/commands/teams-overview.js.map +1 -0
  86. package/dist/commands/teams-scope.d.ts +10 -0
  87. package/dist/commands/teams-scope.js +109 -0
  88. package/dist/commands/teams-scope.js.map +1 -0
  89. package/dist/commands/teams.d.ts +4 -2
  90. package/dist/commands/teams.js +113 -14
  91. package/dist/commands/teams.js.map +1 -1
  92. package/dist/commands/upgrade.js +12 -2
  93. package/dist/commands/upgrade.js.map +1 -1
  94. package/dist/commands/use.js +2 -2
  95. package/dist/commands/use.js.map +1 -1
  96. package/dist/commands/whoami.js +1 -1
  97. package/dist/commands/whoami.js.map +1 -1
  98. package/dist/connections-api.js +1 -1
  99. package/dist/connections-api.js.map +1 -1
  100. package/dist/delegate.js +11 -4
  101. package/dist/delegate.js.map +1 -1
  102. package/dist/harness-scaffold.js +12 -0
  103. package/dist/harness-scaffold.js.map +1 -1
  104. package/dist/index.d.ts +6 -0
  105. package/dist/index.js +682 -167
  106. package/dist/index.js.map +1 -1
  107. package/dist/knowledge-api.d.ts +46 -0
  108. package/dist/knowledge-api.js +32 -1
  109. package/dist/knowledge-api.js.map +1 -1
  110. package/dist/open-url.d.ts +16 -0
  111. package/dist/open-url.js +73 -0
  112. package/dist/open-url.js.map +1 -0
  113. package/dist/parse-argv.d.ts +2 -0
  114. package/dist/parse-argv.js.map +1 -1
  115. package/dist/publish-api.d.ts +2 -1
  116. package/dist/publish-api.js +4 -3
  117. package/dist/publish-api.js.map +1 -1
  118. package/dist/pull-write.d.ts +27 -0
  119. package/dist/pull-write.js +60 -0
  120. package/dist/pull-write.js.map +1 -0
  121. package/dist/routes-api.d.ts +3 -0
  122. package/dist/routes-api.js +9 -4
  123. package/dist/routes-api.js.map +1 -1
  124. package/dist/runs-api.d.ts +7 -1
  125. package/dist/runs-api.js +21 -6
  126. package/dist/runs-api.js.map +1 -1
  127. package/dist/safe-fs.d.ts +2 -0
  128. package/dist/safe-fs.js +12 -6
  129. package/dist/safe-fs.js.map +1 -1
  130. package/dist/secret-file.d.ts +17 -0
  131. package/dist/secret-file.js +69 -0
  132. package/dist/secret-file.js.map +1 -0
  133. package/dist/skills-api.d.ts +10 -2
  134. package/dist/skills-api.js +37 -2
  135. package/dist/skills-api.js.map +1 -1
  136. package/dist/source-products-api.d.ts +4 -0
  137. package/dist/source-products-api.js +14 -4
  138. package/dist/source-products-api.js.map +1 -1
  139. package/dist/source-target.js +2 -1
  140. package/dist/source-target.js.map +1 -1
  141. package/dist/sources-api.d.ts +2 -1
  142. package/dist/sources-api.js +3 -2
  143. package/dist/sources-api.js.map +1 -1
  144. package/dist/team-connect-api.d.ts +44 -2
  145. package/dist/team-connect-api.js +19 -7
  146. package/dist/team-connect-api.js.map +1 -1
  147. package/dist/teams-api.d.ts +41 -1
  148. package/dist/teams-api.js +95 -19
  149. package/dist/teams-api.js.map +1 -1
  150. package/dist/toolchain-api.d.ts +9 -0
  151. package/dist/toolchain-api.js +17 -2
  152. package/dist/toolchain-api.js.map +1 -1
  153. package/dist/toolchain-resolve.d.ts +3 -0
  154. package/dist/toolchain-resolve.js +15 -1
  155. package/dist/toolchain-resolve.js.map +1 -1
  156. package/dist/toolchain.d.ts +6 -0
  157. package/dist/toolchain.js +19 -0
  158. package/dist/toolchain.js.map +1 -1
  159. package/dist/update-notice.js +2 -1
  160. package/dist/update-notice.js.map +1 -1
  161. package/package.json +2 -2
  162. package/templates/AGENTS.md.tmpl +6 -1
  163. package/templates/claude-skill.md.tmpl +5 -0
  164. package/templates/package.json.tmpl +4 -4
  165. package/templates/skills/build-agent/SKILL.md +104 -17
  166. package/templates/skills/build-agent/references/agent-json.md +4 -2
  167. package/templates/skills/build-agent/references/rollout.md +23 -4
  168. package/templates/skills/build-agent/references/set-up-an-integration.md +55 -7
  169. package/templates/skills/build-agent/references/skills.md +20 -1
  170. package/templates/skills/build-agent/references/triggers.md +47 -11
  171. package/templates/skills/build-integration/references/widget-design.md +3 -3
  172. package/templates/skills/ekanos-platform/SKILL.md +45 -16
  173. package/templates/skills/polish-widgets/references/patterns.md +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"teams-connect.js","sourceRoot":"","sources":["../../src/commands/teams-connect.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from 'node:child_process';\n\nimport type { CliContext } from '../context';\nimport { invalidStateError, usageError, validationError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport {\n type TeamConnectPlan,\n showTeamConnect,\n startTeamConnect,\n} from '../team-connect-api';\nimport { showTeamIntegration } from '../teams-api';\nimport type { ResultRow } from '../ui';\nimport { promptHidden, promptLine } from './apps';\nimport {\n type TeamsArgs,\n type TeamsClient,\n canPrompt,\n checklist,\n promptAndSaveTeamApp,\n} from './teams';\n\n/**\n * `teams connect <team> <product>` — connect a product for one team, doing\n * whichever the integration needs (the host's plan decides, never the CLI):\n *\n * - works as shipped → says so; not self-serve or not enabled → refuses\n * with the reason (and points at `sources products` for the latter);\n * - form fields → asks them here (secrets hidden, never as arguments) and\n * activates exactly as the app's form does;\n * - OAuth → runs `teams app set` inline when the team's own app is needed\n * first (Zendesk), then a one-time sign-in link for the member who\n * consents: the caller when a member, else `--as <email>`. Opens it for\n * the caller (unless `--no-open`), always prints it, and waits until the\n * team is connected (unless `--no-wait`);\n * - a form only the browser can fill → prints the team's page.\n *\n * `--link-only` keeps the old behaviour: the team's page and its status.\n */\nexport async function runTeamConnect(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n source: string,\n input: { team: string; product: string; as?: string },\n): Promise<ExitCode> {\n const target = { source, team: input.team, product: input.product };\n\n if (args.linkOnly) return printLink(ctx, client, host, target);\n\n const { plan } = await client.call((token) =>\n showTeamConnect(host, token, target, input.as),\n );\n const name = plan.product.name;\n\n switch (plan.mode) {\n case 'not-entitled':\n throw invalidStateError(\n plan.reason ??\n `\"${input.product}\" is not enabled on ${plan.source.slug}.`,\n `A super-admin enables it for the Source first (\"ekanos sources products\" shows what ${plan.source.slug} has; \"ekanos sources products enable ${input.product}\" from a super-admin session, or /admin in the browser).`,\n );\n case 'not-self-serve':\n throw invalidStateError(\n plan.reason ?? `${name} is not connected by a team.`,\n plan.product.kind === 'experience'\n ? `\"ekanos sources products --source ${plan.source.slug}\" shows whether it is on for the Source.`\n : 'It is turned on for the Source by Ekanos; there is nothing for the team to do.',\n );\n case 'unsupported':\n throw invalidStateError(\n plan.reason ?? `${name} cannot be connected from here.`,\n `Open the team's page instead: ${plan.connectUrl}`,\n );\n case 'works-as-shipped':\n return ctx.succeed(\n { host, plan, connected: true },\n ctx.ui.result({\n title: `${name} works as shipped for ${plan.team.slug}`,\n rows: [['Status', 'nothing to connect']],\n }),\n );\n case 'browser':\n return ctx.succeed(\n { host, plan, connected: plan.connected },\n ctx.ui.result({\n title: plan.connected\n ? `${plan.team.slug} has connected ${name}`\n : `${name} connects in the app for ${plan.team.slug}`,\n tone: plan.connected ? 'ok' : 'warn',\n rows: [\n ['Open', plan.connectUrl],\n ['Status', statusOf(plan)],\n ],\n notes: plan.connected\n ? []\n : [\n plan.reason ??\n `${name} connects through its own form in the app.`,\n 'A team admin signs in there and clicks Connect.',\n ],\n }),\n );\n default:\n break;\n }\n\n if (plan.connected) {\n return ctx.succeed(\n { host, plan, connected: true },\n ctx.ui.result({\n title: `${plan.team.slug} has already connected ${name}`,\n rows: [\n ['Status', statusOf(plan)],\n ['Team page', plan.connectUrl],\n ],\n notes: [\n `\"ekanos teams show ${plan.team.slug} ${plan.product.slug}\" shows the full setup.`,\n ],\n }),\n );\n }\n\n if (plan.mode === 'fields' || plan.mode === 'no-fields') {\n return activate(ctx, args, client, host, target, plan);\n }\n return connectOAuth(ctx, args, client, host, target, plan, input.as);\n}\n\nasync function activate(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n target: { source: string; team: string; product: string },\n plan: TeamConnectPlan,\n): Promise<ExitCode> {\n if (plan.scope === 'user' && !plan.member) {\n throw invalidStateError(\n plan.memberProblem ??\n `${plan.product.name} is a personal connection: each member connects their own.`,\n `A member connects it for themselves on the team's page: ${plan.connectUrl}`,\n );\n }\n\n const fields: Record<string, string> = {};\n if (plan.mode === 'fields') {\n if (!canPrompt(ctx, args)) {\n throw usageError(\n `${plan.product.name} needs its fields typed at a terminal (${plan.fields.map((field) => field.label).join(', ')}), never in a script or an agent run.`,\n `Run it yourself in your terminal: npx @ekanos/cli teams connect ${target.team} ${target.product} --source ${plan.source.slug}`,\n );\n }\n ctx.log(\n `${plan.product.name} for ${plan.scope === 'user' ? 'you, in' : 'team'} ${plan.team.slug}: enter what the app's form asks. Secrets are hidden and never shown again.`,\n );\n for (const field of plan.fields) {\n if (field.description) ctx.log(` ${field.description}`);\n const suffix = `${field.required ? '' : ' (optional — Enter skips)'}${field.sensitive ? ' (hidden)' : ''}: `;\n const value = (\n await (\n field.sensitive\n ? (args.askSecret ?? promptHidden)\n : (args.ask ?? promptLine)\n )(`${field.label}${suffix}`)\n ).trim();\n if (value) fields[field.name] = value;\n else if (field.required) {\n throw validationError(\n `${field.label} is needed.`,\n `Run \"ekanos teams connect ${target.team} ${target.product}\" again.`,\n );\n }\n }\n }\n\n const started = await client.call((token) =>\n startTeamConnect(host, token, target, { fields }),\n );\n return ctx.succeed(\n { host, ...started, connected: started.plan.connected },\n ctx.ui.result({\n title: `Connected ${started.plan.product.name} for ${started.plan.team.slug}`,\n rows: [\n ['Status', statusOf(started.plan)],\n [\n 'For',\n started.plan.scope === 'user'\n ? `you (${started.plan.member?.email ?? 'your account'}) — a personal connection`\n : 'the whole team',\n ],\n ['Team page', started.plan.connectUrl],\n ],\n }),\n );\n}\n\nasync function connectOAuth(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n target: { source: string; team: string; product: string },\n plan: TeamConnectPlan,\n asEmail: string | undefined,\n): Promise<ExitCode> {\n if (!plan.member) {\n throw invalidStateError(\n plan.memberProblem ?? 'No member of the team can sign in yet.',\n `Name a member of ${plan.team.slug} who signs in: ekanos teams connect ${target.team} ${target.product} --as <email>`,\n );\n }\n\n if (plan.teamApp) {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n const app =\n status.teamApps.find((entry) => entry.connectionId === 'default') ??\n status.teamApps[0];\n if (app && app.fields.some((field) => !field.set)) {\n if (!canPrompt(ctx, args)) {\n throw usageError(\n `${plan.product.name} needs ${plan.team.slug}'s own app first, entered at a terminal.`,\n `Run it yourself in your terminal: npx @ekanos/cli teams connect ${target.team} ${target.product} --source ${plan.source.slug}`,\n );\n }\n ctx.log(\n `${plan.product.name} signs ${plan.team.slug} in through the team's own app. Set it up first:`,\n );\n await promptAndSaveTeamApp(ctx, args, client, host, target, status, app);\n }\n }\n\n const started = await client.call((token) =>\n startTeamConnect(host, token, target, asEmail ? { as: asEmail } : {}),\n );\n if (started.result !== 'consent') {\n throw invalidStateError(\n `The host answered \"${started.result}\" where a sign-in link was expected.`,\n 'Run \"ekanos upgrade\" — the CLI and the host disagree on the connect contract.',\n );\n }\n\n const member = started.plan.member ?? plan.member;\n const forCaller = member.isCaller;\n const expires = started.expiresAt.replace('T', ' ').slice(0, 16);\n ctx.log(\n forCaller\n ? [\n `Sign in to ${plan.product.name} as the account ${plan.team.slug} should use${plan.scope === 'user' ? ' (a personal connection: yours)' : ''}:`,\n ` ${started.authorizeUrl}`,\n ` (one-time link, valid until ${expires} UTC)`,\n ].join('\\n')\n : [\n `Send this link to ${member.email ?? 'the member'} — they sign in to ${plan.product.name} for ${plan.team.slug}${plan.scope === 'user' ? ' (a personal connection: theirs)' : ''}:`,\n ` ${started.authorizeUrl}`,\n ` (one-time, for them only, valid until ${expires} UTC)`,\n ].join('\\n'),\n );\n\n // Only ever the caller's own browser: opening a link meant for another\n // member would sign the caller's provider account in for them.\n if (forCaller && !args.noOpen && !ctx.jsonMode) {\n (args.openUrl ?? openInBrowser)(started.authorizeUrl);\n }\n\n if (args.noWait || ctx.jsonMode) {\n return ctx.succeed(\n {\n host,\n plan: started.plan,\n authorizeUrl: started.authorizeUrl,\n expiresAt: started.expiresAt,\n connected: false,\n },\n ctx.ui.hint(\n `Then check with \"ekanos teams show ${target.team} ${target.product}\".`,\n ),\n );\n }\n\n ctx.log(\n 'Waiting for the sign-in to finish (Ctrl-C stops waiting; the link stays valid)…',\n );\n const deadline = Date.parse(started.expiresAt) || Date.now() + 10 * 60 * 1000;\n while (Date.now() < deadline) {\n await new Promise((resolve) =>\n setTimeout(resolve, args.pollDelayMs ?? 3000),\n );\n const polled = await client.call((token) =>\n showTeamConnect(host, token, target, asEmail),\n );\n if (polled.plan.connected) {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n return ctx.succeed(\n { host, plan: polled.plan, status, connected: true },\n [\n ctx.ui.result({\n title: `Connected ${plan.product.name} for ${plan.team.slug}`,\n rows: [\n ['Signed in by', member.email ?? member.userId],\n ['Status', statusOf(polled.plan)],\n ],\n }),\n checklist(status).join('\\n'),\n ].join('\\n'),\n );\n }\n }\n throw validationError(\n 'The sign-in did not finish before the link expired.',\n `Run \"ekanos teams connect ${target.team} ${target.product}${asEmail ? ` --as ${asEmail}` : ''}\" again for a fresh link.`,\n );\n}\n\n/** `--link-only`: the team's page and whether it is connected. */\nasync function printLink(\n ctx: CliContext,\n client: TeamsClient,\n host: string,\n target: { source: string; team: string; product: string },\n): Promise<ExitCode> {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n if (!status.enabled) {\n throw invalidStateError(\n `\"${target.product}\" is not enabled on ${status.source.slug}.`,\n `\"ekanos sources products --source ${status.source.slug}\" shows what this Source has; a super-admin enables a product for a Source.`,\n );\n }\n const connected = status.activation !== null;\n const rows: ResultRow[] = [\n ['Open', status.connectUrl],\n [\n 'Status',\n connected\n ? `connected${status.activation?.activatedAt ? ` ${status.activation.activatedAt.slice(0, 10)}` : ''}`\n : 'not connected',\n ],\n ];\n return ctx.succeed(\n { host, ...status },\n ctx.ui.result({\n title: connected\n ? `${status.team.slug} has connected ${status.product.name}`\n : `Connect link for ${status.team.slug} · ${status.product.name}`,\n tone: connected ? 'ok' : 'warn',\n rows,\n notes: [\n 'A team member signs in there and clicks Connect.',\n `\"ekanos teams connect ${status.team.slug} ${status.product.slug}\" (without --link-only) connects it from here.`,\n ],\n }),\n );\n}\n\nfunction statusOf(plan: TeamConnectPlan): string {\n if (!plan.connected) return 'not connected';\n return `connected${plan.connectedAt ? ` ${plan.connectedAt.slice(0, 10)}` : ''}`;\n}\n\n/** Best effort: the link is always printed, so a failed open costs nothing. */\nfunction openInBrowser(url: string): void {\n const [command, argv] =\n process.platform === 'darwin'\n ? ['open', [url]]\n : process.platform === 'win32'\n ? ['cmd', ['/c', 'start', '\"\"', url]]\n : ['xdg-open', [url]];\n try {\n const child = spawn(command, argv, { detached: true, stdio: 'ignore' });\n child.on('error', () => {});\n child.unref();\n } catch {\n // Printed above; nothing to do.\n }\n}\n"]}
1
+ {"version":3,"file":"teams-connect.js","sourceRoot":"","sources":["../../src/commands/teams-connect.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n TeamAgentListSchema,\n type TeamIntegrationStatus,\n} from '@ekanos/integration-schema';\n\nimport type { CliContext } from '../context';\nimport { invalidStateError, usageError, validationError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { assertBrowserSafeUrl, openInBrowser } from '../open-url';\nimport {\n type TeamConnectPlan,\n showTeamConnect,\n startTeamConnect,\n} from '../team-connect-api';\nimport { call, showTeamIntegration } from '../teams-api';\nimport type { ResultRow } from '../ui';\nimport { promptHidden, promptLine } from './apps';\nimport { scopeHiddenLines } from './scope-notice';\nimport {\n type TeamsArgs,\n type TeamsClient,\n canPrompt,\n checklist,\n promptAndSaveTeamApp,\n} from './teams';\nimport { isTeamChannel, runTeamChannelInstall } from './teams-channel-install';\n\n/**\n * `teams connect <team> <product>` — connect a product for one team, doing\n * whichever the integration needs (the host's plan decides, never the CLI):\n *\n * - works as shipped → says so; not self-serve or not enabled → refuses\n * with the reason (and points at `sources products` for the latter);\n * - form fields → asks them here (secrets hidden, never as arguments) and\n * activates exactly as the app's form does;\n * - OAuth → runs `teams app set` inline when the team's own app is needed\n * first (Zendesk), then a one-time sign-in link for the member who\n * consents: the caller when a member, else `--as <email>`. Opens it for\n * the caller (unless `--no-open`), always prints it, and waits until the\n * team is connected (unless `--no-wait`);\n * - a form only the browser can fill → prints the team's page.\n *\n * `--connection <id>` connects one of the integration's named connections\n * instead of the main one — Linear's `agent`, the team's own Linear app\n * installed as a workspace member, which is what makes Linear send the\n * @mention and assignment webhooks an agent's triggers listen for. It runs\n * the same way: the team app's fields when missing, then the sign-in, then\n * the wait until it is installed.\n *\n * Without `--connection`, once the main connection is made (or already\n * was), a named connection the team's agents' triggers wait on is offered\n * next — at a terminal it asks and installs it, otherwise it names the\n * command. \"Connected\" is not the goal; an agent that can be reached is.\n *\n * `--reconnect` connects it again even though it reads as connected — for\n * a revoked or expired sign-in, or new form values. An OAuth reconnect\n * prints the link and returns: the team already reads as connected, so\n * there is nothing to wait for.\n *\n * `--link-only` keeps the old behaviour: the team's page and its status.\n *\n * `slack` and `linear-app` install the channels agent triggers answer\n * through — Slack, and Ekanos's own Linear Agents app — by the same\n * link-and-wait (`teams-channel-install.ts`).\n */\nexport async function runTeamConnect(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n source: string,\n input: { team: string; product: string; as?: string; connection?: string },\n): Promise<ExitCode> {\n const target = {\n source,\n team: input.team,\n product: input.product,\n ...(input.connection ? { connection: input.connection } : {}),\n };\n\n // Slack and Ekanos's Linear Agents app: the channels a `slack` or `linear`\n // agent trigger answers through, installed by their own flows.\n if (!input.connection && !args.linkOnly && isTeamChannel(input.product)) {\n return runTeamChannelInstall(ctx, args, client, host, source, {\n team: input.team,\n channel: input.product,\n ...(input.as ? { as: input.as } : {}),\n open: args.openUrl ?? openInBrowser,\n });\n }\n\n if (args.linkOnly) return printLink(ctx, client, host, target);\n\n const { plan } = await client.call((token) =>\n showTeamConnect(host, token, target, input.as),\n );\n const named = isNamed(plan);\n const name = named\n ? await connectionLabel(client, host, target, plan)\n : plan.product.name;\n await warnOtherRunsAs(ctx, client, host, source, plan);\n for (const line of scopeHiddenLines(plan.productScope, {\n team: plan.team.slug,\n product: plan.product.slug,\n source: plan.source.slug,\n })) {\n ctx.warn(line);\n }\n\n switch (plan.mode) {\n case 'not-entitled':\n throw invalidStateError(\n plan.reason ??\n `\"${input.product}\" is not enabled on ${plan.source.slug}.`,\n `Enable it for the Source first: \"ekanos sources products enable ${input.product}\" as a Source admin if ${plan.source.slug} built it, otherwise a super-admin (/admin in the browser). \"ekanos sources products\" shows what ${plan.source.slug} has.`,\n );\n case 'not-self-serve':\n throw invalidStateError(\n plan.reason ?? `${name} is not connected by a team.`,\n plan.product.kind === 'experience'\n ? `\"ekanos sources products --source ${plan.source.slug}\" shows whether it is on for the Source.`\n : 'It is turned on for the Source by Ekanos; there is nothing for the team to do.',\n );\n case 'unsupported':\n throw invalidStateError(\n plan.reason ?? `${name} cannot be connected from here.`,\n `Open the team's page instead: ${plan.connectUrl}`,\n );\n case 'works-as-shipped':\n return ctx.succeed(\n { host, plan, connected: true },\n ctx.ui.result({\n title: `${name} works as shipped for ${plan.team.slug}`,\n rows: [['Status', 'nothing to connect']],\n }),\n );\n case 'browser':\n return ctx.succeed(\n { host, plan, connected: plan.connected },\n ctx.ui.result({\n title: plan.connected\n ? `${plan.team.slug} has connected ${name}`\n : `${name} connects in the app for ${plan.team.slug}`,\n tone: plan.connected ? 'ok' : 'warn',\n rows: [\n ['Open', plan.connectUrl],\n ['Status', statusOf(plan)],\n ],\n notes: plan.connected\n ? []\n : [\n plan.reason ??\n `${name} connects through its own form in the app.`,\n 'A team admin signs in there and clicks Connect.',\n ],\n }),\n );\n default:\n break;\n }\n\n if (plan.connected && !args.reconnect) {\n const summary = ctx.ui.result({\n title: `${plan.team.slug} has already ${named ? 'installed' : 'connected'} ${name}`,\n rows: [\n ['Status', statusOf(plan, named)],\n ['Team page', plan.connectUrl],\n ],\n notes: [\n `\"ekanos teams show ${plan.team.slug} ${plan.product.slug}\" shows the full setup.`,\n `Broken (revoked or expired)? Connect it again: ekanos teams connect ${plan.team.slug} ${plan.product.slug}${named ? ` --connection ${plan.connectionId}` : ''} --reconnect`,\n ],\n });\n return named\n ? ctx.succeed({ host, plan, connected: true }, summary)\n : offerChannels(ctx, args, client, host, source, input, {\n data: { host, plan, connected: true },\n summary,\n });\n }\n\n if (plan.mode === 'fields' || plan.mode === 'no-fields') {\n return activate(ctx, args, client, host, target, plan);\n }\n return connectOAuth(ctx, args, client, host, target, plan, input.as, {\n name,\n then: named\n ? undefined\n : (done) => offerChannels(ctx, args, client, host, source, input, done),\n });\n}\n\n/**\n * A personal connection belongs to whoever makes it, but a provided agent\n * uses the personal connection of the person it runs as — so connecting\n * your own leaves the agent missing it (CLI audit P0-5). Name each agent\n * that runs as someone else and the command that connects it for them.\n */\nasync function warnOtherRunsAs(\n ctx: CliContext,\n client: TeamsClient,\n host: string,\n source: string,\n plan: TeamConnectPlan,\n): Promise<void> {\n const email = plan.member?.email?.toLowerCase();\n if (plan.scope !== 'user' || !email) return;\n let list;\n try {\n list = await client.call((token) =>\n call(host, token, TeamAgentListSchema, {\n method: 'GET',\n path: `/api/partner/teams/${encodeURIComponent(plan.team.slug)}/agents`,\n source,\n }),\n );\n } catch (error) {\n ctx.log(\n `Could not check who ${plan.team.slug}'s agents run as: ${error instanceof Error ? error.message : String(error)}`,\n );\n return;\n }\n for (const entry of list.agents) {\n const runsAs = entry.agent?.requirements.find(\n (item) =>\n item.key === plan.product.slug &&\n item.via === 'person' &&\n item.viaDetail &&\n item.viaDetail.toLowerCase() !== email,\n )?.viaDetail;\n if (!runsAs) continue;\n ctx.warn(\n `Note: ${entry.key} runs as ${runsAs} and uses ${runsAs}'s ${plan.product.name} connection, not ${email}'s. For the agent, run: npx @ekanos/cli teams connect ${plan.team.slug} ${plan.product.slug} --as ${runsAs} --source ${source}`,\n );\n }\n}\n\n/**\n * After the main connection: the named connections the team's agents'\n * triggers wait on and the team has not installed (Linear's agent). At a\n * terminal, ask and install each; otherwise name the command, in the\n * result and its JSON (`channelsToInstall`).\n */\nasync function offerChannels(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n source: string,\n input: { team: string; product: string; as?: string },\n done: { data: Record<string, unknown>; summary: string },\n): Promise<ExitCode> {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, {\n source,\n team: input.team,\n product: input.product,\n }),\n );\n const waiting = channelsToInstall(status);\n if (waiting.length === 0) return ctx.succeed(done.data, done.summary);\n\n const command = (connectionId: string) =>\n `ekanos teams connect ${input.team} ${input.product} --connection ${connectionId} --source ${status.source.slug}`;\n const why = (entry: (typeof waiting)[number]) =>\n `${entry.label} is not installed for ${input.team}, and ${entry.neededBy.map((need) => `${need.agent} (${need.triggers.join(', ')})`).join(', ')} only start${entry.neededBy.length === 1 ? 's' : ''} through it.`;\n\n if (!canPrompt(ctx, args)) {\n return ctx.succeed(\n {\n ...done.data,\n channelsToInstall: waiting.map((entry) => ({\n connectionId: entry.connectionId,\n label: entry.label,\n neededBy: entry.neededBy,\n command: command(entry.connectionId),\n })),\n },\n [\n done.summary,\n ...waiting.flatMap((entry) => [\n `Next: ${why(entry)}`,\n ` Install it in your terminal: npx @ekanos/cli ${command(entry.connectionId)}`,\n ]),\n ].join('\\n'),\n );\n }\n\n ctx.log(done.summary);\n let code: ExitCode = 0;\n for (const entry of waiting) {\n ctx.log(why(entry));\n const answer = (\n await (args.ask ?? promptLine)(`Install ${entry.label} now? [Y/n] `)\n )\n .trim()\n .toLowerCase();\n if (answer !== '' && answer !== 'y' && answer !== 'yes') {\n ctx.log(`Skipped. Later: ${command(entry.connectionId)}`);\n continue;\n }\n code = await runTeamConnect(ctx, args, client, host, source, {\n ...input,\n connection: entry.connectionId,\n });\n }\n return code;\n}\n\n/** Named connections the team's agents wait on and the team has not installed. */\nexport function channelsToInstall(status: TeamIntegrationStatus) {\n return (status.connections ?? []).filter(\n (entry) =>\n entry.connectionId !== 'default' &&\n !entry.connected &&\n entry.neededBy.length > 0,\n );\n}\n\nfunction isNamed(plan: TeamConnectPlan): boolean {\n return Boolean(plan.connectionId && plan.connectionId !== 'default');\n}\n\nasync function connectionLabel(\n client: TeamsClient,\n host: string,\n target: { source: string; team: string; product: string },\n plan: TeamConnectPlan,\n): Promise<string> {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n return (\n status.connections?.find(\n (entry) => entry.connectionId === plan.connectionId,\n )?.label ??\n status.teamApps.find((entry) => entry.connectionId === plan.connectionId)\n ?.label ??\n `${plan.product.name} (${plan.connectionId})`\n );\n}\n\nasync function activate(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n target: { source: string; team: string; product: string },\n plan: TeamConnectPlan,\n): Promise<ExitCode> {\n if (plan.scope === 'user' && !plan.member) {\n throw invalidStateError(\n plan.memberProblem ??\n `${plan.product.name} is a personal connection: each member connects their own.`,\n `A member connects it for themselves on the team's page: ${plan.connectUrl}`,\n );\n }\n\n const fields: Record<string, string> = {};\n if (plan.mode === 'fields') {\n if (!canPrompt(ctx, args)) {\n throw usageError(\n `${plan.product.name} needs its fields typed at a terminal (${plan.fields.map((field) => field.label).join(', ')}), never in a script or an agent run.`,\n `Run it yourself in your terminal: npx @ekanos/cli teams connect ${target.team} ${target.product} --source ${plan.source.slug}`,\n );\n }\n ctx.log(\n `${plan.product.name} for ${plan.scope === 'user' ? 'you, in' : 'team'} ${plan.team.slug}: enter what the app's form asks. Secrets are hidden and never shown again.`,\n );\n for (const field of plan.fields) {\n if (field.description) ctx.log(` ${field.description}`);\n const suffix = `${field.required ? '' : ' (optional — Enter skips)'}${field.sensitive ? ' (hidden)' : ''}: `;\n const value = (\n await (\n field.sensitive\n ? (args.askSecret ?? promptHidden)\n : (args.ask ?? promptLine)\n )(`${field.label}${suffix}`)\n ).trim();\n if (value) fields[field.name] = value;\n else if (field.required) {\n throw validationError(\n `${field.label} is needed.`,\n `Run \"ekanos teams connect ${target.team} ${target.product}\" again.`,\n );\n }\n }\n }\n\n const started = await client.call((token) =>\n startTeamConnect(host, token, target, { fields }),\n );\n return ctx.succeed(\n { host, ...started, connected: started.plan.connected },\n ctx.ui.result({\n title: `Connected ${started.plan.product.name} for ${started.plan.team.slug}`,\n rows: [\n ['Status', statusOf(started.plan)],\n [\n 'For',\n started.plan.scope === 'user'\n ? `you (${started.plan.member?.email ?? 'your account'}) — a personal connection`\n : 'the whole team',\n ],\n ['Team page', started.plan.connectUrl],\n ],\n }),\n );\n}\n\nasync function connectOAuth(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n target: {\n source: string;\n team: string;\n product: string;\n connection?: string;\n },\n plan: TeamConnectPlan,\n asEmail: string | undefined,\n options: {\n /** What is being connected: the product, or a named connection's label. */\n name: string;\n /** On success, instead of finishing: the main connection's follow-ups. */\n then?: (done: {\n data: Record<string, unknown>;\n summary: string;\n }) => Promise<ExitCode>;\n },\n): Promise<ExitCode> {\n const named = isNamed(plan);\n const name = options.name;\n const again = `ekanos teams connect ${target.team} ${target.product}${named ? ` --connection ${plan.connectionId}` : ''}`;\n if (!plan.member) {\n throw invalidStateError(\n plan.memberProblem ?? 'No member of the team can sign in yet.',\n `Name a member of ${plan.team.slug} who signs in: ${again} --as <email>`,\n );\n }\n\n if (plan.teamApp) {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n const connectionId = plan.connectionId ?? 'default';\n const app =\n status.teamApps.find((entry) => entry.connectionId === connectionId) ??\n (named ? undefined : status.teamApps[0]);\n if (app && app.fields.some((field) => !field.set)) {\n if (!canPrompt(ctx, args)) {\n throw usageError(\n `${name} needs ${plan.team.slug}'s own app first, entered at a terminal.`,\n `Run it yourself in your terminal: npx @ekanos/cli ${again} --source ${plan.source.slug}`,\n );\n }\n ctx.log(\n `${name} signs ${plan.team.slug} in through the team's own app. Set it up first:`,\n );\n await promptAndSaveTeamApp(ctx, args, client, host, target, status, app);\n }\n }\n\n const started = await client.call((token) =>\n startTeamConnect(host, token, target, asEmail ? { as: asEmail } : {}),\n );\n if (started.result !== 'consent') {\n throw invalidStateError(\n `The host answered \"${started.result}\" where a sign-in link was expected.`,\n 'Run \"ekanos upgrade\" — the CLI and the host disagree on the connect contract.',\n );\n }\n assertBrowserSafeUrl(started.authorizeUrl, 'sign-in link');\n\n const member = started.plan.member ?? plan.member;\n const forCaller = member.isCaller;\n const expires = started.expiresAt.replace('T', ' ').slice(0, 16);\n ctx.log(\n forCaller\n ? [\n named\n ? `Install ${name} for ${plan.team.slug} — sign in as an admin of the workspace it goes into, and approve it:`\n : `Sign in to ${plan.product.name} as the account ${plan.team.slug} should use${plan.scope === 'user' ? ' (a personal connection: yours)' : ''}:`,\n ` ${started.authorizeUrl}`,\n ` (one-time link, valid until ${expires} UTC)`,\n ].join('\\n')\n : [\n `Send this link to ${member.email ?? 'the member'} — they ${named ? `install ${name}` : `sign in to ${plan.product.name}`} for ${plan.team.slug}${plan.scope === 'user' ? ' (a personal connection: theirs)' : ''}:`,\n ` ${started.authorizeUrl}`,\n ` (one-time, for them only, valid until ${expires} UTC)`,\n ].join('\\n'),\n );\n\n // Only ever the caller's own browser: opening a link meant for another\n // member would sign the caller's provider account in for them.\n if (forCaller && !args.noOpen && !ctx.jsonMode) {\n (args.openUrl ?? openInBrowser)(started.authorizeUrl);\n }\n\n // A reconnect can't be waited on: the team already reads as connected, so\n // nothing the host reports changes when the new sign-in lands.\n const reconnecting = args.reconnect === true && plan.connected;\n if (args.noWait || ctx.jsonMode || reconnecting) {\n return ctx.succeed(\n {\n host,\n plan: started.plan,\n authorizeUrl: started.authorizeUrl,\n expiresAt: started.expiresAt,\n connected: false,\n },\n ctx.ui.hint(\n reconnecting\n ? `The current connection keeps working until the sign-in finishes; then its tokens are replaced. Check with \"ekanos teams show ${target.team} ${target.product}\".`\n : `Then check with \"ekanos teams show ${target.team} ${target.product}\".`,\n ),\n );\n }\n\n ctx.log(\n 'Waiting for the sign-in to finish (Ctrl-C stops waiting; the link stays valid)…',\n );\n const deadline = Date.parse(started.expiresAt) || Date.now() + 10 * 60 * 1000;\n while (Date.now() < deadline) {\n await new Promise((resolve) =>\n setTimeout(resolve, args.pollDelayMs ?? 3000),\n );\n const polled = await client.call((token) =>\n showTeamConnect(host, token, target, asEmail),\n );\n if (polled.plan.connected) {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n const done = {\n data: { host, plan: polled.plan, status, connected: true },\n summary: [\n ctx.ui.result({\n title: `${named ? 'Installed' : 'Connected'} ${name} for ${plan.team.slug}`,\n rows: [\n ['Signed in by', member.email ?? member.userId],\n ['Status', statusOf(polled.plan, named)],\n ],\n notes: named\n ? [\n `Prove it end to end: @mention the agent in ${plan.product.name}, then \"ekanos runs list --team ${plan.team.slug}\" shows the run it started.`,\n ]\n : [],\n }),\n checklist(status).join('\\n'),\n ].join('\\n'),\n };\n return options.then\n ? options.then(done)\n : ctx.succeed(done.data, done.summary);\n }\n }\n throw validationError(\n 'The sign-in did not finish before the link expired.',\n `Run \"${again}${asEmail ? ` --as ${asEmail}` : ''}\" again for a fresh link.`,\n );\n}\n\n/** `--link-only`: the team's page and whether it is connected. */\nasync function printLink(\n ctx: CliContext,\n client: TeamsClient,\n host: string,\n target: { source: string; team: string; product: string },\n): Promise<ExitCode> {\n const status = await client.call((token) =>\n showTeamIntegration(host, token, target),\n );\n if (!status.enabled) {\n throw invalidStateError(\n `\"${target.product}\" is not enabled on ${status.source.slug}.`,\n `\"ekanos sources products --source ${status.source.slug}\" shows what this Source has; a super-admin enables a product for a Source.`,\n );\n }\n const connected = status.activation !== null;\n const rows: ResultRow[] = [\n ['Open', status.connectUrl],\n [\n 'Status',\n connected\n ? `connected${status.activation?.activatedAt ? ` ${status.activation.activatedAt.slice(0, 10)}` : ''}`\n : 'not connected',\n ],\n ];\n return ctx.succeed(\n { host, ...status },\n ctx.ui.result({\n title: connected\n ? `${status.team.slug} has connected ${status.product.name}`\n : `Connect link for ${status.team.slug} · ${status.product.name}`,\n tone: connected ? 'ok' : 'warn',\n rows,\n notes: [\n 'A team member signs in there and clicks Connect.',\n `\"ekanos teams connect ${status.team.slug} ${status.product.slug}\" (without --link-only) connects it from here.`,\n ],\n }),\n );\n}\n\nfunction statusOf(plan: TeamConnectPlan, named = false): string {\n if (!plan.connected) return named ? 'not installed' : 'not connected';\n return `${named ? 'installed' : 'connected'}${plan.connectedAt ? ` ${plan.connectedAt.slice(0, 10)}` : ''}`;\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import type { CliContext } from '../context.js';
2
+ import type { ExitCode } from '../exit-codes.js';
3
+ import { type TeamsArgs } from './teams.js';
4
+ /**
5
+ * `teams events <team> [<product>]` — the integration events recorded for a
6
+ * team, newest first, each with what it started: "an event arrived, and
7
+ * here's why it did or didn't start a run". The team-level counterpart of
8
+ * `routes unrouted`. Read-only; never the event's payload.
9
+ */
10
+ export declare function runTeamEvents(ctx: CliContext, args: TeamsArgs, operands: readonly string[], now?: () => number): Promise<ExitCode>;
11
+ /** `--since 30m|24h|7d` (before now) or a date the host can read, as ISO. */
12
+ export declare function parseSince(raw: string | boolean | string[] | undefined, nowMs: number): string | undefined;
@@ -0,0 +1,138 @@
1
+ import { requireSession, resolveAuthEnvironment } from '../auth/session.js';
2
+ import { usageError } from '../errors.js';
3
+ import { resolveSourceTarget } from '../source-target.js';
4
+ import { listTeamEvents } from '../teams-api.js';
5
+ import { TeamsClient } from './teams.js';
6
+ const USAGE = 'Run "ekanos teams events <team> [<product>] [--product <slug>] [--since 24h|7d|<date>] [--limit <1-100>]".';
7
+ const MAX_LIMIT = 100;
8
+ /**
9
+ * `teams events <team> [<product>]` — the integration events recorded for a
10
+ * team, newest first, each with what it started: "an event arrived, and
11
+ * here's why it did or didn't start a run". The team-level counterpart of
12
+ * `routes unrouted`. Read-only; never the event's payload.
13
+ */
14
+ export async function runTeamEvents(ctx, args, operands, now = Date.now) {
15
+ var _a, _b, _c;
16
+ const team = slugOperand(operands[0], 'team');
17
+ const positionalProduct = operands[1] === undefined ? undefined : slugOperand(operands[1], 'product');
18
+ if (operands[2] !== undefined) {
19
+ throw usageError(`Unexpected argument "${operands[2]}".`, USAGE);
20
+ }
21
+ const flagProduct = typeof ((_a = args.flags) === null || _a === void 0 ? void 0 : _a.product) === 'string'
22
+ ? slugOperand(args.flags.product, 'product')
23
+ : undefined;
24
+ if (positionalProduct && flagProduct && positionalProduct !== flagProduct) {
25
+ throw usageError(`Two products named: "${positionalProduct}" and --product "${flagProduct}".`, USAGE);
26
+ }
27
+ const product = positionalProduct !== null && positionalProduct !== void 0 ? positionalProduct : flagProduct;
28
+ const since = parseSince((_b = args.flags) === null || _b === void 0 ? void 0 : _b.since, now());
29
+ const limit = parseLimit((_c = args.flags) === null || _c === void 0 ? void 0 : _c.limit);
30
+ const env = resolveAuthEnvironment(ctx, args.host, args.env, {
31
+ projectDir: args.dir,
32
+ });
33
+ const resolved = await resolveSourceTarget(env, requireSession(env), args);
34
+ const client = new TeamsClient(env, resolved.session);
35
+ const list = await client.call((token) => listTeamEvents(env.host, token, { source: resolved.source, team }, { product, since, limit }));
36
+ const scope = [
37
+ product ? `for ${product}` : '',
38
+ since ? `since ${since.slice(0, 16).replace('T', ' ')}` : '',
39
+ ]
40
+ .filter(Boolean)
41
+ .join(' ');
42
+ if (list.events.length === 0) {
43
+ return ctx.succeed(Object.assign({ host: env.host }, list), ctx.ui.result({
44
+ title: `No events recorded for ${list.team.slug}${scope ? ` ${scope}` : ''}`,
45
+ tone: 'warn',
46
+ notes: [
47
+ 'An event lands here once an integration emits one for this team.',
48
+ `Nothing yet? Check the team's setup ("ekanos teams show ${list.team.slug} <product>") and, for a Source connection, "ekanos routes unrouted".`,
49
+ ],
50
+ }));
51
+ }
52
+ const quiet = list.events.filter((event) => event.status === 'done' && event.runs.length === 0).length;
53
+ return ctx.succeed(Object.assign({ host: env.host }, list), ctx.ui.result({
54
+ title: `${list.events.length} event${list.events.length === 1 ? '' : 's'} on ${list.team.slug}${scope ? ` ${scope}` : ''}`,
55
+ tone: list.events.some((event) => event.status === 'failed' || event.status === 'dropped')
56
+ ? 'warn'
57
+ : 'ok',
58
+ rows: list.events.map((event) => eventRow(event, list.team.slug)),
59
+ notes: [
60
+ ...(quiet > 0
61
+ ? [
62
+ `List an agent's triggers with "ekanos teams triggers list ${list.team.slug} <key>"; add one with "ekanos teams triggers add ${list.team.slug} <key> event <event-id>".`,
63
+ ]
64
+ : []),
65
+ `"ekanos runs show <run-id> --team ${list.team.slug}" opens a run.`,
66
+ ],
67
+ }));
68
+ }
69
+ function eventRow(event, team) {
70
+ return [
71
+ event.receivedAt.slice(0, 19).replace('T', ' '),
72
+ [`${event.eventId} · ${event.status}`, ...outcome(event, team)],
73
+ ];
74
+ }
75
+ /** Why the event did or didn't start a run, in a line or two. */
76
+ function outcome(event, team) {
77
+ var _a;
78
+ switch (event.status) {
79
+ case 'pending':
80
+ return [' waiting to be dispatched'];
81
+ case 'processing':
82
+ return [' being dispatched now'];
83
+ case 'dropped':
84
+ return [
85
+ ' dropped: no integration declares this event any more, its payload did not validate, or it was an agent’s own activity',
86
+ ];
87
+ case 'failed':
88
+ return [
89
+ ` failed after ${event.attempts} attempt${event.attempts === 1 ? '' : 's'}: ${(_a = event.lastError) !== null && _a !== void 0 ? _a : 'no error recorded'} (retried while attempts remain)`,
90
+ ...event.runs.map(runLine),
91
+ ];
92
+ case 'done':
93
+ if (event.runs.length > 0)
94
+ return event.runs.map(runLine);
95
+ return event.subscribedTriggers === 0
96
+ ? [
97
+ ` no run: no enabled trigger on ${team} subscribes to ${event.eventId}`,
98
+ ]
99
+ : [
100
+ ` no run: ${event.subscribedTriggers} enabled trigger${event.subscribedTriggers === 1 ? '' : 's'} subscribe${event.subscribedTriggers === 1 ? 's' : ''} to it, but none matched its filter or its agent could not start (paused, or Agents off)`,
101
+ ];
102
+ }
103
+ }
104
+ function runLine(run) {
105
+ var _a;
106
+ return ` → run ${run.id} · ${(_a = run.agent.templateKey) !== null && _a !== void 0 ? _a : run.agent.slug} · ${run.status}`;
107
+ }
108
+ function slugOperand(value, what) {
109
+ const slug = value === null || value === void 0 ? void 0 : value.trim().toLowerCase();
110
+ if (slug && /^[a-z0-9][a-z0-9-]*$/.test(slug))
111
+ return slug;
112
+ throw usageError(value ? `"${value}" is not a ${what} slug.` : `Name the ${what}.`, USAGE);
113
+ }
114
+ /** `--since 30m|24h|7d` (before now) or a date the host can read, as ISO. */
115
+ export function parseSince(raw, nowMs) {
116
+ if (raw === undefined)
117
+ return undefined;
118
+ const value = typeof raw === 'string' ? raw.trim() : '';
119
+ const relative = /^(\d+)([mhd])$/.exec(value);
120
+ if (relative) {
121
+ const unitMs = { m: 60000, h: 3600000, d: 86400000 }[relative[2]];
122
+ return new Date(nowMs - Number(relative[1]) * unitMs).toISOString();
123
+ }
124
+ const parsed = Date.parse(value);
125
+ if (value && !Number.isNaN(parsed))
126
+ return new Date(parsed).toISOString();
127
+ throw usageError(`--since "${value}" is not a duration or a date.`, 'Use a duration before now (30m, 24h, 7d) or a date (2026-10-19, 2026-10-19T09:00Z).');
128
+ }
129
+ function parseLimit(raw) {
130
+ if (raw === undefined)
131
+ return undefined;
132
+ const limit = typeof raw === 'string' ? Number(raw) : Number.NaN;
133
+ if (Number.isInteger(limit) && limit >= 1 && limit <= MAX_LIMIT) {
134
+ return limit;
135
+ }
136
+ throw usageError(`--limit must be a whole number from 1 to ${MAX_LIMIT}.`, USAGE);
137
+ }
138
+ //# sourceMappingURL=teams-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teams-events.js","sourceRoot":"","sources":["../../src/commands/teams-events.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AgentRunSummary,\n TeamIntegrationEvent,\n} from '@ekanos/integration-schema';\n\nimport { requireSession, resolveAuthEnvironment } from '../auth/session';\nimport type { CliContext } from '../context';\nimport { usageError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { resolveSourceTarget } from '../source-target';\nimport { listTeamEvents } from '../teams-api';\nimport type { ResultRow } from '../ui';\nimport { TeamsClient, type TeamsArgs } from './teams';\n\nconst USAGE =\n 'Run \"ekanos teams events <team> [<product>] [--product <slug>] [--since 24h|7d|<date>] [--limit <1-100>]\".';\nconst MAX_LIMIT = 100;\n\n/**\n * `teams events <team> [<product>]` — the integration events recorded for a\n * team, newest first, each with what it started: \"an event arrived, and\n * here's why it did or didn't start a run\". The team-level counterpart of\n * `routes unrouted`. Read-only; never the event's payload.\n */\nexport async function runTeamEvents(\n ctx: CliContext,\n args: TeamsArgs,\n operands: readonly string[],\n now: () => number = Date.now,\n): Promise<ExitCode> {\n const team = slugOperand(operands[0], 'team');\n const positionalProduct =\n operands[1] === undefined ? undefined : slugOperand(operands[1], 'product');\n if (operands[2] !== undefined) {\n throw usageError(`Unexpected argument \"${operands[2]}\".`, USAGE);\n }\n const flagProduct =\n typeof args.flags?.product === 'string'\n ? slugOperand(args.flags.product, 'product')\n : undefined;\n if (positionalProduct && flagProduct && positionalProduct !== flagProduct) {\n throw usageError(\n `Two products named: \"${positionalProduct}\" and --product \"${flagProduct}\".`,\n USAGE,\n );\n }\n const product = positionalProduct ?? flagProduct;\n const since = parseSince(args.flags?.since, now());\n const limit = parseLimit(args.flags?.limit);\n\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const resolved = await resolveSourceTarget(env, requireSession(env), args);\n const client = new TeamsClient(env, resolved.session);\n const list = await client.call((token) =>\n listTeamEvents(\n env.host,\n token,\n { source: resolved.source, team },\n { product, since, limit },\n ),\n );\n\n const scope = [\n product ? `for ${product}` : '',\n since ? `since ${since.slice(0, 16).replace('T', ' ')}` : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n if (list.events.length === 0) {\n return ctx.succeed(\n { host: env.host, ...list },\n ctx.ui.result({\n title: `No events recorded for ${list.team.slug}${scope ? ` ${scope}` : ''}`,\n tone: 'warn',\n notes: [\n 'An event lands here once an integration emits one for this team.',\n `Nothing yet? Check the team's setup (\"ekanos teams show ${list.team.slug} <product>\") and, for a Source connection, \"ekanos routes unrouted\".`,\n ],\n }),\n );\n }\n\n const quiet = list.events.filter(\n (event) => event.status === 'done' && event.runs.length === 0,\n ).length;\n return ctx.succeed(\n { host: env.host, ...list },\n ctx.ui.result({\n title: `${list.events.length} event${list.events.length === 1 ? '' : 's'} on ${list.team.slug}${scope ? ` ${scope}` : ''}`,\n tone: list.events.some(\n (event) => event.status === 'failed' || event.status === 'dropped',\n )\n ? 'warn'\n : 'ok',\n rows: list.events.map((event) => eventRow(event, list.team.slug)),\n notes: [\n ...(quiet > 0\n ? [\n `List an agent's triggers with \"ekanos teams triggers list ${list.team.slug} <key>\"; add one with \"ekanos teams triggers add ${list.team.slug} <key> event <event-id>\".`,\n ]\n : []),\n `\"ekanos runs show <run-id> --team ${list.team.slug}\" opens a run.`,\n ],\n }),\n );\n}\n\nfunction eventRow(event: TeamIntegrationEvent, team: string): ResultRow {\n return [\n event.receivedAt.slice(0, 19).replace('T', ' '),\n [`${event.eventId} · ${event.status}`, ...outcome(event, team)],\n ];\n}\n\n/** Why the event did or didn't start a run, in a line or two. */\nfunction outcome(event: TeamIntegrationEvent, team: string): string[] {\n switch (event.status) {\n case 'pending':\n return [' waiting to be dispatched'];\n case 'processing':\n return [' being dispatched now'];\n case 'dropped':\n return [\n ' dropped: no integration declares this event any more, its payload did not validate, or it was an agent’s own activity',\n ];\n case 'failed':\n return [\n ` failed after ${event.attempts} attempt${event.attempts === 1 ? '' : 's'}: ${event.lastError ?? 'no error recorded'} (retried while attempts remain)`,\n ...event.runs.map(runLine),\n ];\n case 'done':\n if (event.runs.length > 0) return event.runs.map(runLine);\n return event.subscribedTriggers === 0\n ? [\n ` no run: no enabled trigger on ${team} subscribes to ${event.eventId}`,\n ]\n : [\n ` no run: ${event.subscribedTriggers} enabled trigger${event.subscribedTriggers === 1 ? '' : 's'} subscribe${event.subscribedTriggers === 1 ? 's' : ''} to it, but none matched its filter or its agent could not start (paused, or Agents off)`,\n ];\n }\n}\n\nfunction runLine(run: AgentRunSummary): string {\n return ` → run ${run.id} · ${run.agent.templateKey ?? run.agent.slug} · ${run.status}`;\n}\n\nfunction slugOperand(\n value: string | undefined,\n what: 'team' | 'product',\n): string {\n const slug = value?.trim().toLowerCase();\n if (slug && /^[a-z0-9][a-z0-9-]*$/.test(slug)) return slug;\n throw usageError(\n value ? `\"${value}\" is not a ${what} slug.` : `Name the ${what}.`,\n USAGE,\n );\n}\n\n/** `--since 30m|24h|7d` (before now) or a date the host can read, as ISO. */\nexport function parseSince(\n raw: string | boolean | string[] | undefined,\n nowMs: number,\n): string | undefined {\n if (raw === undefined) return undefined;\n const value = typeof raw === 'string' ? raw.trim() : '';\n const relative = /^(\\d+)([mhd])$/.exec(value);\n if (relative) {\n const unitMs = { m: 60_000, h: 3_600_000, d: 86_400_000 }[\n relative[2] as 'm' | 'h' | 'd'\n ];\n return new Date(nowMs - Number(relative[1]) * unitMs).toISOString();\n }\n const parsed = Date.parse(value);\n if (value && !Number.isNaN(parsed)) return new Date(parsed).toISOString();\n throw usageError(\n `--since \"${value}\" is not a duration or a date.`,\n 'Use a duration before now (30m, 24h, 7d) or a date (2026-10-19, 2026-10-19T09:00Z).',\n );\n}\n\nfunction parseLimit(\n raw: string | boolean | string[] | undefined,\n): number | undefined {\n if (raw === undefined) return undefined;\n const limit = typeof raw === 'string' ? Number(raw) : Number.NaN;\n if (Number.isInteger(limit) && limit >= 1 && limit <= MAX_LIMIT) {\n return limit;\n }\n throw usageError(\n `--limit must be a whole number from 1 to ${MAX_LIMIT}.`,\n USAGE,\n );\n}\n"]}
@@ -3,12 +3,12 @@ import type { ExitCode } from '../exit-codes.js';
3
3
  import type { TeamsArgs, TeamsClient } from './teams.js';
4
4
  /**
5
5
  * Onboarding a team from the terminal, for the Source admin: `teams create`,
6
- * `teams members list|invite|role|remove`, `teams roles list` and
7
- * `teams connect`. Parsed before any session is touched (`parseOnboarding`)
6
+ * `teams members list|invite|role|remove`, `teams roles list`,
7
+ * `teams connect` and `teams disconnect`. Parsed before any session is touched (`parseOnboarding`)
8
8
  * so a usage error never costs a network round-trip, then run against the
9
9
  * session `runTeams` resolved.
10
10
  */
11
- export declare const ONBOARDING_SUBCOMMANDS: readonly ['create', 'members', 'roles', 'connect'];
11
+ export declare const ONBOARDING_SUBCOMMANDS: readonly ['create', 'rename', 'members', 'roles', 'connect', 'disconnect'];
12
12
  export type OnboardingSubcommand = (typeof ONBOARDING_SUBCOMMANDS)[number];
13
13
  export interface OnboardingFlags {
14
14
  slug?: string;
@@ -23,6 +23,10 @@ export type OnboardingPlan = {
23
23
  name: string;
24
24
  slug?: string;
25
25
  ownerEmail?: string;
26
+ } | {
27
+ kind: 'rename';
28
+ team: string;
29
+ name: string;
26
30
  } | {
27
31
  kind: 'members-list';
28
32
  team: string;
@@ -48,6 +52,10 @@ export type OnboardingPlan = {
48
52
  team: string;
49
53
  product: string;
50
54
  as?: string;
55
+ } | {
56
+ kind: 'disconnect';
57
+ team: string;
58
+ product: string;
51
59
  };
52
60
  export declare function isOnboardingSubcommand(value: string): value is OnboardingSubcommand;
53
61
  export declare function parseOnboarding(subcommand: OnboardingSubcommand, rest: readonly string[], flags: OnboardingFlags): OnboardingPlan;
@@ -1,18 +1,20 @@
1
1
  import { invalidStateError, usageError } from '../errors.js';
2
- import { createTeam, inviteTeamMember, listTeamMembers, listTeamRoles, removeTeamMember, setTeamMemberRole, } from '../teams-api.js';
2
+ import { createTeam, disconnectTeamIntegration, inviteTeamMember, listTeamMembers, listTeamRoles, removeTeamMember, renameTeam, setTeamMemberRole, } from '../teams-api.js';
3
3
  import { runTeamConnect } from './teams-connect.js';
4
4
  /**
5
5
  * Onboarding a team from the terminal, for the Source admin: `teams create`,
6
- * `teams members list|invite|role|remove`, `teams roles list` and
7
- * `teams connect`. Parsed before any session is touched (`parseOnboarding`)
6
+ * `teams members list|invite|role|remove`, `teams roles list`,
7
+ * `teams connect` and `teams disconnect`. Parsed before any session is touched (`parseOnboarding`)
8
8
  * so a usage error never costs a network round-trip, then run against the
9
9
  * session `runTeams` resolved.
10
10
  */
11
11
  export const ONBOARDING_SUBCOMMANDS = [
12
12
  'create',
13
+ 'rename',
13
14
  'members',
14
15
  'roles',
15
16
  'connect',
17
+ 'disconnect',
16
18
  ];
17
19
  const MEMBERS_VERBS = ['list', 'invite', 'role', 'remove'];
18
20
  export function isOnboardingSubcommand(value) {
@@ -33,11 +35,30 @@ export function parseOnboarding(subcommand, rest, flags) {
33
35
  ownerEmail: flags.owner === undefined ? undefined : emailOf(flags.owner),
34
36
  };
35
37
  }
38
+ if (subcommand === 'rename') {
39
+ const [team, name, ...extra] = rest;
40
+ const teamSlug = slugOf(team, 'team');
41
+ if (!(name === null || name === void 0 ? void 0 : name.trim())) {
42
+ throw usageError('Name the team’s new name.', `Run "ekanos teams rename ${teamSlug} \\"Bank A Support\\"".`);
43
+ }
44
+ noExtra(extra);
45
+ return { kind: 'rename', team: teamSlug, name: name.trim() };
46
+ }
36
47
  if (subcommand === 'connect') {
37
48
  const [team, product, ...extra] = rest;
38
49
  noExtra(extra);
39
50
  return Object.assign({ kind: 'connect', team: slugOf(team, 'team'), product: slugOf(product, 'product') }, (flags.as === undefined ? {} : { as: emailOf(flags.as) }));
40
51
  }
52
+ if (subcommand === 'disconnect') {
53
+ const [team, product, ...extra] = rest;
54
+ noExtra(extra);
55
+ const teamSlug = slugOf(team, 'team');
56
+ const productSlug = slugOf(product, 'product');
57
+ if (!flags.yes) {
58
+ throw invalidStateError(`Disconnecting ${productSlug} from ${teamSlug} removes the team's connection and its tokens: every widget, workflow and agent of the team that uses it stops until someone connects it again. The team's own app (its saved fields) stays.`, `Re-run with --yes: ekanos teams disconnect ${teamSlug} ${productSlug} --yes`);
59
+ }
60
+ return { kind: 'disconnect', team: teamSlug, product: productSlug };
61
+ }
41
62
  if (subcommand === 'roles') {
42
63
  const [verb, team, ...extra] = rest;
43
64
  if (verb !== 'list') {
@@ -120,6 +141,26 @@ export async function runOnboarding(ctx, args, client, host, source, plan) {
120
141
  ],
121
142
  }));
122
143
  }
144
+ case 'rename': {
145
+ const renamed = await client.call((token) => renameTeam(host, token, { source, team: plan.team }, plan.name));
146
+ const moved = renamed.team.slug !== renamed.previous.slug;
147
+ return ctx.succeed(Object.assign({ host }, renamed), ctx.ui.result({
148
+ title: renamed.team.name === renamed.previous.name
149
+ ? `${renamed.team.slug} is already named ${renamed.team.name}`
150
+ : `Renamed ${renamed.previous.slug} to ${renamed.team.name}`,
151
+ rows: [
152
+ ['Name', renamed.team.name],
153
+ ['Slug', renamed.team.slug],
154
+ ['Team home', renamed.teamUrl],
155
+ ],
156
+ notes: moved
157
+ ? [
158
+ `The slug followed the name: use "${renamed.team.slug}" from now on. Links and scripts naming "${renamed.previous.slug}" no longer reach the team.`,
159
+ ]
160
+ : [],
161
+ tone: moved ? 'warn' : 'ok',
162
+ }));
163
+ }
123
164
  case 'members-list': {
124
165
  const list = await client.call((token) => listTeamMembers(host, token, { source, team: plan.team }));
125
166
  const rows = list.members.map((member) => { var _a; return [
@@ -197,12 +238,24 @@ export async function runOnboarding(ctx, args, client, host, source, plan) {
197
238
  ],
198
239
  }));
199
240
  }
200
- case 'connect':
201
- return runTeamConnect(ctx, args, client, host, source, {
241
+ case 'disconnect': {
242
+ const done = await client.call((token) => disconnectTeamIntegration(host, token, {
243
+ source,
202
244
  team: plan.team,
203
245
  product: plan.product,
204
- as: plan.as,
205
- });
246
+ }));
247
+ return ctx.succeed(Object.assign({ host }, done), ctx.ui.result({
248
+ title: done.wasConnected
249
+ ? `Disconnected ${done.product.name} from ${done.team.slug}`
250
+ : `${done.team.slug} had no ${done.product.name} connection; cleared what was left`,
251
+ tone: 'warn',
252
+ notes: [
253
+ `Connect it again with "ekanos teams connect ${done.team.slug} ${done.product.slug}".`,
254
+ ],
255
+ }));
256
+ }
257
+ case 'connect':
258
+ return runTeamConnect(ctx, args, client, host, source, Object.assign({ team: plan.team, product: plan.product, as: plan.as }, (args.connection ? { connection: args.connection } : {})));
206
259
  }
207
260
  }
208
261
  function noExtra(extra) {
@@ -1 +1 @@
1
- {"version":3,"file":"teams-onboard.js","sourceRoot":"","sources":["../../src/commands/teams-onboard.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CliContext } from '../context';\nimport { invalidStateError, usageError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport {\n createTeam,\n inviteTeamMember,\n listTeamMembers,\n listTeamRoles,\n removeTeamMember,\n setTeamMemberRole,\n} from '../teams-api';\nimport type { TeamsArgs, TeamsClient } from './teams';\nimport { runTeamConnect } from './teams-connect';\n\n/**\n * Onboarding a team from the terminal, for the Source admin: `teams create`,\n * `teams members list|invite|role|remove`, `teams roles list` and\n * `teams connect`. Parsed before any session is touched (`parseOnboarding`)\n * so a usage error never costs a network round-trip, then run against the\n * session `runTeams` resolved.\n */\n\nexport const ONBOARDING_SUBCOMMANDS = [\n 'create',\n 'members',\n 'roles',\n 'connect',\n] as const;\nexport type OnboardingSubcommand = (typeof ONBOARDING_SUBCOMMANDS)[number];\n\nexport interface OnboardingFlags {\n slug?: string;\n owner?: string;\n role?: string;\n /** `connect --as <member-email>`: the member who signs in. */\n as?: string;\n yes: boolean;\n}\n\nexport type OnboardingPlan =\n | { kind: 'create'; name: string; slug?: string; ownerEmail?: string }\n | { kind: 'members-list'; team: string }\n | { kind: 'members-invite'; team: string; email: string; role: string }\n | { kind: 'members-role'; team: string; email: string; role: string }\n | { kind: 'members-remove'; team: string; email: string }\n | { kind: 'roles-list'; team: string }\n | { kind: 'connect'; team: string; product: string; as?: string };\n\nconst MEMBERS_VERBS = ['list', 'invite', 'role', 'remove'] as const;\n\nexport function isOnboardingSubcommand(\n value: string,\n): value is OnboardingSubcommand {\n return (ONBOARDING_SUBCOMMANDS as readonly string[]).includes(value);\n}\n\nexport function parseOnboarding(\n subcommand: OnboardingSubcommand,\n rest: readonly string[],\n flags: OnboardingFlags,\n): OnboardingPlan {\n if (subcommand === 'create') {\n const [name, ...extra] = rest;\n if (!name?.trim()) {\n throw usageError(\n 'Name the team.',\n 'Run \"ekanos teams create \\\\\"Bank A\\\\\" [--slug bank-a] [--owner <email>]\".',\n );\n }\n noExtra(extra);\n return {\n kind: 'create',\n name: name.trim(),\n slug: flags.slug === undefined ? undefined : slugOf(flags.slug, 'team'),\n ownerEmail: flags.owner === undefined ? undefined : emailOf(flags.owner),\n };\n }\n\n if (subcommand === 'connect') {\n const [team, product, ...extra] = rest;\n noExtra(extra);\n return {\n kind: 'connect',\n team: slugOf(team, 'team'),\n product: slugOf(product, 'product'),\n ...(flags.as === undefined ? {} : { as: emailOf(flags.as) }),\n };\n }\n\n if (subcommand === 'roles') {\n const [verb, team, ...extra] = rest;\n if (verb !== 'list') {\n throw usageError(\n verb\n ? `Unknown teams roles subcommand \"${verb}\".`\n : 'teams roles needs a subcommand.',\n 'Run \"ekanos teams roles list <team>\".',\n );\n }\n noExtra(extra);\n return { kind: 'roles-list', team: slugOf(team, 'team') };\n }\n\n const [verb, team, email, role, ...extra] = rest;\n const match = MEMBERS_VERBS.find((name) => name === verb);\n if (!match) {\n throw usageError(\n verb\n ? `Unknown teams members subcommand \"${verb}\".`\n : 'teams members needs a subcommand.',\n 'Run one of: ekanos teams members list <team>, ekanos teams members invite <team> <email> --role <role>, ekanos teams members role <team> <email> <role>, ekanos teams members remove <team> <email> --yes.',\n );\n }\n noExtra(extra);\n\n if (match === 'list') {\n if (email !== undefined) noExtra([email]);\n return { kind: 'members-list', team: slugOf(team, 'team') };\n }\n\n const teamSlug = slugOf(team, 'team');\n const address = emailOf(email);\n\n if (match === 'invite') {\n if (role !== undefined) noExtra([role]);\n return {\n kind: 'members-invite',\n team: teamSlug,\n email: address,\n role: roleOf(flags.role ?? 'member'),\n };\n }\n\n if (match === 'role') {\n const named = role ?? flags.role;\n if (!named) {\n throw usageError(\n 'Name the new role.',\n `Run \"ekanos teams members role ${teamSlug} ${address} <role>\"; \"ekanos teams roles list ${teamSlug}\" lists them.`,\n );\n }\n return {\n kind: 'members-role',\n team: teamSlug,\n email: address,\n role: roleOf(named),\n };\n }\n\n if (role !== undefined) noExtra([role]);\n if (!flags.yes) {\n throw invalidStateError(\n `Removing ${address} from ${teamSlug} ends their access to the team (a pending invitation is withdrawn instead).`,\n `Re-run with --yes: ekanos teams members remove ${teamSlug} ${address} --yes`,\n );\n }\n return { kind: 'members-remove', team: teamSlug, email: address };\n}\n\nexport async function runOnboarding(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n source: string,\n plan: OnboardingPlan,\n): Promise<ExitCode> {\n switch (plan.kind) {\n case 'create': {\n const created = await client.call((token) =>\n createTeam(host, token, source, {\n name: plan.name,\n slug: plan.slug,\n ownerEmail: plan.ownerEmail,\n }),\n );\n return ctx.succeed(\n { host, ...created },\n ctx.ui.result({\n title: `Created team ${created.team.slug}`,\n rows: [\n ['Name', created.team.name],\n ['Source', created.source.slug],\n [\n 'Owner',\n created.owner.kind === 'caller'\n ? `you${created.owner.email ? ` (${created.owner.email})` : ''}`\n : `${created.owner.email} — invited; ownership moves to them on accept`,\n ],\n ['Team home', created.teamUrl],\n ],\n notes: [\n `Next: \"ekanos teams members invite ${created.team.slug} <email> --role <role>\" (\"ekanos teams roles list ${created.team.slug}\" lists the roles).`,\n `Then \"ekanos teams connect ${created.team.slug} <product>\" connects an integration for the team.`,\n ],\n }),\n );\n }\n\n case 'members-list': {\n const list = await client.call((token) =>\n listTeamMembers(host, token, { source, team: plan.team }),\n );\n const rows: [string, string][] = list.members.map((member) => [\n member.email ?? member.userId,\n `${member.role}${member.primaryOwner ? ' · primary owner' : ''}${member.status === 'active' ? '' : ` · ${member.status}`}${member.name ? ` · ${member.name}` : ''}`,\n ]);\n for (const invitation of list.invitations) {\n rows.push([\n invitation.email,\n `${invitation.role} · invited, expires ${invitation.expiresAt.slice(0, 10)}`,\n ]);\n }\n return ctx.succeed(\n { host, ...list },\n ctx.ui.result({\n title: `Members of ${list.team.slug} (${list.team.name})`,\n tone: rows.length === 0 ? 'warn' : 'ok',\n rows,\n notes: [\n `\"ekanos teams members invite ${list.team.slug} <email> --role <role>\" adds one.`,\n ],\n }),\n );\n }\n\n case 'members-invite': {\n const invited = await client.call((token) =>\n inviteTeamMember(\n host,\n token,\n { source, team: plan.team },\n { email: plan.email, role: plan.role },\n ),\n );\n return ctx.succeed(\n { host, ...invited },\n ctx.ui.result({\n title: `Invited ${invited.invitation.email} to ${invited.team.slug}`,\n rows: [\n ['Role', invited.invitation.role],\n ['Expires', invited.invitation.expiresAt.slice(0, 10)],\n ],\n notes: [\n 'The invitation email is on its way; they join when they accept it.',\n ],\n }),\n );\n }\n\n case 'members-role': {\n const changed = await client.call((token) =>\n setTeamMemberRole(\n host,\n token,\n { source, team: plan.team, email: plan.email },\n plan.role,\n ),\n );\n return ctx.succeed(\n { host, ...changed },\n ctx.ui.result({\n title:\n changed.before === changed.after\n ? `${changed.email} is already ${changed.after} on ${changed.team.slug}`\n : `${changed.email} is now ${changed.after} on ${changed.team.slug}`,\n rows: [\n ['Was', changed.before ?? '—'],\n [\n 'Applies to',\n changed.kind === 'member'\n ? 'their membership'\n : 'their pending invitation',\n ],\n ],\n }),\n );\n }\n\n case 'members-remove': {\n const removed = await client.call((token) =>\n removeTeamMember(host, token, {\n source,\n team: plan.team,\n email: plan.email,\n }),\n );\n return ctx.succeed(\n { host, ...removed },\n ctx.ui.result({\n title:\n removed.kind === 'member'\n ? `Removed ${removed.email} from ${removed.team.slug}`\n : `Withdrew ${removed.email}'s invitation to ${removed.team.slug}`,\n rows: [['Role was', removed.before ?? '—']],\n }),\n );\n }\n\n case 'roles-list': {\n const roles = await client.call((token) =>\n listTeamRoles(host, token, { source, team: plan.team }),\n );\n return ctx.succeed(\n { host, ...roles },\n ctx.ui.result({\n title: `Roles on ${roles.team.slug}`,\n rows: roles.roles.map((role) => [\n `${role.name} (${role.displayName})`,\n role.permissions.length > 0 ? role.permissions : ['no permissions'],\n ]),\n notes: [\n 'Lower roles are listed last. Give one with \"ekanos teams members role <team> <email> <role>\".',\n ],\n }),\n );\n }\n\n case 'connect':\n return runTeamConnect(ctx, args, client, host, source, {\n team: plan.team,\n product: plan.product,\n as: plan.as,\n });\n }\n}\n\nfunction noExtra(extra: readonly string[]) {\n if (extra.length > 0) {\n throw usageError(\n `Unexpected argument \"${extra[0]}\".`,\n 'See \"ekanos teams --help\".',\n );\n }\n}\n\nfunction slugOf(value: string | undefined, what: 'team' | 'product'): string {\n const slug = value?.trim().toLowerCase();\n if (slug && /^[a-z0-9][a-z0-9-]*$/.test(slug)) return slug;\n throw usageError(\n value ? `\"${value}\" is not a ${what} slug.` : `Name the ${what}.`,\n what === 'team'\n ? '\"ekanos teams list\" lists the teams, e.g. \"ekanos teams members list bank-a\".'\n : '\"ekanos catalog\" lists the products, e.g. \"ekanos teams connect bank-a zendesk\".',\n );\n}\n\nfunction emailOf(value: string | undefined): string {\n const email = value?.trim().toLowerCase();\n if (email && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) return email;\n throw usageError(\n value ? `\"${value}\" is not an email address.` : 'Name the person by email.',\n 'e.g. \"ekanos teams members invite bank-a ana@bank-a.com --role member\".',\n );\n}\n\nfunction roleOf(value: string): string {\n const role = value.trim().toLowerCase();\n if (/^[a-z][a-z0-9_-]{0,49}$/.test(role)) return role;\n throw usageError(\n `\"${value}\" is not a role name.`,\n '\"ekanos teams roles list <team>\" lists the roles this Source uses.',\n );\n}\n"]}
1
+ {"version":3,"file":"teams-onboard.js","sourceRoot":"","sources":["../../src/commands/teams-onboard.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CliContext } from '../context';\nimport { invalidStateError, usageError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport {\n createTeam,\n disconnectTeamIntegration,\n inviteTeamMember,\n listTeamMembers,\n listTeamRoles,\n removeTeamMember,\n renameTeam,\n setTeamMemberRole,\n} from '../teams-api';\nimport type { TeamsArgs, TeamsClient } from './teams';\nimport { runTeamConnect } from './teams-connect';\n\n/**\n * Onboarding a team from the terminal, for the Source admin: `teams create`,\n * `teams members list|invite|role|remove`, `teams roles list`,\n * `teams connect` and `teams disconnect`. Parsed before any session is touched (`parseOnboarding`)\n * so a usage error never costs a network round-trip, then run against the\n * session `runTeams` resolved.\n */\n\nexport const ONBOARDING_SUBCOMMANDS = [\n 'create',\n 'rename',\n 'members',\n 'roles',\n 'connect',\n 'disconnect',\n] as const;\nexport type OnboardingSubcommand = (typeof ONBOARDING_SUBCOMMANDS)[number];\n\nexport interface OnboardingFlags {\n slug?: string;\n owner?: string;\n role?: string;\n /** `connect --as <member-email>`: the member who signs in. */\n as?: string;\n yes: boolean;\n}\n\nexport type OnboardingPlan =\n | { kind: 'create'; name: string; slug?: string; ownerEmail?: string }\n | { kind: 'rename'; team: string; name: string }\n | { kind: 'members-list'; team: string }\n | { kind: 'members-invite'; team: string; email: string; role: string }\n | { kind: 'members-role'; team: string; email: string; role: string }\n | { kind: 'members-remove'; team: string; email: string }\n | { kind: 'roles-list'; team: string }\n | { kind: 'connect'; team: string; product: string; as?: string }\n | { kind: 'disconnect'; team: string; product: string };\n\nconst MEMBERS_VERBS = ['list', 'invite', 'role', 'remove'] as const;\n\nexport function isOnboardingSubcommand(\n value: string,\n): value is OnboardingSubcommand {\n return (ONBOARDING_SUBCOMMANDS as readonly string[]).includes(value);\n}\n\nexport function parseOnboarding(\n subcommand: OnboardingSubcommand,\n rest: readonly string[],\n flags: OnboardingFlags,\n): OnboardingPlan {\n if (subcommand === 'create') {\n const [name, ...extra] = rest;\n if (!name?.trim()) {\n throw usageError(\n 'Name the team.',\n 'Run \"ekanos teams create \\\\\"Bank A\\\\\" [--slug bank-a] [--owner <email>]\".',\n );\n }\n noExtra(extra);\n return {\n kind: 'create',\n name: name.trim(),\n slug: flags.slug === undefined ? undefined : slugOf(flags.slug, 'team'),\n ownerEmail: flags.owner === undefined ? undefined : emailOf(flags.owner),\n };\n }\n\n if (subcommand === 'rename') {\n const [team, name, ...extra] = rest;\n const teamSlug = slugOf(team, 'team');\n if (!name?.trim()) {\n throw usageError(\n 'Name the team’s new name.',\n `Run \"ekanos teams rename ${teamSlug} \\\\\"Bank A Support\\\\\"\".`,\n );\n }\n noExtra(extra);\n return { kind: 'rename', team: teamSlug, name: name.trim() };\n }\n\n if (subcommand === 'connect') {\n const [team, product, ...extra] = rest;\n noExtra(extra);\n return {\n kind: 'connect',\n team: slugOf(team, 'team'),\n product: slugOf(product, 'product'),\n ...(flags.as === undefined ? {} : { as: emailOf(flags.as) }),\n };\n }\n\n if (subcommand === 'disconnect') {\n const [team, product, ...extra] = rest;\n noExtra(extra);\n const teamSlug = slugOf(team, 'team');\n const productSlug = slugOf(product, 'product');\n if (!flags.yes) {\n throw invalidStateError(\n `Disconnecting ${productSlug} from ${teamSlug} removes the team's connection and its tokens: every widget, workflow and agent of the team that uses it stops until someone connects it again. The team's own app (its saved fields) stays.`,\n `Re-run with --yes: ekanos teams disconnect ${teamSlug} ${productSlug} --yes`,\n );\n }\n return { kind: 'disconnect', team: teamSlug, product: productSlug };\n }\n\n if (subcommand === 'roles') {\n const [verb, team, ...extra] = rest;\n if (verb !== 'list') {\n throw usageError(\n verb\n ? `Unknown teams roles subcommand \"${verb}\".`\n : 'teams roles needs a subcommand.',\n 'Run \"ekanos teams roles list <team>\".',\n );\n }\n noExtra(extra);\n return { kind: 'roles-list', team: slugOf(team, 'team') };\n }\n\n const [verb, team, email, role, ...extra] = rest;\n const match = MEMBERS_VERBS.find((name) => name === verb);\n if (!match) {\n throw usageError(\n verb\n ? `Unknown teams members subcommand \"${verb}\".`\n : 'teams members needs a subcommand.',\n 'Run one of: ekanos teams members list <team>, ekanos teams members invite <team> <email> --role <role>, ekanos teams members role <team> <email> <role>, ekanos teams members remove <team> <email> --yes.',\n );\n }\n noExtra(extra);\n\n if (match === 'list') {\n if (email !== undefined) noExtra([email]);\n return { kind: 'members-list', team: slugOf(team, 'team') };\n }\n\n const teamSlug = slugOf(team, 'team');\n const address = emailOf(email);\n\n if (match === 'invite') {\n if (role !== undefined) noExtra([role]);\n return {\n kind: 'members-invite',\n team: teamSlug,\n email: address,\n role: roleOf(flags.role ?? 'member'),\n };\n }\n\n if (match === 'role') {\n const named = role ?? flags.role;\n if (!named) {\n throw usageError(\n 'Name the new role.',\n `Run \"ekanos teams members role ${teamSlug} ${address} <role>\"; \"ekanos teams roles list ${teamSlug}\" lists them.`,\n );\n }\n return {\n kind: 'members-role',\n team: teamSlug,\n email: address,\n role: roleOf(named),\n };\n }\n\n if (role !== undefined) noExtra([role]);\n if (!flags.yes) {\n throw invalidStateError(\n `Removing ${address} from ${teamSlug} ends their access to the team (a pending invitation is withdrawn instead).`,\n `Re-run with --yes: ekanos teams members remove ${teamSlug} ${address} --yes`,\n );\n }\n return { kind: 'members-remove', team: teamSlug, email: address };\n}\n\nexport async function runOnboarding(\n ctx: CliContext,\n args: TeamsArgs,\n client: TeamsClient,\n host: string,\n source: string,\n plan: OnboardingPlan,\n): Promise<ExitCode> {\n switch (plan.kind) {\n case 'create': {\n const created = await client.call((token) =>\n createTeam(host, token, source, {\n name: plan.name,\n slug: plan.slug,\n ownerEmail: plan.ownerEmail,\n }),\n );\n return ctx.succeed(\n { host, ...created },\n ctx.ui.result({\n title: `Created team ${created.team.slug}`,\n rows: [\n ['Name', created.team.name],\n ['Source', created.source.slug],\n [\n 'Owner',\n created.owner.kind === 'caller'\n ? `you${created.owner.email ? ` (${created.owner.email})` : ''}`\n : `${created.owner.email} — invited; ownership moves to them on accept`,\n ],\n ['Team home', created.teamUrl],\n ],\n notes: [\n `Next: \"ekanos teams members invite ${created.team.slug} <email> --role <role>\" (\"ekanos teams roles list ${created.team.slug}\" lists the roles).`,\n `Then \"ekanos teams connect ${created.team.slug} <product>\" connects an integration for the team.`,\n ],\n }),\n );\n }\n\n case 'rename': {\n const renamed = await client.call((token) =>\n renameTeam(host, token, { source, team: plan.team }, plan.name),\n );\n const moved = renamed.team.slug !== renamed.previous.slug;\n return ctx.succeed(\n { host, ...renamed },\n ctx.ui.result({\n title:\n renamed.team.name === renamed.previous.name\n ? `${renamed.team.slug} is already named ${renamed.team.name}`\n : `Renamed ${renamed.previous.slug} to ${renamed.team.name}`,\n rows: [\n ['Name', renamed.team.name],\n ['Slug', renamed.team.slug],\n ['Team home', renamed.teamUrl],\n ],\n notes: moved\n ? [\n `The slug followed the name: use \"${renamed.team.slug}\" from now on. Links and scripts naming \"${renamed.previous.slug}\" no longer reach the team.`,\n ]\n : [],\n tone: moved ? 'warn' : 'ok',\n }),\n );\n }\n\n case 'members-list': {\n const list = await client.call((token) =>\n listTeamMembers(host, token, { source, team: plan.team }),\n );\n const rows: [string, string][] = list.members.map((member) => [\n member.email ?? member.userId,\n `${member.role}${member.primaryOwner ? ' · primary owner' : ''}${member.status === 'active' ? '' : ` · ${member.status}`}${member.name ? ` · ${member.name}` : ''}`,\n ]);\n for (const invitation of list.invitations) {\n rows.push([\n invitation.email,\n `${invitation.role} · invited, expires ${invitation.expiresAt.slice(0, 10)}`,\n ]);\n }\n return ctx.succeed(\n { host, ...list },\n ctx.ui.result({\n title: `Members of ${list.team.slug} (${list.team.name})`,\n tone: rows.length === 0 ? 'warn' : 'ok',\n rows,\n notes: [\n `\"ekanos teams members invite ${list.team.slug} <email> --role <role>\" adds one.`,\n ],\n }),\n );\n }\n\n case 'members-invite': {\n const invited = await client.call((token) =>\n inviteTeamMember(\n host,\n token,\n { source, team: plan.team },\n { email: plan.email, role: plan.role },\n ),\n );\n return ctx.succeed(\n { host, ...invited },\n ctx.ui.result({\n title: `Invited ${invited.invitation.email} to ${invited.team.slug}`,\n rows: [\n ['Role', invited.invitation.role],\n ['Expires', invited.invitation.expiresAt.slice(0, 10)],\n ],\n notes: [\n 'The invitation email is on its way; they join when they accept it.',\n ],\n }),\n );\n }\n\n case 'members-role': {\n const changed = await client.call((token) =>\n setTeamMemberRole(\n host,\n token,\n { source, team: plan.team, email: plan.email },\n plan.role,\n ),\n );\n return ctx.succeed(\n { host, ...changed },\n ctx.ui.result({\n title:\n changed.before === changed.after\n ? `${changed.email} is already ${changed.after} on ${changed.team.slug}`\n : `${changed.email} is now ${changed.after} on ${changed.team.slug}`,\n rows: [\n ['Was', changed.before ?? '—'],\n [\n 'Applies to',\n changed.kind === 'member'\n ? 'their membership'\n : 'their pending invitation',\n ],\n ],\n }),\n );\n }\n\n case 'members-remove': {\n const removed = await client.call((token) =>\n removeTeamMember(host, token, {\n source,\n team: plan.team,\n email: plan.email,\n }),\n );\n return ctx.succeed(\n { host, ...removed },\n ctx.ui.result({\n title:\n removed.kind === 'member'\n ? `Removed ${removed.email} from ${removed.team.slug}`\n : `Withdrew ${removed.email}'s invitation to ${removed.team.slug}`,\n rows: [['Role was', removed.before ?? '—']],\n }),\n );\n }\n\n case 'roles-list': {\n const roles = await client.call((token) =>\n listTeamRoles(host, token, { source, team: plan.team }),\n );\n return ctx.succeed(\n { host, ...roles },\n ctx.ui.result({\n title: `Roles on ${roles.team.slug}`,\n rows: roles.roles.map((role) => [\n `${role.name} (${role.displayName})`,\n role.permissions.length > 0 ? role.permissions : ['no permissions'],\n ]),\n notes: [\n 'Lower roles are listed last. Give one with \"ekanos teams members role <team> <email> <role>\".',\n ],\n }),\n );\n }\n\n case 'disconnect': {\n const done = await client.call((token) =>\n disconnectTeamIntegration(host, token, {\n source,\n team: plan.team,\n product: plan.product,\n }),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: done.wasConnected\n ? `Disconnected ${done.product.name} from ${done.team.slug}`\n : `${done.team.slug} had no ${done.product.name} connection; cleared what was left`,\n tone: 'warn',\n notes: [\n `Connect it again with \"ekanos teams connect ${done.team.slug} ${done.product.slug}\".`,\n ],\n }),\n );\n }\n\n case 'connect':\n return runTeamConnect(ctx, args, client, host, source, {\n team: plan.team,\n product: plan.product,\n as: plan.as,\n ...(args.connection ? { connection: args.connection } : {}),\n });\n }\n}\n\nfunction noExtra(extra: readonly string[]) {\n if (extra.length > 0) {\n throw usageError(\n `Unexpected argument \"${extra[0]}\".`,\n 'See \"ekanos teams --help\".',\n );\n }\n}\n\nfunction slugOf(value: string | undefined, what: 'team' | 'product'): string {\n const slug = value?.trim().toLowerCase();\n if (slug && /^[a-z0-9][a-z0-9-]*$/.test(slug)) return slug;\n throw usageError(\n value ? `\"${value}\" is not a ${what} slug.` : `Name the ${what}.`,\n what === 'team'\n ? '\"ekanos teams list\" lists the teams, e.g. \"ekanos teams members list bank-a\".'\n : '\"ekanos catalog\" lists the products, e.g. \"ekanos teams connect bank-a zendesk\".',\n );\n}\n\nfunction emailOf(value: string | undefined): string {\n const email = value?.trim().toLowerCase();\n if (email && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) return email;\n throw usageError(\n value ? `\"${value}\" is not an email address.` : 'Name the person by email.',\n 'e.g. \"ekanos teams members invite bank-a ana@bank-a.com --role member\".',\n );\n}\n\nfunction roleOf(value: string): string {\n const role = value.trim().toLowerCase();\n if (/^[a-z][a-z0-9_-]{0,49}$/.test(role)) return role;\n throw usageError(\n `\"${value}\" is not a role name.`,\n '\"ekanos teams roles list <team>\" lists the roles this Source uses.',\n );\n}\n"]}