@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,69 @@
1
+ import { type TeamWorkflowApplied, type TeamWorkflowApplyRequest, type TeamWorkflowApprovalDecideRequest, type TeamWorkflowApprovalDecided, type TeamWorkflowApprovalList, type TeamWorkflowDetail, type TeamWorkflowList, type TeamWorkflowRunCancelled, type TeamWorkflowRunDetail, type TeamWorkflowRunList, type TeamWorkflowRunStartRequest, type TeamWorkflowRunStarted, type TeamWorkflowStatusChanged, type TeamWorkflowStatusRequest } from '@ekanos/integration-schema';
2
+ /**
3
+ * The CLI's client for a team's workflows — `ekanos workflows`.
4
+ *
5
+ * GET /api/partner/teams/<team>/workflows → TeamWorkflowList
6
+ * POST /api/partner/teams/<team>/workflows → TeamWorkflowApplied
7
+ * GET /api/partner/teams/<team>/workflows/<id> → TeamWorkflowDetail
8
+ * POST /api/partner/teams/<team>/workflows/<id>/status → TeamWorkflowStatusChanged
9
+ * POST /api/partner/teams/<team>/workflows/<id>/runs → TeamWorkflowRunStarted
10
+ * GET /api/partner/teams/<team>/workflows/runs → TeamWorkflowRunList
11
+ * GET /api/partner/teams/<team>/workflows/runs/<id> → TeamWorkflowRunDetail
12
+ * POST /api/partner/teams/<team>/workflows/runs/<id>/cancel → TeamWorkflowRunCancelled
13
+ * GET /api/partner/teams/<team>/workflows/approvals → TeamWorkflowApprovalList
14
+ * POST /api/partner/teams/<team>/workflows/approvals/<id> → TeamWorkflowApprovalDecided
15
+ *
16
+ * Every path carries `?source=<slug>`.
17
+ */
18
+ export type WorkflowsApiResult<T> = {
19
+ status: 'ok';
20
+ data: T;
21
+ } | {
22
+ status: 'unauthorized';
23
+ }
24
+ /** Activation stopped only on what Custom Code reaches: ask, then resend. */
25
+ | {
26
+ status: 'needs-access';
27
+ error: string;
28
+ codeAccess: CodeAccess[];
29
+ };
30
+ export interface CodeAccess {
31
+ stepId: string;
32
+ effect: 'read' | 'write';
33
+ egressHosts: string[];
34
+ tools: string[];
35
+ dependencies: string[];
36
+ reviewSummary: string | null;
37
+ }
38
+ interface TeamTarget {
39
+ source: string;
40
+ team: string;
41
+ }
42
+ export declare function listWorkflows(host: string, accessToken: string, target: TeamTarget & {
43
+ all: boolean;
44
+ }): Promise<WorkflowsApiResult<TeamWorkflowList>>;
45
+ export declare function showWorkflow(host: string, accessToken: string, target: TeamTarget & {
46
+ workflow: string;
47
+ }): Promise<WorkflowsApiResult<TeamWorkflowDetail>>;
48
+ export declare function applyWorkflow(host: string, accessToken: string, target: TeamTarget, body: TeamWorkflowApplyRequest): Promise<WorkflowsApiResult<TeamWorkflowApplied>>;
49
+ export declare function setWorkflowStatus(host: string, accessToken: string, target: TeamTarget & {
50
+ workflow: string;
51
+ }, body: TeamWorkflowStatusRequest): Promise<WorkflowsApiResult<TeamWorkflowStatusChanged>>;
52
+ export declare function startWorkflowRun(host: string, accessToken: string, target: TeamTarget & {
53
+ workflow: string;
54
+ }, body: TeamWorkflowRunStartRequest): Promise<WorkflowsApiResult<TeamWorkflowRunStarted>>;
55
+ export declare function listWorkflowRuns(host: string, accessToken: string, target: TeamTarget & {
56
+ workflow?: string;
57
+ status?: string;
58
+ }): Promise<WorkflowsApiResult<TeamWorkflowRunList>>;
59
+ export declare function showWorkflowRun(host: string, accessToken: string, target: TeamTarget & {
60
+ runId: string;
61
+ }): Promise<WorkflowsApiResult<TeamWorkflowRunDetail>>;
62
+ export declare function cancelWorkflowRun(host: string, accessToken: string, target: TeamTarget & {
63
+ runId: string;
64
+ }): Promise<WorkflowsApiResult<TeamWorkflowRunCancelled>>;
65
+ export declare function listWorkflowApprovals(host: string, accessToken: string, target: TeamTarget): Promise<WorkflowsApiResult<TeamWorkflowApprovalList>>;
66
+ export declare function decideWorkflowApproval(host: string, accessToken: string, target: TeamTarget & {
67
+ approvalId: string;
68
+ }, body: TeamWorkflowApprovalDecideRequest): Promise<WorkflowsApiResult<TeamWorkflowApprovalDecided>>;
69
+ export {};
@@ -0,0 +1,182 @@
1
+ import { TeamWorkflowAppliedSchema, TeamWorkflowApprovalDecidedSchema, TeamWorkflowApprovalListSchema, TeamWorkflowDetailSchema, TeamWorkflowListSchema, TeamWorkflowRunCancelledSchema, TeamWorkflowRunDetailSchema, TeamWorkflowRunListSchema, TeamWorkflowRunStartedSchema, TeamWorkflowStatusChangedSchema, } from '@ekanos/integration-schema';
2
+ import { request } from './auth/ekanos-api.js';
3
+ import { authRequiredError, forbiddenError, invalidStateError, networkError, notFoundError, usageError, validationError, } from './errors.js';
4
+ const segment = encodeURIComponent;
5
+ export function listWorkflows(host, accessToken, target) {
6
+ return call(host, accessToken, TeamWorkflowListSchema, {
7
+ method: 'GET',
8
+ path: base(target),
9
+ query: Object.assign({ source: target.source }, (target.all ? { all: '1' } : {})),
10
+ });
11
+ }
12
+ export function showWorkflow(host, accessToken, target) {
13
+ return call(host, accessToken, TeamWorkflowDetailSchema, {
14
+ method: 'GET',
15
+ path: `${base(target)}/${segment(target.workflow)}`,
16
+ query: { source: target.source },
17
+ });
18
+ }
19
+ export function applyWorkflow(host, accessToken, target, body) {
20
+ return call(host, accessToken, TeamWorkflowAppliedSchema, {
21
+ method: 'POST',
22
+ path: base(target),
23
+ query: { source: target.source },
24
+ body,
25
+ });
26
+ }
27
+ export function setWorkflowStatus(host, accessToken, target, body) {
28
+ return call(host, accessToken, TeamWorkflowStatusChangedSchema, {
29
+ method: 'POST',
30
+ path: `${base(target)}/${segment(target.workflow)}/status`,
31
+ query: { source: target.source },
32
+ body,
33
+ });
34
+ }
35
+ export function startWorkflowRun(host, accessToken, target, body) {
36
+ return call(host, accessToken, TeamWorkflowRunStartedSchema, {
37
+ method: 'POST',
38
+ path: `${base(target)}/${segment(target.workflow)}/runs`,
39
+ query: { source: target.source },
40
+ body,
41
+ });
42
+ }
43
+ export function listWorkflowRuns(host, accessToken, target) {
44
+ return call(host, accessToken, TeamWorkflowRunListSchema, {
45
+ method: 'GET',
46
+ path: `${base(target)}/runs`,
47
+ query: Object.assign(Object.assign({ source: target.source }, (target.workflow ? { workflow: target.workflow } : {})), (target.status ? { status: target.status } : {})),
48
+ });
49
+ }
50
+ export function showWorkflowRun(host, accessToken, target) {
51
+ return call(host, accessToken, TeamWorkflowRunDetailSchema, {
52
+ method: 'GET',
53
+ path: `${base(target)}/runs/${segment(target.runId)}`,
54
+ query: { source: target.source },
55
+ });
56
+ }
57
+ export function cancelWorkflowRun(host, accessToken, target) {
58
+ return call(host, accessToken, TeamWorkflowRunCancelledSchema, {
59
+ method: 'POST',
60
+ path: `${base(target)}/runs/${segment(target.runId)}/cancel`,
61
+ query: { source: target.source },
62
+ });
63
+ }
64
+ export function listWorkflowApprovals(host, accessToken, target) {
65
+ return call(host, accessToken, TeamWorkflowApprovalListSchema, {
66
+ method: 'GET',
67
+ path: `${base(target)}/approvals`,
68
+ query: { source: target.source },
69
+ });
70
+ }
71
+ export function decideWorkflowApproval(host, accessToken, target, body) {
72
+ return call(host, accessToken, TeamWorkflowApprovalDecidedSchema, {
73
+ method: 'POST',
74
+ path: `${base(target)}/approvals/${segment(target.approvalId)}`,
75
+ query: { source: target.source },
76
+ body,
77
+ });
78
+ }
79
+ function base(target) {
80
+ return `/api/partner/teams/${segment(target.team)}/workflows`;
81
+ }
82
+ async function call(host, accessToken, schema, init) {
83
+ const response = await request(`${host}${init.path}?${new URLSearchParams(init.query)}`, {
84
+ method: init.method,
85
+ headers: Object.assign({ accept: 'application/json', authorization: `Bearer ${accessToken}` }, (init.body === undefined
86
+ ? {}
87
+ : { 'content-type': 'application/json' })),
88
+ body: init.body === undefined ? undefined : JSON.stringify(init.body),
89
+ });
90
+ if (response.status === 401 ||
91
+ (response.status >= 300 && response.status < 400)) {
92
+ return { status: 'unauthorized' };
93
+ }
94
+ const body = await readOptionalJson(response);
95
+ const code = typeof body.code === 'string' ? body.code : null;
96
+ const message = typeof body.error === 'string' && body.error ? body.error : null;
97
+ if (response.status === 403 && code === 'MFA_REQUIRED') {
98
+ throw authRequiredError(message !== null && message !== void 0 ? message : `${host} requires multi-factor authentication.`, 'Complete MFA in the browser, then run "ekanos login" again.');
99
+ }
100
+ if (response.status === 403) {
101
+ throw forbiddenError(message !== null && message !== void 0 ? message : 'Not permitted on this Source.', code === 'SOURCE_ADMIN_REQUIRED'
102
+ ? "Only a Source admin manages its teams' workflows."
103
+ : 'Run "ekanos sources" to list the sources you hold a seat on.');
104
+ }
105
+ if (response.status === 404) {
106
+ throw notFoundError(message !== null && message !== void 0 ? message : 'Not found.', code === 'TEAM_NOT_FOUND'
107
+ ? 'Run "ekanos teams list" to see the teams on this Source.'
108
+ : code === 'WORKFLOW_NOT_FOUND'
109
+ ? 'Run "ekanos workflows list --team <slug>" for the team\'s workflows (a member\'s personal workflow is theirs alone).'
110
+ : code === 'RUN_NOT_FOUND'
111
+ ? 'Run "ekanos workflows runs list --team <slug>" for the team\'s runs.'
112
+ : code === 'APPROVAL_NOT_FOUND'
113
+ ? 'Run "ekanos workflows approvals list --team <slug>" for what is waiting.'
114
+ : 'Run "ekanos sources" to list the sources you hold a seat on.');
115
+ }
116
+ if (response.status === 409 && code === 'CODE_ACCESS_NEEDS_APPROVAL') {
117
+ const details = Array.isArray(body.codeAccess) ? body.codeAccess : [];
118
+ return {
119
+ status: 'needs-access',
120
+ error: message !== null && message !== void 0 ? message : 'Custom Code access needs your approval.',
121
+ codeAccess: details.filter(isCodeAccess),
122
+ };
123
+ }
124
+ if (response.status === 422) {
125
+ throw validationError(message !== null && message !== void 0 ? message : 'The host refused the workflow definition.', code === 'INVALID_DEFINITION'
126
+ ? 'Fix the definition and apply it again; nothing was saved.'
127
+ : 'The stored definition no longer validates: fix it with "ekanos workflows apply <file> --update <id>".');
128
+ }
129
+ if (response.status === 409 || response.status === 502) {
130
+ throw invalidStateError(message !== null && message !== void 0 ? message : 'The host refused the request in its current state.', code === 'WORKFLOWS_EXPERIENCE_OFF'
131
+ ? 'Ask Ekanos to turn on Workflows for this Source: only a super-admin can ("ekanos sources products" shows it as off).'
132
+ : code === 'AMBIGUOUS_WORKFLOW'
133
+ ? 'Name it by id: "ekanos workflows list --team <slug>" shows each one\'s.'
134
+ : code === 'WORKFLOW_ARCHIVED'
135
+ ? 'Restore it in the app first, or apply without --update to create a new draft.'
136
+ : code === 'ALREADY_DECIDED' || code === 'APPROVAL_EXPIRED'
137
+ ? 'Run "ekanos workflows approvals list --team <slug>" for what is still waiting.'
138
+ : code === 'RUN_FINISHED'
139
+ ? 'Nothing to stop. "ekanos workflows runs show <run-id> --team <slug>" shows how it ended.'
140
+ : code === 'CANCEL_FAILED'
141
+ ? 'Its status is reconciled automatically; check "ekanos workflows runs show <run-id>" shortly.'
142
+ : code === 'RESUME_FAILED'
143
+ ? 'The decision is saved; the run picks it up shortly. Check with "ekanos workflows runs show <run-id>".'
144
+ : code === 'RUN_REFUSED'
145
+ ? 'A live run needs an active workflow ("ekanos workflows enable"); "--dry-run" rehearses a draft.'
146
+ : 'Run "ekanos workflows show <id> --team <slug>" for its status and what blocks it.');
147
+ }
148
+ if (response.status === 400) {
149
+ throw usageError(message !== null && message !== void 0 ? message : 'The host refused the request.', 'See "ekanos workflows --help".');
150
+ }
151
+ if (!response.ok) {
152
+ throw networkError(`${host}${init.path} responded ${response.status}.`, response.status >= 500
153
+ ? 'The Ekanos deployment returned a server error. Retry shortly.'
154
+ : 'Confirm the host runs a build that includes the workflows routes.');
155
+ }
156
+ const parsed = schema.safeParse(body.data);
157
+ if (!parsed.success) {
158
+ throw networkError(`${host}${init.path} answered in a shape this CLI does not read.`, 'Run "ekanos upgrade" — the CLI and the host disagree on the workflows contract.');
159
+ }
160
+ return { status: 'ok', data: parsed.data };
161
+ }
162
+ function isCodeAccess(value) {
163
+ if (typeof value !== 'object' || value === null)
164
+ return false;
165
+ const entry = value;
166
+ return (typeof entry.stepId === 'string' &&
167
+ (entry.effect === 'read' || entry.effect === 'write') &&
168
+ Array.isArray(entry.egressHosts) &&
169
+ Array.isArray(entry.tools));
170
+ }
171
+ async function readOptionalJson(response) {
172
+ try {
173
+ const parsed = await response.json();
174
+ return typeof parsed === 'object' && parsed !== null
175
+ ? parsed
176
+ : {};
177
+ }
178
+ catch (_a) {
179
+ return {};
180
+ }
181
+ }
182
+ //# sourceMappingURL=workflows-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflows-api.js","sourceRoot":"","sources":["../src/workflows-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,yBAAyB,EAIzB,iCAAiC,EAEjC,8BAA8B,EAE9B,wBAAwB,EAExB,sBAAsB,EAEtB,8BAA8B,EAE9B,2BAA2B,EAE3B,yBAAyB,EAGzB,4BAA4B,EAE5B,+BAA+B,GAEhC,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,UAAU,EACV,eAAe,GAChB,MAAM,UAAU,CAAC;AAuClB,MAAM,OAAO,GAAG,kBAAkB,CAAC;AAEnC,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,WAAmB,EACnB,MAAqC;IAErC,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,sBAAsB,EAAE;QACrD,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;QAClB,KAAK,kBAAI,MAAM,EAAE,MAAM,CAAC,MAAM,IAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAE;KACtE,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,WAAmB,EACnB,MAAyC;IAEzC,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,wBAAwB,EAAE;QACvD,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE;QACnD,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;KACjC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,WAAmB,EACnB,MAAkB,EAClB,IAA8B;IAE9B,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,yBAAyB,EAAE;QACxD,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;QAClB,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAChC,IAAI;KACL,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,IAAY,EACZ,WAAmB,EACnB,MAAyC,EACzC,IAA+B;IAE/B,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,+BAA+B,EAAE;QAC9D,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS;QAC1D,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAChC,IAAI;KACL,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,WAAmB,EACnB,MAAyC,EACzC,IAAiC;IAEjC,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,4BAA4B,EAAE;QAC3D,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO;QACxD,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAChC,IAAI;KACL,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,WAAmB,EACnB,MAA2D;IAE3D,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,yBAAyB,EAAE;QACxD,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO;QAC5B,KAAK,gCACH,MAAM,EAAE,MAAM,CAAC,MAAM,IAClB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GACtD,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CACpD;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,IAAY,EACZ,WAAmB,EACnB,MAAsC;IAEtC,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,2BAA2B,EAAE;QAC1D,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACrD,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;KACjC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,IAAY,EACZ,WAAmB,EACnB,MAAsC;IAEtC,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,8BAA8B,EAAE;QAC7D,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS;QAC5D,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;KACjC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,IAAY,EACZ,WAAmB,EACnB,MAAkB;IAElB,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,8BAA8B,EAAE;QAC7D,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY;QACjC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;KACjC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,IAAY,EACZ,WAAmB,EACnB,MAA2C,EAC3C,IAAuC;IAEvC,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,iCAAiC,EAAE;QAChE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;QAC/D,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAChC,IAAI;KACL,CAAC,CAAC;AACL,CAAC;AAED,SAAS,IAAI,CAAC,MAAkB;IAC9B,OAAO,sBAAsB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;AAChE,CAAC;AAED,KAAK,UAAU,IAAI,CACjB,IAAY,EACZ,WAAmB,EACnB,MAAoB,EACpB,IAKC;IAED,MAAM,QAAQ,GAAG,MAAM,OAAO,CAC5B,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EACxD;QACE,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,kBACL,MAAM,EAAE,kBAAkB,EAC1B,aAAa,EAAE,UAAU,WAAW,EAAE,IACnC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS;YACzB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAC5C;QACD,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;KACtE,CACF,CAAC;IAEF,IACE,QAAQ,CAAC,MAAM,KAAK,GAAG;QACvB,CAAC,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,CAAC,EACjD,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACpC,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,MAAM,OAAO,GACX,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAEnE,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;QACvD,MAAM,iBAAiB,CACrB,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,GAAG,IAAI,wCAAwC,EAC1D,6DAA6D,CAC9D,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,cAAc,CAClB,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,+BAA+B,EAC1C,IAAI,KAAK,uBAAuB;YAC9B,CAAC,CAAC,mDAAmD;YACrD,CAAC,CAAC,8DAA8D,CACnE,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,aAAa,CACjB,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,YAAY,EACvB,IAAI,KAAK,gBAAgB;YACvB,CAAC,CAAC,0DAA0D;YAC5D,CAAC,CAAC,IAAI,KAAK,oBAAoB;gBAC7B,CAAC,CAAC,sHAAsH;gBACxH,CAAC,CAAC,IAAI,KAAK,eAAe;oBACxB,CAAC,CAAC,sEAAsE;oBACxE,CAAC,CAAC,IAAI,KAAK,oBAAoB;wBAC7B,CAAC,CAAC,0EAA0E;wBAC5E,CAAC,CAAC,8DAA8D,CACzE,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,IAAI,KAAK,4BAA4B,EAAE,CAAC;QACrE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,OAAO;YACL,MAAM,EAAE,cAAc;YACtB,KAAK,EAAE,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,yCAAyC;YAC3D,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC;SACzC,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,eAAe,CACnB,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,2CAA2C,EACtD,IAAI,KAAK,oBAAoB;YAC3B,CAAC,CAAC,2DAA2D;YAC7D,CAAC,CAAC,uGAAuG,CAC5G,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvD,MAAM,iBAAiB,CACrB,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,oDAAoD,EAC/D,IAAI,KAAK,0BAA0B;YACjC,CAAC,CAAC,sHAAsH;YACxH,CAAC,CAAC,IAAI,KAAK,oBAAoB;gBAC7B,CAAC,CAAC,yEAAyE;gBAC3E,CAAC,CAAC,IAAI,KAAK,mBAAmB;oBAC5B,CAAC,CAAC,+EAA+E;oBACjF,CAAC,CAAC,IAAI,KAAK,iBAAiB,IAAI,IAAI,KAAK,kBAAkB;wBACzD,CAAC,CAAC,gFAAgF;wBAClF,CAAC,CAAC,IAAI,KAAK,cAAc;4BACvB,CAAC,CAAC,0FAA0F;4BAC5F,CAAC,CAAC,IAAI,KAAK,eAAe;gCACxB,CAAC,CAAC,8FAA8F;gCAChG,CAAC,CAAC,IAAI,KAAK,eAAe;oCACxB,CAAC,CAAC,uGAAuG;oCACzG,CAAC,CAAC,IAAI,KAAK,aAAa;wCACtB,CAAC,CAAC,iGAAiG;wCACnG,CAAC,CAAC,mFAAmF,CACtG,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,UAAU,CACd,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,+BAA+B,EAC1C,gCAAgC,CACjC,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,YAAY,CAChB,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,cAAc,QAAQ,CAAC,MAAM,GAAG,EACnD,QAAQ,CAAC,MAAM,IAAI,GAAG;YACpB,CAAC,CAAC,+DAA+D;YACjE,CAAC,CAAC,mEAAmE,CACxE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,YAAY,CAChB,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,8CAA8C,EACjE,iFAAiF,CAClF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,KAAK,GAAG,KAAgC,CAAC;IAC/C,OAAO,CACL,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ;QAChC,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC;QACrD,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC;QAChC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAC3B,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,QAAkB;IAElB,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC9C,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;YAClD,CAAC,CAAE,MAAkC;YACrC,CAAC,CAAC,EAAE,CAAC;IACT,CAAC;eAAO,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC","sourcesContent":["import {\n type TeamWorkflowApplied,\n TeamWorkflowAppliedSchema,\n type TeamWorkflowApplyRequest,\n type TeamWorkflowApprovalDecideRequest,\n type TeamWorkflowApprovalDecided,\n TeamWorkflowApprovalDecidedSchema,\n type TeamWorkflowApprovalList,\n TeamWorkflowApprovalListSchema,\n type TeamWorkflowDetail,\n TeamWorkflowDetailSchema,\n type TeamWorkflowList,\n TeamWorkflowListSchema,\n type TeamWorkflowRunCancelled,\n TeamWorkflowRunCancelledSchema,\n type TeamWorkflowRunDetail,\n TeamWorkflowRunDetailSchema,\n type TeamWorkflowRunList,\n TeamWorkflowRunListSchema,\n type TeamWorkflowRunStartRequest,\n type TeamWorkflowRunStarted,\n TeamWorkflowRunStartedSchema,\n type TeamWorkflowStatusChanged,\n TeamWorkflowStatusChangedSchema,\n type TeamWorkflowStatusRequest,\n} from '@ekanos/integration-schema';\nimport type { z } from 'zod';\n\nimport { request } from './auth/ekanos-api';\nimport {\n authRequiredError,\n forbiddenError,\n invalidStateError,\n networkError,\n notFoundError,\n usageError,\n validationError,\n} from './errors';\n\n/**\n * The CLI's client for a team's workflows — `ekanos workflows`.\n *\n * GET /api/partner/teams/<team>/workflows → TeamWorkflowList\n * POST /api/partner/teams/<team>/workflows → TeamWorkflowApplied\n * GET /api/partner/teams/<team>/workflows/<id> → TeamWorkflowDetail\n * POST /api/partner/teams/<team>/workflows/<id>/status → TeamWorkflowStatusChanged\n * POST /api/partner/teams/<team>/workflows/<id>/runs → TeamWorkflowRunStarted\n * GET /api/partner/teams/<team>/workflows/runs → TeamWorkflowRunList\n * GET /api/partner/teams/<team>/workflows/runs/<id> → TeamWorkflowRunDetail\n * POST /api/partner/teams/<team>/workflows/runs/<id>/cancel → TeamWorkflowRunCancelled\n * GET /api/partner/teams/<team>/workflows/approvals → TeamWorkflowApprovalList\n * POST /api/partner/teams/<team>/workflows/approvals/<id> → TeamWorkflowApprovalDecided\n *\n * Every path carries `?source=<slug>`.\n */\n\nexport type WorkflowsApiResult<T> =\n | { status: 'ok'; data: T }\n | { status: 'unauthorized' }\n /** Activation stopped only on what Custom Code reaches: ask, then resend. */\n | { status: 'needs-access'; error: string; codeAccess: CodeAccess[] };\n\nexport interface CodeAccess {\n stepId: string;\n effect: 'read' | 'write';\n egressHosts: string[];\n tools: string[];\n dependencies: string[];\n reviewSummary: string | null;\n}\n\ninterface TeamTarget {\n source: string;\n team: string;\n}\n\nconst segment = encodeURIComponent;\n\nexport function listWorkflows(\n host: string,\n accessToken: string,\n target: TeamTarget & { all: boolean },\n): Promise<WorkflowsApiResult<TeamWorkflowList>> {\n return call(host, accessToken, TeamWorkflowListSchema, {\n method: 'GET',\n path: base(target),\n query: { source: target.source, ...(target.all ? { all: '1' } : {}) },\n });\n}\n\nexport function showWorkflow(\n host: string,\n accessToken: string,\n target: TeamTarget & { workflow: string },\n): Promise<WorkflowsApiResult<TeamWorkflowDetail>> {\n return call(host, accessToken, TeamWorkflowDetailSchema, {\n method: 'GET',\n path: `${base(target)}/${segment(target.workflow)}`,\n query: { source: target.source },\n });\n}\n\nexport function applyWorkflow(\n host: string,\n accessToken: string,\n target: TeamTarget,\n body: TeamWorkflowApplyRequest,\n): Promise<WorkflowsApiResult<TeamWorkflowApplied>> {\n return call(host, accessToken, TeamWorkflowAppliedSchema, {\n method: 'POST',\n path: base(target),\n query: { source: target.source },\n body,\n });\n}\n\nexport function setWorkflowStatus(\n host: string,\n accessToken: string,\n target: TeamTarget & { workflow: string },\n body: TeamWorkflowStatusRequest,\n): Promise<WorkflowsApiResult<TeamWorkflowStatusChanged>> {\n return call(host, accessToken, TeamWorkflowStatusChangedSchema, {\n method: 'POST',\n path: `${base(target)}/${segment(target.workflow)}/status`,\n query: { source: target.source },\n body,\n });\n}\n\nexport function startWorkflowRun(\n host: string,\n accessToken: string,\n target: TeamTarget & { workflow: string },\n body: TeamWorkflowRunStartRequest,\n): Promise<WorkflowsApiResult<TeamWorkflowRunStarted>> {\n return call(host, accessToken, TeamWorkflowRunStartedSchema, {\n method: 'POST',\n path: `${base(target)}/${segment(target.workflow)}/runs`,\n query: { source: target.source },\n body,\n });\n}\n\nexport function listWorkflowRuns(\n host: string,\n accessToken: string,\n target: TeamTarget & { workflow?: string; status?: string },\n): Promise<WorkflowsApiResult<TeamWorkflowRunList>> {\n return call(host, accessToken, TeamWorkflowRunListSchema, {\n method: 'GET',\n path: `${base(target)}/runs`,\n query: {\n source: target.source,\n ...(target.workflow ? { workflow: target.workflow } : {}),\n ...(target.status ? { status: target.status } : {}),\n },\n });\n}\n\nexport function showWorkflowRun(\n host: string,\n accessToken: string,\n target: TeamTarget & { runId: string },\n): Promise<WorkflowsApiResult<TeamWorkflowRunDetail>> {\n return call(host, accessToken, TeamWorkflowRunDetailSchema, {\n method: 'GET',\n path: `${base(target)}/runs/${segment(target.runId)}`,\n query: { source: target.source },\n });\n}\n\nexport function cancelWorkflowRun(\n host: string,\n accessToken: string,\n target: TeamTarget & { runId: string },\n): Promise<WorkflowsApiResult<TeamWorkflowRunCancelled>> {\n return call(host, accessToken, TeamWorkflowRunCancelledSchema, {\n method: 'POST',\n path: `${base(target)}/runs/${segment(target.runId)}/cancel`,\n query: { source: target.source },\n });\n}\n\nexport function listWorkflowApprovals(\n host: string,\n accessToken: string,\n target: TeamTarget,\n): Promise<WorkflowsApiResult<TeamWorkflowApprovalList>> {\n return call(host, accessToken, TeamWorkflowApprovalListSchema, {\n method: 'GET',\n path: `${base(target)}/approvals`,\n query: { source: target.source },\n });\n}\n\nexport function decideWorkflowApproval(\n host: string,\n accessToken: string,\n target: TeamTarget & { approvalId: string },\n body: TeamWorkflowApprovalDecideRequest,\n): Promise<WorkflowsApiResult<TeamWorkflowApprovalDecided>> {\n return call(host, accessToken, TeamWorkflowApprovalDecidedSchema, {\n method: 'POST',\n path: `${base(target)}/approvals/${segment(target.approvalId)}`,\n query: { source: target.source },\n body,\n });\n}\n\nfunction base(target: TeamTarget): string {\n return `/api/partner/teams/${segment(target.team)}/workflows`;\n}\n\nasync function call<T>(\n host: string,\n accessToken: string,\n schema: z.ZodType<T>,\n init: {\n method: 'GET' | 'POST';\n path: string;\n query: Record<string, string>;\n body?: unknown;\n },\n): Promise<WorkflowsApiResult<T>> {\n const response = await request(\n `${host}${init.path}?${new URLSearchParams(init.query)}`,\n {\n method: init.method,\n headers: {\n accept: 'application/json',\n authorization: `Bearer ${accessToken}`,\n ...(init.body === undefined\n ? {}\n : { 'content-type': 'application/json' }),\n },\n body: init.body === undefined ? undefined : JSON.stringify(init.body),\n },\n );\n\n if (\n response.status === 401 ||\n (response.status >= 300 && response.status < 400)\n ) {\n return { status: 'unauthorized' };\n }\n\n const body = await readOptionalJson(response);\n const code = typeof body.code === 'string' ? body.code : null;\n const message =\n typeof body.error === 'string' && body.error ? body.error : null;\n\n if (response.status === 403 && code === 'MFA_REQUIRED') {\n throw authRequiredError(\n message ?? `${host} requires multi-factor authentication.`,\n 'Complete MFA in the browser, then run \"ekanos login\" again.',\n );\n }\n if (response.status === 403) {\n throw forbiddenError(\n message ?? 'Not permitted on this Source.',\n code === 'SOURCE_ADMIN_REQUIRED'\n ? \"Only a Source admin manages its teams' workflows.\"\n : 'Run \"ekanos sources\" to list the sources you hold a seat on.',\n );\n }\n if (response.status === 404) {\n throw notFoundError(\n message ?? 'Not found.',\n code === 'TEAM_NOT_FOUND'\n ? 'Run \"ekanos teams list\" to see the teams on this Source.'\n : code === 'WORKFLOW_NOT_FOUND'\n ? 'Run \"ekanos workflows list --team <slug>\" for the team\\'s workflows (a member\\'s personal workflow is theirs alone).'\n : code === 'RUN_NOT_FOUND'\n ? 'Run \"ekanos workflows runs list --team <slug>\" for the team\\'s runs.'\n : code === 'APPROVAL_NOT_FOUND'\n ? 'Run \"ekanos workflows approvals list --team <slug>\" for what is waiting.'\n : 'Run \"ekanos sources\" to list the sources you hold a seat on.',\n );\n }\n if (response.status === 409 && code === 'CODE_ACCESS_NEEDS_APPROVAL') {\n const details = Array.isArray(body.codeAccess) ? body.codeAccess : [];\n return {\n status: 'needs-access',\n error: message ?? 'Custom Code access needs your approval.',\n codeAccess: details.filter(isCodeAccess),\n };\n }\n if (response.status === 422) {\n throw validationError(\n message ?? 'The host refused the workflow definition.',\n code === 'INVALID_DEFINITION'\n ? 'Fix the definition and apply it again; nothing was saved.'\n : 'The stored definition no longer validates: fix it with \"ekanos workflows apply <file> --update <id>\".',\n );\n }\n if (response.status === 409 || response.status === 502) {\n throw invalidStateError(\n message ?? 'The host refused the request in its current state.',\n code === 'WORKFLOWS_EXPERIENCE_OFF'\n ? 'Ask Ekanos to turn on Workflows for this Source: only a super-admin can (\"ekanos sources products\" shows it as off).'\n : code === 'AMBIGUOUS_WORKFLOW'\n ? 'Name it by id: \"ekanos workflows list --team <slug>\" shows each one\\'s.'\n : code === 'WORKFLOW_ARCHIVED'\n ? 'Restore it in the app first, or apply without --update to create a new draft.'\n : code === 'ALREADY_DECIDED' || code === 'APPROVAL_EXPIRED'\n ? 'Run \"ekanos workflows approvals list --team <slug>\" for what is still waiting.'\n : code === 'RUN_FINISHED'\n ? 'Nothing to stop. \"ekanos workflows runs show <run-id> --team <slug>\" shows how it ended.'\n : code === 'CANCEL_FAILED'\n ? 'Its status is reconciled automatically; check \"ekanos workflows runs show <run-id>\" shortly.'\n : code === 'RESUME_FAILED'\n ? 'The decision is saved; the run picks it up shortly. Check with \"ekanos workflows runs show <run-id>\".'\n : code === 'RUN_REFUSED'\n ? 'A live run needs an active workflow (\"ekanos workflows enable\"); \"--dry-run\" rehearses a draft.'\n : 'Run \"ekanos workflows show <id> --team <slug>\" for its status and what blocks it.',\n );\n }\n if (response.status === 400) {\n throw usageError(\n message ?? 'The host refused the request.',\n 'See \"ekanos workflows --help\".',\n );\n }\n if (!response.ok) {\n throw networkError(\n `${host}${init.path} responded ${response.status}.`,\n response.status >= 500\n ? 'The Ekanos deployment returned a server error. Retry shortly.'\n : 'Confirm the host runs a build that includes the workflows routes.',\n );\n }\n\n const parsed = schema.safeParse(body.data);\n if (!parsed.success) {\n throw networkError(\n `${host}${init.path} answered in a shape this CLI does not read.`,\n 'Run \"ekanos upgrade\" — the CLI and the host disagree on the workflows contract.',\n );\n }\n return { status: 'ok', data: parsed.data };\n}\n\nfunction isCodeAccess(value: unknown): value is CodeAccess {\n if (typeof value !== 'object' || value === null) return false;\n const entry = value as Record<string, unknown>;\n return (\n typeof entry.stepId === 'string' &&\n (entry.effect === 'read' || entry.effect === 'write') &&\n Array.isArray(entry.egressHosts) &&\n Array.isArray(entry.tools)\n );\n}\n\nasync function readOptionalJson(\n response: Response,\n): Promise<Record<string, unknown>> {\n try {\n const parsed: unknown = await response.json();\n return typeof parsed === 'object' && parsed !== null\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ekanos/cli",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "private": false,
5
5
  "description": "The Ekanos partner toolchain CLI: scaffold, validate, and test an Ekanos integration against the published @ekanos packages. Agent-native — every verb speaks JSON with a stable exit-code taxonomy.",
6
6
  "keywords": [
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@clack/prompts": "1.7.0",
38
- "@ekanos/integration-schema": "0.17.0",
38
+ "@ekanos/integration-schema": "0.19.0",
39
39
  "esbuild": "0.28.1",
40
40
  "picocolors": "1.1.1"
41
41
  },
@@ -44,7 +44,7 @@
44
44
  "@types/node": "25.0.1",
45
45
  "typescript": "^7.0.2",
46
46
  "vitest": "4.1.10",
47
- "zod": "4.6.5"
47
+ "zod": "4.6.7"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "zod": "^3.25.76 || ^4.0.0"
@@ -431,10 +431,12 @@ Icons are Font Awesome glyph names via `@ekanos/ui/icon`. This generated shell l
431
431
  (`@fortawesome/fontawesome-free`) — a much smaller set than the Pro kit Ekanos
432
432
  itself runs — so a name that's Pro-only (or just mistyped) renders a
433
433
  circle-question disc instead of vanishing, and dev builds `console.warn` once
434
- per name to catch it before a screenshot review does. `fa-light` / `fa-duotone`
435
- / `fa-thin` are rewritten to `fa-solid`, the one weight Free ships, so author
436
- `fa-light` anyway — it degrades harmlessly today, and the intended weight
437
- survives if this host ever loads Pro instead. Verify a glyph name against the
434
+ per name to catch it before a screenshot review does. Write icon names
435
+ family-less (`fa-gear`, not `fa-light fa-gear`): the host's theme picks the
436
+ family, so a Source's icon style reaches your icons too, and
437
+ `design/no-default-icon-family` rejects `fa-light` / `fa-regular`. On Free,
438
+ families it lacks (`fa-light`, `fa-duotone`, `fa-thin`) still render as
439
+ `fa-solid`. Verify a glyph name against the
438
440
  Free set (`pnpm --filter @ekanos/ui check:fa-free-names`, or
439
441
  https://fontawesome.com/search?o=r&s=solid,regular,brands) before relying on
440
442
  it looking like anything in particular.
@@ -30,7 +30,10 @@ and after upgrading `@ekanos/*` packages. The topic → URL map is in AGENTS.md.
30
30
  tools and agent triggers, and the steps left to set each one up. If a product
31
31
  already does what the user wants, propose setting it up (walk its
32
32
  `setupSteps`, naming who does each one) instead of building it again.
33
- `npx ekanos catalog <product> --json` shows one in full.
33
+ `npx ekanos catalog <product> --json` shows one in full: each tool's
34
+ `inputSchema` (so you can see which other tool returns an id a tool needs)
35
+ and `connection` — who connects the product and whose connection an agent
36
+ run uses.
34
37
 
35
38
  ## Managed agents live in Ekanos
36
39
 
@@ -1,4 +1,5 @@
1
1
  {
2
+ "kind": "integration",
2
3
  "slug": "__SLUG__",
3
4
  "entry": "src/integration.ts"
4
5
  }
@@ -0,0 +1,22 @@
1
+ # __DISPLAY_NAME__ (an Ekanos experience)
2
+
3
+ This project is an EXPERIENCE: widgets, pages and workflow templates that depend
4
+ on integrations and reach them only through their pinned contracts. It is not an
5
+ integration itself.
6
+
7
+ - The integrations it depends on are declared in `ekanos.json` "integrations"
8
+ (`name` = the integration, `version`, the `operations` it may call) and pinned in
9
+ `ekanos.lock.json` + `contracts/`. Add one:
10
+ `ekanos add <integration>@<version> --from-dir <dir>`.
11
+ Never edit `src/.ekanos/integrations.d.ts`; `ekanos codegen` writes it.
12
+ - Read: `useOperation(integration, 'tool/<name>', input)`. Write:
13
+ `useOperationMutation(integration, 'action/<name>')` (a person approves each write).
14
+ Server: `operation(integration, op, input)` from `@ekanos/sdk/experience/server`.
15
+ - Never import integration code (`@companydotcom/integration-*`, a path into an
16
+ integration repo, `@kit/*`). `ekanos check` and `ekanos build` fail on it.
17
+ - Build UI with `@ekanos/sdk/components` (`Widget.*`) and `@ekanos/ui`, semantic
18
+ tokens only.
19
+ - To try an unpublished integration, create `ekanos.local.json` (gitignored)
20
+ with an "integrations" entry pointing at the integration's folder. While any override is active `ekanos publish`
21
+ refuses.
22
+ - Loop: `ekanos check` then `ekanos build`.
@@ -0,0 +1,7 @@
1
+ {
2
+ "kind": "experience",
3
+ "slug": "__SLUG__",
4
+ "entry": "src/experience.ts",
5
+ "contractsDir": "contracts",
6
+ "integrations": []
7
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "integrations": {}
4
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Lint config for __SLUG__.
3
+ *
4
+ * `@ekanos/sdk/eslint/experience` keeps integration code out of this project:
5
+ * no `@companydotcom/integration-*`, no path into an integration, no `@kit/*`,
6
+ * no computed `import()`. An experience XX * integrations (`useOperation`, `operation`, `step.tool`). `ekanos check` re-verifies
7
+ * the same rule against the real import graph and the built bundle.
8
+ */
9
+ import experiencePreset from '@ekanos/sdk/eslint/experience';
10
+ import tsParser from '@typescript-eslint/parser';
11
+
12
+ export default [
13
+ { ignores: ['dist/**', 'node_modules/**', '.ekanos/**', 'legacy/**'] },
14
+ {
15
+ name: '__SLUG__/parser',
16
+ files: ['src/**/*.ts', 'src/**/*.tsx'],
17
+ languageOptions: {
18
+ parser: tsParser,
19
+ ecmaVersion: 'latest',
20
+ sourceType: 'module',
21
+ parserOptions: { ecmaFeatures: { jsx: true } },
22
+ },
23
+ },
24
+ ...experiencePreset,
25
+ ];
@@ -0,0 +1,17 @@
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Build output (regenerated by `ekanos build`)
5
+ dist/
6
+ manifest.json
7
+ *.tsbuildinfo
8
+
9
+ # Per-developer: integration overrides and the generated dev harness (root only:
10
+ # src/.ekanos/integrations.d.ts is codegen output and IS committed). Never commit these;
11
+ # `ekanos check` fails if ekanos.local.json is tracked and `ekanos publish`
12
+ # refuses while an override is active.
13
+ ekanos.local.json
14
+ /.ekanos/
15
+
16
+ # Logs
17
+ *.log
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "__SLUG__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "description": "An Ekanos experience built with @ekanos/sdk.",
7
+ "files": [
8
+ "dist",
9
+ "manifest.json",
10
+ "ekanos.json",
11
+ "ekanos.lock.json",
12
+ "contracts"
13
+ ],
14
+ "scripts": {
15
+ "typecheck": "tsc --noEmit",
16
+ "lint": "eslint .",
17
+ "check": "npx ekanos check",
18
+ "build": "npx ekanos build"
19
+ },
20
+ "dependencies": {
21
+ "@ekanos/sdk": "^0.19.0",
22
+ "@ekanos/ui": "^0.19.0",
23
+ "@tanstack/react-query": "^5.101.4",
24
+ "react": "^19.2.8",
25
+ "react-dom": "^19.2.8",
26
+ "zod": "^3.25.76"
27
+ },
28
+ "devDependencies": {
29
+ "@ekanos/cli": "^0.17.0",
30
+ "@ekanos/harness": "^0.19.0",
31
+ "@tailwindcss/postcss": "^4.3.3",
32
+ "@typescript-eslint/parser": "^8.46.2",
33
+ "@types/react": "^19.2.0",
34
+ "@types/react-dom": "^19.2.0",
35
+ "eslint": "^10.11.0",
36
+ "next": "^16.0.0",
37
+ "react-hook-form": "^7.68.0",
38
+ "tailwindcss": "^4.3.3",
39
+ "typescript": "^5.9.3"
40
+ }
41
+ }
@@ -0,0 +1,3 @@
1
+ // GENERATED by `ekanos codegen` from the pinned contracts. Do not edit; commit it.
2
+ // Run `ekanos add <integration>@<version>` or `ekanos sync` to change the integrations.
3
+ export {};
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Your experience, declared in one object.
3
+ *
4
+ * The integrations this experience depends on live in ekanos.json "integrations",
5
+ * not here. Add one with:
6
+ *
7
+ * ekanos add <integration>@<version> --from-dir <contracts folder>
8
+ *
9
+ * That pins the integration's contract and generates src/.ekanos/integrations.d.ts,
10
+ * after which `useOperation('<integration>', 'tool/<name>')` is typed end to end.
11
+ */
12
+ import { defineExperience } from '@ekanos/sdk/experience';
13
+
14
+ import { HelloWidget } from './widgets/hello-widget';
15
+
16
+ export default defineExperience({
17
+ slug: '__SLUG__',
18
+ name: '__DISPLAY_NAME__',
19
+ description: 'A starter experience. Replace this with what it does.',
20
+ sidebar: { section: '__SLUG__', icon: 'sparkles', label: '__DISPLAY_NAME__' },
21
+ widgets: [
22
+ {
23
+ id: 'hello',
24
+ title: 'Hello',
25
+ integrations: [],
26
+ width: 'half',
27
+ component: HelloWidget,
28
+ },
29
+ ],
30
+ });
@@ -0,0 +1,40 @@
1
+ import { Widget } from '@ekanos/sdk/components';
2
+ import {
3
+ Stat,
4
+ StatDetail,
5
+ StatFigure,
6
+ StatLabel,
7
+ StatValue,
8
+ } from '@ekanos/ui/stat';
9
+
10
+ // A starter widget, built like an integration widget: the Widget.* compound
11
+ // API plus the kit's Stat, semantic tokens only, never an inline style.
12
+ //
13
+ // Once you have added an integration, read from it with a typed hook:
14
+ //
15
+ // import { useOperation } from '@ekanos/sdk/experience/client';
16
+ // const posts = useOperation('sanity', 'tool/list_posts', { limit: 10 });
17
+ //
18
+ // and write with useOperationMutation, which asks a person to approve first.
19
+ export function HelloWidget() {
20
+ return (
21
+ <Widget.DataState>
22
+ <Widget.Card>
23
+ <Widget.Header context="Since you scaffolded this" />
24
+ <Widget.Active>
25
+ <Widget.Body>
26
+ <Stat>
27
+ <StatLabel>Integrations</StatLabel>
28
+ <StatFigure>
29
+ <StatValue>0</StatValue>
30
+ </StatFigure>
31
+ <StatDetail>Run "ekanos add" to add an integration</StatDetail>
32
+ </Stat>
33
+ </Widget.Body>
34
+ </Widget.Active>
35
+ <Widget.Loading variant="stat" />
36
+ <Widget.Error />
37
+ </Widget.Card>
38
+ </Widget.DataState>
39
+ );
40
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["dom", "dom.iterable", "ES2022"],
5
+ "module": "esnext",
6
+ "moduleResolution": "bundler",
7
+ "jsx": "react-jsx",
8
+ "strict": true,
9
+ "noUncheckedIndexedAccess": true,
10
+ "noEmit": true,
11
+ "skipLibCheck": true,
12
+ "esModuleInterop": true,
13
+ "resolveJsonModule": true,
14
+ "isolatedModules": true,
15
+ "verbatimModuleSyntax": true,
16
+ "forceConsistentCasingInFileNames": true
17
+ },
18
+ "include": ["src", "src/.ekanos/integrations.d.ts"],
19
+ "exclude": ["node_modules", "dist", ".ekanos", "legacy"]
20
+ }
@@ -0,0 +1,9 @@
1
+ import { createEkanosApiHandlers } 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/*.
5
+ const handlers = createEkanosApiHandlers();
6
+
7
+ export const GET = handlers.GET;
8
+ export const POST = handlers.POST;
9
+ export const PUT = handlers.PUT;
@@ -1 +1 @@
1
- export { ActivationPage as default } from '@ekanos/harness/routes';
1
+ export { LegacyPreviewRedirect as default } from '@ekanos/harness/routes';
@@ -1 +1 @@
1
- export { IntegrationIndexPage as default } from '@ekanos/harness/routes';
1
+ export { LegacyPreviewRedirect as default } from '@ekanos/harness/routes';
@@ -1 +1 @@
1
- export { TilePage as default } from '@ekanos/harness/routes';
1
+ export { LegacyPreviewRedirect as default } from '@ekanos/harness/routes';
@@ -1 +1 @@
1
- export { TriggersPage as default } from '@ekanos/harness/routes';
1
+ export { LegacyPreviewRedirect as default } from '@ekanos/harness/routes';
@@ -1 +1 @@
1
- export { SingleWidgetPage as default } from '@ekanos/harness/routes';
1
+ export { LegacyPreviewRedirect as default } from '@ekanos/harness/routes';
@@ -1 +1 @@
1
- export { WidgetsPage as default } from '@ekanos/harness/routes';
1
+ export { LegacyPreviewRedirect as default } from '@ekanos/harness/routes';