@ekanos/cli 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. package/README.md +103 -8
  2. package/dist/auth/ekanos-api.d.ts +23 -0
  3. package/dist/auth/ekanos-api.js +33 -6
  4. package/dist/auth/ekanos-api.js.map +1 -1
  5. package/dist/commands/add.d.ts +2 -0
  6. package/dist/commands/add.js +118 -0
  7. package/dist/commands/add.js.map +1 -0
  8. package/dist/commands/agents.js +3 -2
  9. package/dist/commands/agents.js.map +1 -1
  10. package/dist/commands/apps.d.ts +11 -3
  11. package/dist/commands/apps.js +86 -28
  12. package/dist/commands/apps.js.map +1 -1
  13. package/dist/commands/audiences.d.ts +31 -0
  14. package/dist/commands/audiences.js +239 -0
  15. package/dist/commands/audiences.js.map +1 -0
  16. package/dist/commands/build.d.ts +2 -0
  17. package/dist/commands/build.js +41 -0
  18. package/dist/commands/build.js.map +1 -0
  19. package/dist/commands/catalog.d.ts +4 -2
  20. package/dist/commands/catalog.js +166 -35
  21. package/dist/commands/catalog.js.map +1 -1
  22. package/dist/commands/check.d.ts +2 -0
  23. package/dist/commands/check.js +43 -0
  24. package/dist/commands/check.js.map +1 -0
  25. package/dist/commands/codegen.d.ts +2 -0
  26. package/dist/commands/codegen.js +49 -0
  27. package/dist/commands/codegen.js.map +1 -0
  28. package/dist/commands/contract.d.ts +52 -0
  29. package/dist/commands/contract.js +300 -0
  30. package/dist/commands/contract.js.map +1 -0
  31. package/dist/commands/dev.d.ts +7 -0
  32. package/dist/commands/dev.js +186 -12
  33. package/dist/commands/dev.js.map +1 -1
  34. package/dist/commands/index-experience.d.ts +31 -0
  35. package/dist/commands/index-experience.js +21 -0
  36. package/dist/commands/index-experience.js.map +1 -0
  37. package/dist/commands/init.d.ts +7 -0
  38. package/dist/commands/init.js +12 -0
  39. package/dist/commands/init.js.map +1 -1
  40. package/dist/commands/login.d.ts +2 -0
  41. package/dist/commands/login.js +17 -0
  42. package/dist/commands/login.js.map +1 -1
  43. package/dist/commands/new.d.ts +2 -0
  44. package/dist/commands/new.js +39 -0
  45. package/dist/commands/new.js.map +1 -0
  46. package/dist/commands/publish.d.ts +59 -0
  47. package/dist/commands/publish.js +118 -65
  48. package/dist/commands/publish.js.map +1 -1
  49. package/dist/commands/runs.d.ts +7 -3
  50. package/dist/commands/runs.js +21 -5
  51. package/dist/commands/runs.js.map +1 -1
  52. package/dist/commands/scope-notice.d.ts +13 -0
  53. package/dist/commands/scope-notice.js +12 -4
  54. package/dist/commands/scope-notice.js.map +1 -1
  55. package/dist/commands/sources-roles.d.ts +5 -0
  56. package/dist/commands/sources-roles.js +235 -0
  57. package/dist/commands/sources-roles.js.map +1 -0
  58. package/dist/commands/sources.d.ts +5 -0
  59. package/dist/commands/sources.js +8 -1
  60. package/dist/commands/sources.js.map +1 -1
  61. package/dist/commands/sync.d.ts +2 -0
  62. package/dist/commands/sync.js +150 -0
  63. package/dist/commands/sync.js.map +1 -0
  64. package/dist/commands/team-agent-readiness.d.ts +18 -2
  65. package/dist/commands/team-agent-readiness.js +39 -39
  66. package/dist/commands/team-agent-readiness.js.map +1 -1
  67. package/dist/commands/team-agents-agents.d.ts +5 -2
  68. package/dist/commands/team-agents-agents.js +152 -15
  69. package/dist/commands/team-agents-agents.js.map +1 -1
  70. package/dist/commands/team-agents-define.d.ts +31 -0
  71. package/dist/commands/team-agents-define.js +176 -0
  72. package/dist/commands/team-agents-define.js.map +1 -0
  73. package/dist/commands/team-agents-mcp.js +112 -10
  74. package/dist/commands/team-agents-mcp.js.map +1 -1
  75. package/dist/commands/team-agents-triggers.d.ts +1 -1
  76. package/dist/commands/team-agents-triggers.js +137 -5
  77. package/dist/commands/team-agents-triggers.js.map +1 -1
  78. package/dist/commands/team-agents.d.ts +4 -1
  79. package/dist/commands/team-agents.js +17 -4
  80. package/dist/commands/team-agents.js.map +1 -1
  81. package/dist/commands/team-llm-key.d.ts +14 -0
  82. package/dist/commands/team-llm-key.js +122 -0
  83. package/dist/commands/team-llm-key.js.map +1 -0
  84. package/dist/commands/teams-audience.d.ts +12 -0
  85. package/dist/commands/teams-audience.js +144 -0
  86. package/dist/commands/teams-audience.js.map +1 -0
  87. package/dist/commands/teams-connect.js +123 -31
  88. package/dist/commands/teams-connect.js.map +1 -1
  89. package/dist/commands/teams-lifecycle.d.ts +90 -0
  90. package/dist/commands/teams-lifecycle.js +457 -0
  91. package/dist/commands/teams-lifecycle.js.map +1 -0
  92. package/dist/commands/teams-onboard.d.ts +14 -0
  93. package/dist/commands/teams-onboard.js +62 -13
  94. package/dist/commands/teams-onboard.js.map +1 -1
  95. package/dist/commands/teams-overview.js +6 -2
  96. package/dist/commands/teams-overview.js.map +1 -1
  97. package/dist/commands/teams-scope.js +4 -0
  98. package/dist/commands/teams-scope.js.map +1 -1
  99. package/dist/commands/teams.d.ts +25 -5
  100. package/dist/commands/teams.js +106 -39
  101. package/dist/commands/teams.js.map +1 -1
  102. package/dist/commands/workflows.d.ts +37 -0
  103. package/dist/commands/workflows.js +589 -0
  104. package/dist/commands/workflows.js.map +1 -0
  105. package/dist/compatibility.d.ts +10 -1
  106. package/dist/compatibility.js +10 -1
  107. package/dist/compatibility.js.map +1 -1
  108. package/dist/connect-fields.d.ts +22 -0
  109. package/dist/connect-fields.js +115 -0
  110. package/dist/connect-fields.js.map +1 -0
  111. package/dist/context.d.ts +12 -0
  112. package/dist/context.js +32 -9
  113. package/dist/context.js.map +1 -1
  114. package/dist/dev-experience.d.ts +125 -0
  115. package/dist/dev-experience.js +128 -0
  116. package/dist/dev-experience.js.map +1 -0
  117. package/dist/experience/boundary.d.ts +12 -0
  118. package/dist/experience/boundary.js +260 -0
  119. package/dist/experience/boundary.js.map +1 -0
  120. package/dist/experience/build.d.ts +16 -0
  121. package/dist/experience/build.js +90 -0
  122. package/dist/experience/build.js.map +1 -0
  123. package/dist/experience/checks.d.ts +29 -0
  124. package/dist/experience/checks.js +133 -0
  125. package/dist/experience/checks.js.map +1 -0
  126. package/dist/experience/contract-sources.d.ts +36 -0
  127. package/dist/experience/contract-sources.js +111 -0
  128. package/dist/experience/contract-sources.js.map +1 -0
  129. package/dist/experience/definition-checks.d.ts +26 -0
  130. package/dist/experience/definition-checks.js +201 -0
  131. package/dist/experience/definition-checks.js.map +1 -0
  132. package/dist/experience/definition-shape.d.ts +60 -0
  133. package/dist/experience/definition-shape.js +2 -0
  134. package/dist/experience/definition-shape.js.map +1 -0
  135. package/dist/experience/init.d.ts +10 -0
  136. package/dist/experience/init.js +64 -0
  137. package/dist/experience/init.js.map +1 -0
  138. package/dist/experience/integrations-codegen.d.ts +17 -0
  139. package/dist/experience/integrations-codegen.js +51 -0
  140. package/dist/experience/integrations-codegen.js.map +1 -0
  141. package/dist/experience/json-schema-to-ts.d.ts +1 -0
  142. package/dist/experience/json-schema-to-ts.js +90 -0
  143. package/dist/experience/json-schema-to-ts.js.map +1 -0
  144. package/dist/experience/load-experience.d.ts +23 -0
  145. package/dist/experience/load-experience.js +115 -0
  146. package/dist/experience/load-experience.js.map +1 -0
  147. package/dist/experience/overrides.d.ts +8 -0
  148. package/dist/experience/overrides.js +21 -0
  149. package/dist/experience/overrides.js.map +1 -0
  150. package/dist/experience/pin-integration.d.ts +8 -0
  151. package/dist/experience/pin-integration.js +17 -0
  152. package/dist/experience/pin-integration.js.map +1 -0
  153. package/dist/experience/pin-ops.d.ts +12 -0
  154. package/dist/experience/pin-ops.js +36 -0
  155. package/dist/experience/pin-ops.js.map +1 -0
  156. package/dist/experience/pins.d.ts +35 -0
  157. package/dist/experience/pins.js +91 -0
  158. package/dist/experience/pins.js.map +1 -0
  159. package/dist/experience/project.d.ts +52 -0
  160. package/dist/experience/project.js +149 -0
  161. package/dist/experience/project.js.map +1 -0
  162. package/dist/experience/publish.d.ts +51 -0
  163. package/dist/experience/publish.js +144 -0
  164. package/dist/experience/publish.js.map +1 -0
  165. package/dist/experience/regenerate.d.ts +10 -0
  166. package/dist/experience/regenerate.js +33 -0
  167. package/dist/experience/regenerate.js.map +1 -0
  168. package/dist/experience/report.d.ts +9 -0
  169. package/dist/experience/report.js +23 -0
  170. package/dist/experience/report.js.map +1 -0
  171. package/dist/harness-scaffold.d.ts +52 -18
  172. package/dist/harness-scaffold.js +189 -9
  173. package/dist/harness-scaffold.js.map +1 -1
  174. package/dist/index.d.ts +13 -0
  175. package/dist/index.js +494 -127
  176. package/dist/index.js.map +1 -1
  177. package/dist/invocation.d.ts +31 -0
  178. package/dist/invocation.js +58 -0
  179. package/dist/invocation.js.map +1 -0
  180. package/dist/project-checks.d.ts +12 -0
  181. package/dist/project-checks.js +46 -0
  182. package/dist/project-checks.js.map +1 -1
  183. package/dist/project.d.ts +14 -0
  184. package/dist/project.js +10 -0
  185. package/dist/project.js.map +1 -1
  186. package/dist/repo/publish.d.ts +42 -0
  187. package/dist/repo/publish.js +225 -0
  188. package/dist/repo/publish.js.map +1 -0
  189. package/dist/repo/scaffold.d.ts +30 -0
  190. package/dist/repo/scaffold.js +165 -0
  191. package/dist/repo/scaffold.js.map +1 -0
  192. package/dist/runs-api.js +8 -3
  193. package/dist/runs-api.js.map +1 -1
  194. package/dist/safe-fs.d.ts +18 -0
  195. package/dist/safe-fs.js +57 -0
  196. package/dist/safe-fs.js.map +1 -1
  197. package/dist/secret-form.d.ts +48 -0
  198. package/dist/secret-form.js +212 -0
  199. package/dist/secret-form.js.map +1 -0
  200. package/dist/secret-input.d.ts +96 -0
  201. package/dist/secret-input.js +299 -0
  202. package/dist/secret-input.js.map +1 -0
  203. package/dist/team-connect-api.d.ts +78 -3
  204. package/dist/team-connect-api.js +17 -2
  205. package/dist/team-connect-api.js.map +1 -1
  206. package/dist/team-lifecycle-api.d.ts +435 -0
  207. package/dist/team-lifecycle-api.js +301 -0
  208. package/dist/team-lifecycle-api.js.map +1 -0
  209. package/dist/teams-api.d.ts +49 -1
  210. package/dist/teams-api.js +149 -27
  211. package/dist/teams-api.js.map +1 -1
  212. package/dist/unknown-command.d.ts +18 -0
  213. package/dist/unknown-command.js +50 -0
  214. package/dist/unknown-command.js.map +1 -0
  215. package/dist/validate-findings.js +2 -1
  216. package/dist/validate-findings.js.map +1 -1
  217. package/dist/workflows-api.d.ts +69 -0
  218. package/dist/workflows-api.js +182 -0
  219. package/dist/workflows-api.js.map +1 -0
  220. package/package.json +3 -3
  221. package/templates/AGENTS.md.tmpl +6 -4
  222. package/templates/claude-skill.md.tmpl +4 -1
  223. package/templates/ekanos.json.tmpl +1 -0
  224. package/templates/experience/AGENTS.md.tmpl +22 -0
  225. package/templates/experience/ekanos.json.tmpl +7 -0
  226. package/templates/experience/ekanos.lock.json.tmpl +4 -0
  227. package/templates/experience/eslint.config.mjs.tmpl +25 -0
  228. package/templates/experience/gitignore.tmpl +17 -0
  229. package/templates/experience/package.json.tmpl +41 -0
  230. package/templates/experience/src/.ekanos/integrations.d.ts.tmpl +3 -0
  231. package/templates/experience/src/experience.ts.tmpl +30 -0
  232. package/templates/experience/src/widgets/hello-widget.tsx.tmpl +40 -0
  233. package/templates/experience/tsconfig.json.tmpl +20 -0
  234. package/templates/harness/app/%5F%5Fekanos/api/[...path]/route.ts.tmpl +9 -0
  235. package/templates/harness/app/[slug]/activation/page.tsx.tmpl +1 -1
  236. package/templates/harness/app/[slug]/page.tsx.tmpl +1 -1
  237. package/templates/harness/app/[slug]/tile/page.tsx.tmpl +1 -1
  238. package/templates/harness/app/[slug]/triggers/page.tsx.tmpl +1 -1
  239. package/templates/harness/app/[slug]/widgets/[widgetId]/page.tsx.tmpl +1 -1
  240. package/templates/harness/app/[slug]/widgets/page.tsx.tmpl +1 -1
  241. package/templates/harness/app/experience/layout.tsx.tmpl +17 -0
  242. package/templates/harness/app/experience/page.tsx.tmpl +1 -0
  243. package/templates/harness/app/experience/pages/[id]/page.tsx.tmpl +1 -0
  244. package/templates/harness/app/experience/review-queue/page.tsx.tmpl +1 -0
  245. package/templates/harness/app/experience/runs/page.tsx.tmpl +1 -0
  246. package/templates/harness/app/experience/widgets/[id]/page.tsx.tmpl +1 -0
  247. package/templates/harness/app/experience/widgets/page.tsx.tmpl +1 -0
  248. package/templates/harness/app/experience/workflows/[id]/page.tsx.tmpl +1 -0
  249. package/templates/harness/app/experience/workflows/page.tsx.tmpl +1 -0
  250. package/templates/harness/app/integrations/[slug]/connect/page.tsx.tmpl +1 -0
  251. package/templates/harness/app/integrations/[slug]/events/page.tsx.tmpl +1 -0
  252. package/templates/harness/app/integrations/[slug]/health/page.tsx.tmpl +1 -0
  253. package/templates/harness/app/integrations/[slug]/operations/[kind]/[name]/page.tsx.tmpl +1 -0
  254. package/templates/harness/app/integrations/[slug]/operations/page.tsx.tmpl +1 -0
  255. package/templates/harness/app/integrations/[slug]/page.tsx.tmpl +1 -0
  256. package/templates/harness/app/integrations/[slug]/preview/activation/page.tsx.tmpl +1 -0
  257. package/templates/harness/app/integrations/[slug]/preview/layout.tsx.tmpl +1 -0
  258. package/templates/harness/app/integrations/[slug]/preview/page.tsx.tmpl +1 -0
  259. package/templates/harness/app/integrations/[slug]/preview/tile/page.tsx.tmpl +1 -0
  260. package/templates/harness/app/integrations/[slug]/preview/triggers/page.tsx.tmpl +1 -0
  261. package/templates/harness/app/integrations/[slug]/preview/widgets/[widgetId]/page.tsx.tmpl +1 -0
  262. package/templates/harness/app/integrations/[slug]/preview/widgets/page.tsx.tmpl +1 -0
  263. package/templates/harness/app/integrations/[slug]/runs/page.tsx.tmpl +1 -0
  264. package/templates/harness/app/integrations/layout.tsx.tmpl +1 -0
  265. package/templates/harness/app/integrations/page.tsx.tmpl +1 -0
  266. package/templates/harness/app/page.experience.tsx.tmpl +5 -0
  267. package/templates/harness/repo/app/%5F%5Fekanos/api/[...path]/route.ts.tmpl +11 -0
  268. package/templates/harness/repo/app/(repo)/connections/page.tsx.tmpl +1 -0
  269. package/templates/harness/repo/app/(repo)/layout.tsx.tmpl +1 -0
  270. package/templates/harness/repo/app/(repo)/page.tsx.tmpl +1 -0
  271. package/templates/harness/repo/app/experiences/[name]/connect/page.tsx.tmpl +1 -0
  272. package/templates/harness/repo/app/experiences/[name]/layout.tsx.tmpl +9 -0
  273. package/templates/harness/repo/app/experiences/page.tsx.tmpl +5 -0
  274. package/templates/harness/repo/app/harness-shell.tsx.tmpl +9 -0
  275. package/templates/harness/repo/app/integrations/[slug]/layout.tsx.tmpl +1 -0
  276. package/templates/harness/repo/app/integrations/page.tsx.tmpl +5 -0
  277. package/templates/harness/repo/app/repo-experiences.ts.tmpl +5 -0
  278. package/templates/harness/styles/globals.css.tmpl +15 -1
  279. package/templates/package.json.tmpl +4 -4
  280. package/templates/skills/build-agent/SKILL.md +43 -10
  281. package/templates/skills/build-agent/references/agent-json.md +4 -1
  282. package/templates/skills/build-agent/references/app-setup.md +14 -7
  283. package/templates/skills/build-agent/references/rollout.md +26 -2
  284. package/templates/skills/build-agent/references/set-up-an-integration.md +46 -29
  285. package/templates/skills/build-integration/references/widget-design.md +1 -1
  286. package/templates/skills/ekanos-platform/SKILL.md +66 -14
  287. package/templates/skills/polish-widgets/references/patterns.md +3 -3
@@ -0,0 +1,17 @@
1
+ 'use client';
2
+
3
+ import { ConsoleLayout } from '@ekanos/harness/routes';
4
+
5
+ import experience from __EXPERIENCE_ENTRY__;
6
+
7
+ export default function ExperienceLayout(props: { children: React.ReactNode }) {
8
+ return (
9
+ <ConsoleLayout
10
+ experience={{
11
+ widgets: experience.widgets ?? [],
12
+ pages: experience.pages ?? [],
13
+ }}
14
+ {...props}
15
+ />
16
+ );
17
+ }
@@ -0,0 +1 @@
1
+ export { ExperienceSummaryPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { ExperiencePageHost as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { ExperienceReviewQueuePage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { ExperienceRunsPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { ExperienceWidgetPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { ExperienceWidgetsPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { ExperienceWorkflowPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { ExperienceWorkflowsPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { IntegrationConnectPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { IntegrationEventsPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { IntegrationHealthPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { IntegrationOperationPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { IntegrationOperationsPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { IntegrationOverviewPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { ActivationPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { PreviewLayout as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { PreviewIndexPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { TilePage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { TriggersPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { SingleWidgetPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { WidgetsPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { IntegrationRunsPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { ConsoleLayout as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { IntegrationsListPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1,5 @@
1
+ import { redirect } from 'next/navigation';
2
+
3
+ export default function HarnessIndex() {
4
+ redirect('/experience');
5
+ }
@@ -0,0 +1,11 @@
1
+ import { createRepoApiHandlers } from '@ekanos/harness/api';
2
+
3
+ // Next treats a leading underscore folder as private, so this directory is
4
+ // literally named `%5F%5Fekanos` and serves /__ekanos/api/*. At a repo root it
5
+ // answers the repo overview and forwards `packages/<kind>/<name>/…` to that
6
+ // package's own harness API.
7
+ const handlers = createRepoApiHandlers();
8
+
9
+ export const GET = handlers.GET;
10
+ export const POST = handlers.POST;
11
+ export const PUT = handlers.PUT;
@@ -0,0 +1 @@
1
+ export { RepoConnectionsPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { RepoLayout as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { RepoHomePage as default } from '@ekanos/harness/routes';
@@ -0,0 +1 @@
1
+ export { ExperienceConnectPage as default } from '@ekanos/harness/routes';
@@ -0,0 +1,9 @@
1
+ 'use client';
2
+
3
+ import { RepoExperienceLayout } from '@ekanos/harness/routes';
4
+
5
+ import { experienceEntries } from '../../repo-experiences';
6
+
7
+ export default function ExperienceLayout(props: { children: React.ReactNode }) {
8
+ return <RepoExperienceLayout entries={experienceEntries} {...props} />;
9
+ }
@@ -0,0 +1,5 @@
1
+ import { redirect } from 'next/navigation';
2
+
3
+ export default function ExperiencesIndex() {
4
+ redirect('/');
5
+ }
@@ -0,0 +1,9 @@
1
+ 'use client';
2
+
3
+ import { RootLayout } from '@ekanos/harness/app';
4
+
5
+ import { harnessIntegrations } from '../../../harness.config';
6
+
7
+ export default function HarnessShell(props: { children: React.ReactNode }) {
8
+ return <RootLayout integrations={harnessIntegrations} repo {...props} />;
9
+ }
@@ -0,0 +1 @@
1
+ export { RepoIntegrationLayout as default } from '@ekanos/harness/routes';
@@ -0,0 +1,5 @@
1
+ import { redirect } from 'next/navigation';
2
+
3
+ export default function IntegrationsIndex() {
4
+ redirect('/');
5
+ }
@@ -0,0 +1,5 @@
1
+ // Generated by `ekanos dev` at a repo root. One entry per experience package:
2
+ // the widgets and pages are React components only the package's own module holds.
3
+ __EXPERIENCE_IMPORTS__
4
+ export const experienceEntries = {
5
+ __EXPERIENCE_ENTRIES__} as const;
@@ -6,7 +6,21 @@
6
6
  * `@ekanos/ui`, `@ekanos/sdk` — is already accounted for inside
7
7
  * `@ekanos/harness/styles.css`, so nothing about the harness needs a glob here.
8
8
  */
9
- @import '@ekanos/harness/styles.css';
9
+ /*
10
+ * `source(none)` turns OFF Tailwind v4's automatic source detection. Left on,
11
+ * it scans everything under this directory — including `.next/`, whose
12
+ * Turbopack cache holds binary `.sst` blocks that contain fragments of our
13
+ * own sources split by control bytes. Those become garbage candidates such as
14
+ * `var(--icon-glyph<ctrl>,16px)`, and the CSS parser then fails with "Parsing
15
+ * CSS source code failed": every page a build-error overlay and every
16
+ * harness API route an HTML 500, recurring whenever the cache is rewritten.
17
+ * Every directory worth scanning is named by an exact `@source` below or
18
+ * inside the harness stylesheet.
19
+ */
20
+ @import '@ekanos/harness/styles.css' source(none);
21
+
22
+ /* The generated shell's own pages — explicit, so `.next/` is never matched. */
23
+ @source '../app/**/*.tsx';
10
24
 
11
25
  /*
12
26
  * Your integration source, and the registry that lists it. A missing @source
@@ -12,12 +12,12 @@
12
12
  "prepare": "node scripts/setup-hooks.mjs"
13
13
  },
14
14
  "dependencies": {
15
- "@ekanos/sdk": "^0.17.0",
16
- "@ekanos/ui": "^0.17.0"
15
+ "@ekanos/sdk": "^0.19.0",
16
+ "@ekanos/ui": "^0.19.0"
17
17
  },
18
18
  "devDependencies": {
19
- "@ekanos/cli": "^0.15.0",
20
- "@ekanos/harness": "^0.17.0",
19
+ "@ekanos/cli": "^0.17.0",
20
+ "@ekanos/harness": "^0.19.0",
21
21
  "@hookform/resolvers": "^5.2.2",
22
22
  "@tailwindcss/postcss": "^4.3.3",
23
23
  "@tanstack/react-query": "^5.101.4",
@@ -39,9 +39,15 @@ installed — so check it, every time (§ 4, "Make it reachable").
39
39
  ## Hard rules
40
40
 
41
41
  - Never ask for, accept or write a secret (API key, client secret, webhook
42
- signing secret). The user types it at their own terminal — `apps set`,
43
- `apps connect`, `teams app set` and `teams connect` ask with hidden input
44
- and refuse an agent run — or a team enters it in the Ekanos app.
42
+ signing secret), and never read one from a file or a variable yourself.
43
+ The user enters it, and it never passes through you: run the command with
44
+ `--browser` (`apps set`, `apps connect`, `teams app set`, `teams connect`,
45
+ `teams mcp token`, `teams llm-key set` take it) and the CLI opens a
46
+ one-time form in their browser on this computer — tell them to fill it in
47
+ there. If they would rather, they put it in an environment variable or a
48
+ file only they can read, and you pass `--secret-env <NAME>` or
49
+ `--secret-file <path>`. Or they type it at their own terminal, or a team
50
+ enters it in the Ekanos app. A secret is never a value on the command line.
45
51
  - Never `publish`, `rollback` or `archive` without the user's explicit yes to
46
52
  that version or agent, after they have seen it. `--yes` records that
47
53
  consent; it is never a way past a question.
@@ -105,7 +111,8 @@ list` to find the role holding `agents.review` for reviewers — see the
105
111
  `ekanos-platform` skill, "Onboarding a team"), and send the member who will
106
112
  sign in the link from `ekanos teams connect <team> <product>`. For the
107
113
  Source's app itself, `references/app-setup.md` has the console walk-through.
108
- Secrets are only ever entered at the user's terminal or in the app.
114
+ Secrets are only ever entered by the user — in the `--browser` form, at
115
+ their terminal, or in the app — never through you.
109
116
 
110
117
  ## 2. The interview
111
118
 
@@ -208,6 +215,32 @@ in parentheses are the recommendation when the user has no preference.
208
215
  team pilots
209
216
  it first, and do § 4 with them.
210
217
 
218
+ ## 3b. Only one team, or only the user: a team's own or a personal agent
219
+
220
+ When the agent is for one team only, or for the user alone (§ 2's rollout
221
+ question, `references/rollout.md`), skip the template: the same files make a
222
+ team's own agent, or with `--personal` the user's own.
223
+
224
+ 1. On their go: `npx @ekanos/cli teams agents create <team> --from agents/<key> --source <slug> --json`
225
+ (add `--personal` for the user's own). The user becomes its creator, so
226
+ they must be an active member of that team; a `NOT_A_TEAM_MEMBER` refusal
227
+ names the command that adds them. Skill folders beside it are pushed as
228
+ that team's skills. Drop any field only a template has (exit 3 lists them).
229
+ 2. It starts as a draft:
230
+ `npx @ekanos/cli teams agents enable <team> <key> --source <slug> --json`.
231
+ Confirm what it may use only with the user's yes (`--confirm-access` on
232
+ `create` or `enable`, or `teams agents confirm <team> <key>`); a personal
233
+ agent's creator alone may.
234
+ 3. Start it from a schedule or a webhook:
235
+ `npx @ekanos/cli teams triggers add <team> <key> schedule --cron "0 8 * * 1-5" --timezone <zone> --prompt "…" --json`
236
+ or `… webhook --prompt "…"`. The webhook's token is saved to a file only
237
+ the user can read — never open or print it; tell them a personal agent's
238
+ token lets whoever holds it make the agent act as them.
239
+ 4. Later changes: edit the files and
240
+ `npx @ekanos/cli teams agents apply <team> agents/<key> --base-version <n> --json`
241
+ (`<n>` from `teams agents show`). Never `--overwrite` a conflict you have
242
+ not shown the user.
243
+
211
244
  ## 4. Make it reachable, and prove it end to end
212
245
 
213
246
  For each team that turns on an agent with a channel trigger, start with
@@ -225,12 +258,12 @@ screen). For the detail behind it:
225
258
  and `agent` (`credentialsSaved`, `connected` = installed, `neededBy`),
226
259
  and the `agent-events` webhook in `teamApps[].webhooks` must have an
227
260
  `endpoint`. Read the state back to the user in those words.
228
- 3. Not installed: the user runs, **in their own terminal** (it asks for the
229
- Linear app's secrets, which you never handle):
230
- `npx @ekanos/cli teams connect <team> linear --connection agent --source <slug>`.
231
- It asks for the app's client ID, secret and webhook signing secret if
232
- missing, opens the install (a Linear workspace admin approves it) and
233
- waits. No webhook URL yet: `npx @ekanos/cli teams webhook <team> linear
261
+ 3. Not installed: run
262
+ `npx @ekanos/cli teams connect <team> linear --connection agent --browser --source <slug>`
263
+ (or the user runs it without `--browser` in their own terminal). If the
264
+ app's client ID, secret or webhook signing secret is missing, it opens a
265
+ form in the user's browser for them to fill — you never handle those —
266
+ then opens the install (a Linear workspace admin approves it) and waits. No webhook URL yet: `npx @ekanos/cli teams webhook <team> linear
234
267
  agent-events --source <slug>` (shown once, and saved to a file only the
235
268
  user can read — the output names it; the user copies it into the Linear
236
269
  app. Never open or print that file yourself).
@@ -56,7 +56,10 @@ conflicting change unless `--overwrite`. Unknown fields are refused.
56
56
  ```
57
57
 
58
58
  The tool names above are illustrations. Take real ones from
59
- `ekanos catalog --json`.
59
+ `ekanos catalog --json`; `ekanos catalog <product> --json` gives each tool's
60
+ `inputSchema` (when a tool needs an id, another tool of the product returns
61
+ it) and the product's `connection` (`connectedBy`, `runsUse`,
62
+ `sourceConnection`).
60
63
 
61
64
  ## Fields
62
65
 
@@ -41,23 +41,30 @@ working from those rather than from Ekanos.
41
41
  the provider's docs rather than guessing.
42
42
  - The last console step is always "copy the client ID and the secret".
43
43
  **Never ask them to paste the secret into the chat.** For the Source's app,
44
- have them run, **in their own terminal**:
44
+ run this yourself, and tell them a form is opening in their browser:
45
45
 
46
46
  ```bash
47
- npx @ekanos/cli apps set <product> --source <slug>
47
+ npx @ekanos/cli apps set <product> --browser --source <slug>
48
48
  ```
49
49
 
50
- It asks for the client ID, then the secret with hidden input; Enter keeps
51
- a saved value, so either can be changed on its own. For a team's
52
- app, they enter the fields in the team's setup panel in the Ekanos app.
50
+ The form asks for the client ID and the secret; a field left empty keeps
51
+ its saved value, so either can be changed on its own. What they type goes
52
+ from their browser to the CLI and on to Ekanos, never to you. (Or they run
53
+ `npx @ekanos/cli apps set <product> --source <slug>` in their own terminal,
54
+ which asks with hidden input.) For a team's app,
55
+ `npx @ekanos/cli teams app set <team> <product> --browser --source <slug>`
56
+ does the same, or they enter the fields in the team's setup panel in the
57
+ Ekanos app.
53
58
  - Then check: `apps show <product> --source <slug> --json` should say
54
59
  `configured: true`, and the catalog's step should be `done`. Tell them
55
60
  teams can now connect, and what the team-side steps are.
56
61
 
57
62
  ## When it goes wrong
58
63
 
59
- - `apps set` says it needs a terminal: it was run inside Claude or a script.
60
- Ask them to run it in a terminal tab themselves.
64
+ - `apps set` says there is no terminal to ask at: add `--browser`. If
65
+ `--browser` is refused (CI, SSH, no display), ask them to run it in a
66
+ terminal tab themselves. The form gives up after five minutes; run it
67
+ again for a fresh one.
61
68
  - `apps set` asks which host: they are signed in to more than one Ekanos;
62
69
  add `--host <url>` (the Source's site) or log out of the other.
63
70
  - Sign-in later fails with a redirect mismatch: the app is missing one of the
@@ -65,11 +65,35 @@ plan is ready.
65
65
 
66
66
  ## A team's own agent
67
67
 
68
- Built by a team in the app (Agents → New). Only that team has it; the Source
69
- cannot update or roll it back, and nothing about it is visible to other teams.
68
+ Built for one team, in the app (Agents → New) or from the terminal with the
69
+ same `agent.json` a template uses:
70
+ `ekanos teams agents create <team> --from agents/<key>` (then
71
+ `ekanos teams agents enable <team> <key>` — it starts as a draft), and
72
+ `ekanos teams agents apply <team> agents/<key> --base-version <n>` to change
73
+ it from the file later. Only that team has it; the Source cannot update or
74
+ roll it back, and nothing about it is visible to other teams. Whoever creates
75
+ it is its creator — its tools run as them — so they must be a member of the
76
+ team who manages its agents. A field only a template has (`connections`,
77
+ `mcpServers`, `teamCustomization`, `triggers`, `links`, `teamOverrides`) is
78
+ refused; add triggers with `ekanos teams triggers add`.
70
79
 
71
80
  Good for: one team's own process; experiments a team owns.
72
81
 
82
+ ## A personal agent
83
+
84
+ One person's agent for themselves: `ekanos teams agents create <team> --from
85
+ agents/<key> --personal`, by a member of that team. It acts for its creator,
86
+ with their own connections, on every trigger, so it is theirs alone: nobody
87
+ else changes it, runs it, decides its approvals or cancels its runs — not a
88
+ team manager, not the Source admin (`PERSONAL_AGENT_CREATOR_ONLY`). Others see
89
+ that it exists, not what its runs read or did. It starts from a schedule or a
90
+ webhook (`ekanos teams triggers add <team> <key> schedule --cron "…" --prompt
91
+ "…"`); whoever holds its webhook token can make it act as its creator, so the
92
+ token goes to a file only they can read, never into a chat.
93
+
94
+ Good for: "brief me on my day", "draft replies to my inbox" — one person's
95
+ own work on their own accounts.
96
+
73
97
  ## Questions that decide it
74
98
 
75
99
  - How many teams do this work? The same way?
@@ -60,19 +60,32 @@ connect nothing for it.
60
60
  `teams show` (or `catalog`) and say what changed ("Ekanos sees the client ID
61
61
  and secret now"). If the check disagrees with what they said, look at the
62
62
  difference with them; don't move on.
63
- - **Secrets never pass through the chat.** Client secrets and signing
64
- secrets go in at the user's own terminal (`ekanos apps set`,
65
- `ekanos teams app set`, with hidden input) or in the team's page in the app.
66
- If they paste one into the chat anyway, tell them to rotate it in the
67
- provider's console and enter the new one at the terminal.
68
- - **Connect with `teams connect <team> <product>`, run by the user in their
69
- own terminal.** It does whatever the integration needs: asks a form's fields
63
+ - **Secrets never pass through the chat, or through you.** Client secrets
64
+ and signing secrets go in through a form in the user's browser that you
65
+ start with `--browser` (`ekanos apps set <product> --browser`,
66
+ `ekanos teams app set <team> <product> --browser`), at the user's own
67
+ terminal with hidden input, or in the team's page in the app. Never read
68
+ one from a file or an environment variable yourself; if the user has put
69
+ one there, pass its name with `--secret-env <NAME>` or its path with
70
+ `--secret-file <path>` and let the CLI read it. If they paste one into the
71
+ chat anyway, tell them to rotate it in the provider's console and enter
72
+ the new one through the form.
73
+ - **Connect with `teams connect <team> <product>`** — add `--browser` when
74
+ you run it, so any field it needs opens as a form in the user's browser;
75
+ without it the user runs it in their own terminal. It does whatever the
76
+ integration needs: asks a form's fields
70
77
  (secrets hidden), runs the team-app prompts first when the team's own app is
71
78
  missing, or opens a one-time sign-in link and waits until the team is
72
- connected. The provider's consent is still a person's click, by a member of
73
- the team (owner/admin for a team-wide connection): the user when they are
74
- one, else `--as <email>` prints a link to send that member. `--link-only`
75
- prints just the team's page. Tell them who should sign in: the account the
79
+ connected. Non-secret fields of any type can be passed with
80
+ `--set <field>=<value>` (a list as `a,b`; secrets and JSON values only at a prompt), so
81
+ it also runs in a script; optional ones can be left out. The provider's
82
+ consent is still a person's click, by a member of the team (owner/admin for
83
+ a team-wide connection): the user when they are one, else `--as <email>`
84
+ prints a link to send that member. A Source admin who is not on the team
85
+ joins it first with `ekanos teams members add <team> --self` (no email). A
86
+ personal product (each person connects their own, such as ROAM) connects
87
+ the account of whoever runs `teams connect`. `--link-only` prints just the
88
+ team's page. Tell them who should sign in: the account the
76
89
  integration acts as. If the product is not enabled for the Source, a
77
90
  super-admin enables it (`sources products` shows what the Source has). A dedicated seat such as "Support agent" makes its replies easy
78
91
  to recognise.
@@ -88,11 +101,12 @@ pilot), the team-side steps can be done from the CLI:
88
101
  1. `npx @ekanos/cli teams show <team> <product> --source <slug>`: the
89
102
  callback URL to register and the integration's steps.
90
103
  2. They create the app in the provider's console, step by step as above.
91
- 3. **In their own terminal:**
92
- `npx @ekanos/cli teams app set <team> <product> --source <slug>`. It asks
93
- for each field and hides the secret ones; Enter keeps a saved value. It
94
- refuses to run inside Claude; that is deliberate. To change one value
95
- later, they need not re-enter the rest:
104
+ 3. Run `npx @ekanos/cli teams app set <team> <product> --browser --source <slug>`
105
+ and tell them a form is opening in their browser: it has every field,
106
+ secrets as password inputs, and a field left empty keeps its saved value.
107
+ What they type never reaches you. (Without `--browser`, they run it in
108
+ their own terminal, which asks for each field and hides the secret ones.)
109
+ To change one value later, they need not re-enter the rest:
96
110
  `teams app set <team> <product> --field <name>` asks for just that field
97
111
  (names are in brackets in `teams show`), `--set <name>=<value>` sets a
98
112
  non-secret field (a subdomain, a client ID) without a prompt — you may run
@@ -122,10 +136,11 @@ mentions arrive. When the agent has any Linear trigger:
122
136
  redirect URIs, webhooks on with **Agent session events** and **Issues**.
123
137
  3. Its webhook URL: `teams webhook <team> linear agent-events` (once; paste
124
138
  it into the Linear app's webhook URL).
125
- 4. **In their own terminal:**
126
- `npx @ekanos/cli teams connect <team> linear --connection agent --source <slug>`
127
- — asks for the client ID, secret and webhook signing secret if any is
128
- missing, opens the install for a Linear workspace admin to approve, and
139
+ 4. `npx @ekanos/cli teams connect <team> linear --connection agent --browser --source <slug>`
140
+ — opens a form in the user's browser for the client ID, secret and
141
+ webhook signing secret if any is missing (without `--browser`, the user
142
+ runs it in their own terminal and it asks there), opens the install for a
143
+ Linear workspace admin to approve, and
129
144
  waits until it is installed. (`teams connect <team> linear` with no
130
145
  `--connection` offers this itself once the personal connection is made,
131
146
  when the team has agents with Linear triggers.)
@@ -146,11 +161,12 @@ the Source's connection.
146
161
  1. **Connect, once, as the Source.** For an integration where each customer
147
162
  brings its own app (Zendesk), first create that app in the shared account,
148
163
  exactly as in the worked example below (OAuth client, Confidential), but
149
- once, for the Source. Then, **in their own terminal**:
150
- `npx @ekanos/cli apps connect <product> --source <slug>`. It asks for the
164
+ once, for the Source. Then run
165
+ `npx @ekanos/cli apps connect <product> --browser --source <slug>` (or the
166
+ user runs it without `--browser` in their own terminal). It asks for the
151
167
  app's fields it doesn't have yet (Zendesk: subdomain, client ID, client
152
- secret, webhook signing secret; secrets hidden, never as flags, and it
153
- refuses to run inside Claude), prints the redirect URL to register and the
168
+ secret, webhook signing secret) in a form in the user's browser — never
169
+ through you, never as values on the command line — prints the redirect URL to register and the
154
170
  consent link, then waits up to ten minutes until it is connected. Whoever
155
171
  clicks the link is the account the integration acts as for every team, so
156
172
  suggest a dedicated seat ("Support agent"). `apps list` shows every
@@ -201,9 +217,9 @@ from `teams show zendesk`.
201
217
  Center › Apps and integrations › Webhooks › Create webhook › Trigger or
202
218
  automation: that URL, POST, JSON, no authentication. Open it and Reveal
203
219
  secret.
204
- 3. **Credentials into Ekanos.** `ekanos teams app set <team> zendesk` in
205
- their terminal: subdomain, client ID, client secret, webhook signing
206
- secret. Any of them can be entered or changed later on its own
220
+ 3. **Credentials into Ekanos.** `ekanos teams app set <team> zendesk --browser`
221
+ (a form in their browser; or without `--browser`, in their terminal):
222
+ subdomain, client ID, client secret, webhook signing secret. Any of them can be entered or changed later on its own
207
223
  (`--field <name>`); `teams show` says which are saved.
208
224
  4. **Connect.** `npx @ekanos/cli teams connect <team> zendesk --source <slug>`
209
225
  opens the sign-in and waits; whoever approves it should be the Zendesk
@@ -244,5 +260,6 @@ from `teams show zendesk`.
244
260
  not installed for this team", or no webhook URL) and the command that
245
261
  fixes it. Installed and still silent: the Linear app's webhook must send
246
262
  **Agent session events** to the latest URL from `teams webhook`.
247
- - **A command says it needs a terminal:** it was run inside Claude. Ask them
248
- to run it in a terminal tab themselves.
263
+ - **A command says there is no terminal to ask at:** run it again with
264
+ `--browser`. If `--browser` is refused (CI, SSH, no display), ask them to
265
+ run it in a terminal tab themselves.
@@ -185,7 +185,7 @@ mock switch) so the harness can show all four; remove it before publish.
185
185
  `border-border`, `bg-primary`, `text-destructive`. NEVER raw palette
186
186
  classes (`bg-white`, `text-gray-500`, `bg-amber-400`) or hex/oklch
187
187
  literals — they break in dark mode and off-brand tenants.
188
- - **Accent discipline**: the primary (coral-orange) on ≤10% of the widget —
188
+ - **Accent discipline**: the `primary` token (the Source's accent) on ≤10% of the widget —
189
189
  one CTA, one highlighted value, one active state. Semantic status colors
190
190
  (success/warning/destructive) are not accents.
191
191
  - **Depth via shadow, not borders** where a surface needs lift.