@ekanos/cli 0.12.0 → 0.14.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 (175) hide show
  1. package/README.md +25 -8
  2. package/dist/agents-api.d.ts +11 -2
  3. package/dist/agents-api.js +39 -3
  4. package/dist/agents-api.js.map +1 -1
  5. package/dist/apps-api.d.ts +3 -2
  6. package/dist/apps-api.js +3 -7
  7. package/dist/apps-api.js.map +1 -1
  8. package/dist/auth/ekanos-api.d.ts +16 -2
  9. package/dist/auth/ekanos-api.js +101 -15
  10. package/dist/auth/ekanos-api.js.map +1 -1
  11. package/dist/auth/host-trust.d.ts +46 -0
  12. package/dist/auth/host-trust.js +79 -0
  13. package/dist/auth/host-trust.js.map +1 -0
  14. package/dist/auth/session.d.ts +10 -1
  15. package/dist/auth/session.js +28 -28
  16. package/dist/auth/session.js.map +1 -1
  17. package/dist/commands/agents-edit.d.ts +6 -2
  18. package/dist/commands/agents-edit.js +57 -26
  19. package/dist/commands/agents-edit.js.map +1 -1
  20. package/dist/commands/agents.d.ts +13 -2
  21. package/dist/commands/agents.js +148 -36
  22. package/dist/commands/agents.js.map +1 -1
  23. package/dist/commands/apps.d.ts +15 -4
  24. package/dist/commands/apps.js +133 -51
  25. package/dist/commands/apps.js.map +1 -1
  26. package/dist/commands/catalog.js +7 -6
  27. package/dist/commands/catalog.js.map +1 -1
  28. package/dist/commands/knowledge.d.ts +56 -0
  29. package/dist/commands/knowledge.js +456 -0
  30. package/dist/commands/knowledge.js.map +1 -0
  31. package/dist/commands/login.d.ts +4 -0
  32. package/dist/commands/login.js +30 -2
  33. package/dist/commands/login.js.map +1 -1
  34. package/dist/commands/logout.d.ts +9 -1
  35. package/dist/commands/logout.js +56 -7
  36. package/dist/commands/logout.js.map +1 -1
  37. package/dist/commands/publish.js +3 -3
  38. package/dist/commands/publish.js.map +1 -1
  39. package/dist/commands/reviewers.d.ts +2 -0
  40. package/dist/commands/reviewers.js +7 -3
  41. package/dist/commands/reviewers.js.map +1 -1
  42. package/dist/commands/routes.d.ts +2 -0
  43. package/dist/commands/routes.js +42 -9
  44. package/dist/commands/routes.js.map +1 -1
  45. package/dist/commands/runs.d.ts +13 -2
  46. package/dist/commands/runs.js +96 -15
  47. package/dist/commands/runs.js.map +1 -1
  48. package/dist/commands/scope-notice.d.ts +21 -0
  49. package/dist/commands/scope-notice.js +35 -0
  50. package/dist/commands/scope-notice.js.map +1 -0
  51. package/dist/commands/skills.d.ts +7 -1
  52. package/dist/commands/skills.js +80 -24
  53. package/dist/commands/skills.js.map +1 -1
  54. package/dist/commands/sources.d.ts +4 -0
  55. package/dist/commands/sources.js +233 -5
  56. package/dist/commands/sources.js.map +1 -1
  57. package/dist/commands/status.js +5 -4
  58. package/dist/commands/status.js.map +1 -1
  59. package/dist/commands/team-agent-readiness.d.ts +59 -0
  60. package/dist/commands/team-agent-readiness.js +341 -0
  61. package/dist/commands/team-agent-readiness.js.map +1 -0
  62. package/dist/commands/team-agents-agents.d.ts +24 -3
  63. package/dist/commands/team-agents-agents.js +336 -35
  64. package/dist/commands/team-agents-agents.js.map +1 -1
  65. package/dist/commands/team-agents-mcp.js +32 -3
  66. package/dist/commands/team-agents-mcp.js.map +1 -1
  67. package/dist/commands/team-agents-triggers.js +230 -54
  68. package/dist/commands/team-agents-triggers.js.map +1 -1
  69. package/dist/commands/team-agents.d.ts +3 -1
  70. package/dist/commands/team-agents.js +27 -7
  71. package/dist/commands/team-agents.js.map +1 -1
  72. package/dist/commands/teams-channel-install.d.ts +24 -0
  73. package/dist/commands/teams-channel-install.js +94 -0
  74. package/dist/commands/teams-channel-install.js.map +1 -0
  75. package/dist/commands/teams-connect.d.ts +66 -0
  76. package/dist/commands/teams-connect.js +397 -0
  77. package/dist/commands/teams-connect.js.map +1 -0
  78. package/dist/commands/teams-events.d.ts +12 -0
  79. package/dist/commands/teams-events.js +138 -0
  80. package/dist/commands/teams-events.js.map +1 -0
  81. package/dist/commands/teams-onboard.d.ts +16 -5
  82. package/dist/commands/teams-onboard.js +61 -36
  83. package/dist/commands/teams-onboard.js.map +1 -1
  84. package/dist/commands/teams-overview.d.ts +11 -0
  85. package/dist/commands/teams-overview.js +160 -0
  86. package/dist/commands/teams-overview.js.map +1 -0
  87. package/dist/commands/teams-scope.d.ts +10 -0
  88. package/dist/commands/teams-scope.js +109 -0
  89. package/dist/commands/teams-scope.js.map +1 -0
  90. package/dist/commands/teams.d.ts +64 -7
  91. package/dist/commands/teams.js +254 -60
  92. package/dist/commands/teams.js.map +1 -1
  93. package/dist/commands/upgrade.js +12 -2
  94. package/dist/commands/upgrade.js.map +1 -1
  95. package/dist/commands/use.js +2 -2
  96. package/dist/commands/use.js.map +1 -1
  97. package/dist/commands/whoami.js +1 -1
  98. package/dist/commands/whoami.js.map +1 -1
  99. package/dist/connections-api.js +1 -1
  100. package/dist/connections-api.js.map +1 -1
  101. package/dist/delegate.js +11 -4
  102. package/dist/delegate.js.map +1 -1
  103. package/dist/harness-scaffold.js +12 -0
  104. package/dist/harness-scaffold.js.map +1 -1
  105. package/dist/index.d.ts +6 -0
  106. package/dist/index.js +724 -152
  107. package/dist/index.js.map +1 -1
  108. package/dist/knowledge-api.d.ts +175 -0
  109. package/dist/knowledge-api.js +169 -0
  110. package/dist/knowledge-api.js.map +1 -0
  111. package/dist/open-url.d.ts +16 -0
  112. package/dist/open-url.js +73 -0
  113. package/dist/open-url.js.map +1 -0
  114. package/dist/parse-argv.d.ts +2 -0
  115. package/dist/parse-argv.js.map +1 -1
  116. package/dist/publish-api.d.ts +2 -1
  117. package/dist/publish-api.js +4 -3
  118. package/dist/publish-api.js.map +1 -1
  119. package/dist/pull-write.d.ts +27 -0
  120. package/dist/pull-write.js +60 -0
  121. package/dist/pull-write.js.map +1 -0
  122. package/dist/routes-api.d.ts +3 -0
  123. package/dist/routes-api.js +9 -4
  124. package/dist/routes-api.js.map +1 -1
  125. package/dist/runs-api.d.ts +7 -1
  126. package/dist/runs-api.js +21 -6
  127. package/dist/runs-api.js.map +1 -1
  128. package/dist/safe-fs.d.ts +2 -0
  129. package/dist/safe-fs.js +12 -6
  130. package/dist/safe-fs.js.map +1 -1
  131. package/dist/secret-file.d.ts +17 -0
  132. package/dist/secret-file.js +69 -0
  133. package/dist/secret-file.js.map +1 -0
  134. package/dist/skills-api.d.ts +10 -2
  135. package/dist/skills-api.js +37 -2
  136. package/dist/skills-api.js.map +1 -1
  137. package/dist/source-products-api.d.ts +63 -0
  138. package/dist/source-products-api.js +123 -0
  139. package/dist/source-products-api.js.map +1 -0
  140. package/dist/source-target.js +2 -1
  141. package/dist/source-target.js.map +1 -1
  142. package/dist/sources-api.d.ts +2 -1
  143. package/dist/sources-api.js +3 -2
  144. package/dist/sources-api.js.map +1 -1
  145. package/dist/team-connect-api.d.ts +286 -0
  146. package/dist/team-connect-api.js +107 -0
  147. package/dist/team-connect-api.js.map +1 -0
  148. package/dist/teams-api.d.ts +42 -1
  149. package/dist/teams-api.js +98 -20
  150. package/dist/teams-api.js.map +1 -1
  151. package/dist/toolchain-api.d.ts +9 -0
  152. package/dist/toolchain-api.js +17 -2
  153. package/dist/toolchain-api.js.map +1 -1
  154. package/dist/toolchain-resolve.d.ts +3 -0
  155. package/dist/toolchain-resolve.js +15 -1
  156. package/dist/toolchain-resolve.js.map +1 -1
  157. package/dist/toolchain.d.ts +6 -0
  158. package/dist/toolchain.js +19 -0
  159. package/dist/toolchain.js.map +1 -1
  160. package/dist/update-notice.js +2 -1
  161. package/dist/update-notice.js.map +1 -1
  162. package/package.json +2 -2
  163. package/templates/AGENTS.md.tmpl +6 -1
  164. package/templates/claude-skill.md.tmpl +5 -0
  165. package/templates/package.json.tmpl +4 -4
  166. package/templates/skills/build-agent/SKILL.md +115 -16
  167. package/templates/skills/build-agent/references/agent-json.md +26 -8
  168. package/templates/skills/build-agent/references/app-setup.md +2 -1
  169. package/templates/skills/build-agent/references/rollout.md +27 -4
  170. package/templates/skills/build-agent/references/set-up-an-integration.md +74 -15
  171. package/templates/skills/build-agent/references/skills.md +20 -1
  172. package/templates/skills/build-agent/references/triggers.md +84 -20
  173. package/templates/skills/build-integration/references/widget-design.md +3 -3
  174. package/templates/skills/ekanos-platform/SKILL.md +70 -17
  175. package/templates/skills/polish-widgets/references/patterns.md +2 -2
@@ -1,6 +1,19 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
1
12
  import { TeamAgentLinkAddResultSchema, TeamAgentLinkListSchema, TeamAgentRowRemoveResultSchema, TeamAgentTriggerAddResultSchema, TeamAgentTriggerListSchema, } from '@ekanos/integration-schema';
2
- import { usageError } from '../errors.js';
13
+ import { invalidStateError, usageError } from '../errors.js';
14
+ import { ensureSecretsDir, writeSecretFile } from '../secret-file.js';
3
15
  import { call } from '../teams-api.js';
16
+ import { parseFilters } from './agents-edit.js';
4
17
  import { requireOperand, usageFor } from './team-agents.js';
5
18
  /**
6
19
  * `ekanos teams triggers list|add|remove` and `ekanos teams links
@@ -11,6 +24,7 @@ import { requireOperand, usageFor } from './team-agents.js';
11
24
  */
12
25
  export async function runTeamTriggers(ctx, run) {
13
26
  var _a;
27
+ var _b, _c, _d;
14
28
  const team = requireOperand(run.operands[0], 'team slug', 'triggers');
15
29
  const key = requireOperand(run.operands[1], 'agent key', 'triggers');
16
30
  const base = agentPath(team, key);
@@ -27,48 +41,69 @@ export async function runTeamTriggers(ctx, run) {
27
41
  trigger.id,
28
42
  describeTrigger(trigger),
29
43
  ]),
30
- notes: list.teamOwned
31
- ? [
32
- '"ekanos teams triggers add <team> <key> manual|schedule|webhook|event …" adds one.',
33
- ]
34
- : [
35
- `These follow the template. To let the team change them: ekanos agents overrides ${key} enable triggers`,
36
- ],
44
+ notes: [
45
+ ...(list.teamOwned
46
+ ? [
47
+ '"ekanos teams triggers add <team> <key> manual|schedule|webhook|event …" adds one.',
48
+ ]
49
+ : [
50
+ `These follow the template. To let the team change them: ekanos agents overrides ${key} enable triggers`,
51
+ ]),
52
+ ...(list.triggers.some((trigger) => trigger.type === 'webhook' && trigger.secretSet === false)
53
+ ? [
54
+ `A webhook trigger with no token yet gets its URL and token from "ekanos teams triggers rotate ${team} ${key} <trigger-key|id>".`,
55
+ ]
56
+ : []),
57
+ ],
37
58
  }));
38
59
  }
39
60
  case 'add': {
40
61
  const body = triggerBody(run, team, key);
62
+ // A webhook trigger's token comes back once: have somewhere to put it.
63
+ const secrets = body.type === 'webhook' ? ensureSecretsDir(run.args.env) : null;
41
64
  const added = await send(run, TeamAgentTriggerAddResultSchema, 'POST', `${base}/triggers`, body);
42
65
  const rows = [
43
66
  ['Trigger', added.trigger.id],
44
67
  ['Fires on', describeTrigger(added.trigger)],
45
68
  ];
46
- if (added.webhook) {
47
- rows.push(['URL', added.webhook.url]);
48
- rows.push(['Bearer token', added.webhook.token]);
49
- }
50
- return ctx.succeed(Object.assign({ host: run.host }, added), ctx.ui.result({
69
+ const { webhook } = added, rest = __rest(added, ["webhook"]);
70
+ const saved = webhook
71
+ ? saveTriggerToken(run, secrets, {
72
+ team: added.team.slug,
73
+ agent: added.agent.slug,
74
+ trigger: (_b = added.trigger.key) !== null && _b !== void 0 ? _b : added.trigger.id,
75
+ webhook,
76
+ again: `ekanos teams triggers rotate ${team} ${key} ${(_c = added.trigger.key) !== null && _c !== void 0 ? _c : added.trigger.id} --yes`,
77
+ })
78
+ : null;
79
+ if (saved)
80
+ rows.push(...saved.rows);
81
+ return ctx.succeed(Object.assign(Object.assign({ host: run.host }, rest), { webhook: (_d = saved === null || saved === void 0 ? void 0 : saved.json) !== null && _d !== void 0 ? _d : null }), ctx.ui.result({
51
82
  title: `Added a ${added.trigger.type} trigger to ${added.agent.slug} on ${added.team.slug}`,
52
- tone: added.webhook ? 'warn' : 'ok',
83
+ tone: saved ? 'warn' : 'ok',
53
84
  rows,
54
- notes: added.webhook
55
- ? [
56
- 'The URL and token are shown once and cannot be read again. POST JSON to the URL with "Authorization: Bearer <token>".',
57
- ]
58
- : [],
85
+ notes: saved ? saved.notes : [],
59
86
  }));
60
87
  }
61
88
  case 'remove': {
62
- const id = (_a = run.operands[2]) === null || _a === void 0 ? void 0 : _a.trim();
63
- if (!id) {
64
- throw usageError('Name the trigger to remove.', `List them: ekanos teams triggers list ${team} ${key}`);
89
+ const ref = (_a = run.operands[2]) === null || _a === void 0 ? void 0 : _a.trim();
90
+ if (!ref) {
91
+ throw usageError('Name the trigger to remove, by its id or key.', `List them: ekanos teams triggers list ${team} ${key}`);
65
92
  }
66
93
  noExtra(run.operands, 3, 'triggers');
94
+ if (!run.args.yes) {
95
+ throw invalidStateError(`Removing trigger ${ref} from ${key} on ${team} stops it starting runs; a webhook trigger's URL stops working for good (adding it again makes a new one).`, `Re-run with --yes: ekanos teams triggers remove ${team} ${key} ${ref} --yes`);
96
+ }
97
+ const id = UUID.test(ref)
98
+ ? ref
99
+ : await triggerIdByKey(run, team, key, ref);
67
100
  const removed = await send(run, TeamAgentRowRemoveResultSchema, 'DELETE', `${base}/triggers/${encodeURIComponent(id)}`);
68
101
  return ctx.succeed(Object.assign({ host: run.host }, removed), ctx.ui.result({
69
102
  title: `Removed trigger ${removed.removed} from ${removed.agent.slug}`,
70
103
  }));
71
104
  }
105
+ case 'rotate':
106
+ return rotateSecret(ctx, run, team, key);
72
107
  default:
73
108
  throw usageError(`Unknown teams triggers subcommand "${run.verb}".`, usageFor('triggers'));
74
109
  }
@@ -121,11 +156,17 @@ export async function runTeamLinks(ctx, run) {
121
156
  }));
122
157
  }
123
158
  case 'remove': {
124
- const id = (_a = run.operands[2]) === null || _a === void 0 ? void 0 : _a.trim();
125
- if (!id) {
126
- throw usageError('Name the link to remove.', `List them: ekanos teams links list ${team} ${from}`);
159
+ const ref = (_a = run.operands[2]) === null || _a === void 0 ? void 0 : _a.trim();
160
+ if (!ref) {
161
+ throw usageError('Name the link to remove, by its id or the key of the agent it goes to.', `List them: ekanos teams links list ${team} ${from}`);
127
162
  }
128
163
  noExtra(run.operands, 3, 'links');
164
+ if (!run.args.yes) {
165
+ throw invalidStateError(`Removing link ${ref} from ${from} on ${team} means ${from} can no longer reach that agent.`, `Re-run with --yes: ekanos teams links remove ${team} ${from} ${ref} --yes`);
166
+ }
167
+ const id = UUID.test(ref)
168
+ ? ref
169
+ : await linkIdByTarget(run, team, from, ref);
129
170
  const removed = await send(run, TeamAgentRowRemoveResultSchema, 'DELETE', `${base}/links/${encodeURIComponent(id)}`);
130
171
  return ctx.succeed(Object.assign({ host: run.host }, removed), ctx.ui.result({
131
172
  title: `Removed link ${removed.removed} from ${removed.agent.slug}`,
@@ -135,11 +176,89 @@ export async function runTeamLinks(ctx, run) {
135
176
  throw usageError(`Unknown teams links subcommand "${run.verb}".`, usageFor('links'));
136
177
  }
137
178
  }
179
+ /**
180
+ * `triggers rotate <team> <key> <trigger-key|id>`: a webhook trigger's new
181
+ * bearer token, the old one revoked — shown once, as `add` shows it. A
182
+ * template's webhook trigger starts with no token, so this is also how its
183
+ * team gets one. Replacing a live token cuts off whoever sends with it, so
184
+ * that needs `--yes`, as `teams webhook` does.
185
+ */
186
+ async function rotateSecret(ctx, run, team, key) {
187
+ var _a;
188
+ var _b, _c, _d, _e, _f, _g, _h;
189
+ const ref = (_a = run.operands[2]) === null || _a === void 0 ? void 0 : _a.trim();
190
+ if (!ref) {
191
+ throw usageError('Name the webhook trigger, by its key or id.', `List them: ekanos teams triggers list ${team} ${key}`);
192
+ }
193
+ noExtra(run.operands, 3, 'triggers');
194
+ const base = agentPath(team, key);
195
+ const list = await send(run, TeamAgentTriggerListSchema, 'GET', `${base}/triggers`);
196
+ const trigger = (_b = list.triggers.find((entry) => entry.id === ref)) !== null && _b !== void 0 ? _b : list.triggers.find((entry) => entry.key === ref.toLowerCase());
197
+ if (!trigger) {
198
+ throw usageError(`${list.agent.slug} on ${list.team.slug} has no trigger "${ref}".`, `List them: ekanos teams triggers list ${team} ${key}`);
199
+ }
200
+ if (trigger.type !== 'webhook') {
201
+ throw usageError(`"${ref}" is a ${trigger.type} trigger; only a webhook trigger has a token to rotate.`, `List them: ekanos teams triggers list ${team} ${key}`);
202
+ }
203
+ if (trigger.secretSet !== false && !run.args.yes) {
204
+ throw invalidStateError(`${(_c = trigger.key) !== null && _c !== void 0 ? _c : trigger.id} on ${list.team.slug} already has a token. A new one revokes it, and whatever sends to the URL with the old token is refused until it uses the new one.`, `Re-run with --yes when you are ready to update the sender: ekanos teams triggers rotate ${team} ${key} ${ref} --yes`);
205
+ }
206
+ const secrets = ensureSecretsDir(run.args.env);
207
+ const rotated = await send(run, TeamAgentTriggerAddResultSchema, 'POST', `${base}/triggers/${encodeURIComponent(trigger.id)}`, { rotate: true });
208
+ const { webhook } = rotated, rest = __rest(rotated, ["webhook"]);
209
+ const saved = webhook
210
+ ? saveTriggerToken(run, secrets, {
211
+ team: rotated.team.slug,
212
+ agent: rotated.agent.slug,
213
+ trigger: (_d = rotated.trigger.key) !== null && _d !== void 0 ? _d : rotated.trigger.id,
214
+ webhook,
215
+ again: `ekanos teams triggers rotate ${team} ${key} ${ref} --yes`,
216
+ })
217
+ : null;
218
+ return ctx.succeed(Object.assign(Object.assign({ host: run.host }, rest), { webhook: (_e = saved === null || saved === void 0 ? void 0 : saved.json) !== null && _e !== void 0 ? _e : null }), ctx.ui.result({
219
+ title: `New token for ${(_f = rotated.trigger.key) !== null && _f !== void 0 ? _f : rotated.trigger.id} on ${rotated.team.slug}`,
220
+ tone: 'warn',
221
+ rows: (_g = saved === null || saved === void 0 ? void 0 : saved.rows) !== null && _g !== void 0 ? _g : [],
222
+ notes: [
223
+ ...((_h = saved === null || saved === void 0 ? void 0 : saved.notes) !== null && _h !== void 0 ? _h : []),
224
+ ...(trigger.secretSet === false
225
+ ? []
226
+ : ['The previous token is revoked.']),
227
+ ],
228
+ }));
229
+ }
230
+ /**
231
+ * A webhook trigger's bearer token goes to a 0600 file, never to the output
232
+ * (a terminal, or an agent's context). The URL is not a secret — the trigger
233
+ * id — so it is still printed. JSON carries `{ url, secretFile }`.
234
+ */
235
+ function saveTriggerToken(run, dir, input) {
236
+ const file = writeSecretFile(dir !== null && dir !== void 0 ? dir : ensureSecretsDir(run.args.env), {
237
+ owner: input.team,
238
+ what: `${input.agent}-${input.trigger}-trigger-token`,
239
+ purpose: `Bearer token for the webhook trigger ${input.trigger} of agent ${input.agent} on team ${input.team} (source ${run.source}). Send it as "Authorization: Bearer <token>" when you POST JSON to ${input.webhook.url}.`,
240
+ values: [
241
+ ['URL', input.webhook.url],
242
+ ['BEARER_TOKEN', input.webhook.token],
243
+ ],
244
+ again: input.again,
245
+ });
246
+ return {
247
+ json: { url: input.webhook.url, secretFile: file },
248
+ rows: [
249
+ ['URL', input.webhook.url],
250
+ ['Bearer token', `saved to ${file} (readable only by you)`],
251
+ ],
252
+ notes: [
253
+ 'The token is shown nowhere else and cannot be read again. Copy it from that file into the sender yourself — not into a chat or an agent session — then delete the file. POST JSON to the URL with "Authorization: Bearer <token>".',
254
+ ],
255
+ };
256
+ }
138
257
  function triggerBody(run, team, key) {
139
- var _a, _b;
140
- var _c, _d;
258
+ var _a, _b, _c, _d;
259
+ var _e, _f;
141
260
  const type = (_a = run.operands[2]) === null || _a === void 0 ? void 0 : _a.trim().toLowerCase();
142
- const prompt = (_c = flag(run, 'prompt')) !== null && _c !== void 0 ? _c : '';
261
+ const prompt = (_e = flag(run, 'prompt')) !== null && _e !== void 0 ? _e : '';
143
262
  switch (type) {
144
263
  case 'manual':
145
264
  noExtra(run.operands, 3, 'triggers');
@@ -153,7 +272,7 @@ function triggerBody(run, team, key) {
153
272
  return {
154
273
  type: 'schedule',
155
274
  scheduleCron: cron,
156
- timezone: (_d = flag(run, 'timezone')) !== null && _d !== void 0 ? _d : 'UTC',
275
+ timezone: (_f = flag(run, 'timezone')) !== null && _f !== void 0 ? _f : 'UTC',
157
276
  promptTemplate: prompt,
158
277
  };
159
278
  }
@@ -173,41 +292,81 @@ function triggerBody(run, team, key) {
173
292
  return {
174
293
  type: 'integration_event',
175
294
  eventId,
176
- filter: parseFilter(flag(run, 'filter')),
295
+ filter: parseFilters(filterFlag(run)),
177
296
  promptTemplate: prompt,
178
297
  };
179
298
  }
180
- case 'slack':
181
- case 'linear':
182
- throw usageError(`A ${type} trigger is connected in the app, where the team picks its workspace and channels.`, 'Open the agent in the app and add it under Triggers.');
299
+ case 'slack': {
300
+ noExtra(run.operands, 3, 'triggers');
301
+ const channels = listFlag(run, 'channel');
302
+ const directMessages = ((_c = run.args.flags) === null || _c === void 0 ? void 0 : _c.dms) === true;
303
+ if (channels.length === 0 && !directMessages) {
304
+ throw usageError('A slack trigger answers in channels, direct messages, or both.', `e.g. ekanos teams triggers add ${team} ${key} slack --channel '#support' --dms --yes (the bot must be in each channel; "ekanos teams connect ${team} slack" installs Slack first)`);
305
+ }
306
+ if (!run.args.yes) {
307
+ throw usageError('Anyone in those channels, and anyone who messages the bot, can then ask the agent to act with everything it is granted.', 'Pass --yes to confirm that audience, as the app asks before it adds the trigger.');
308
+ }
309
+ return {
310
+ type: 'slack',
311
+ channels,
312
+ directMessages,
313
+ promptTemplate: prompt,
314
+ confirmAudience: true,
315
+ };
316
+ }
317
+ case 'linear': {
318
+ noExtra(run.operands, 3, 'triggers');
319
+ const labelNames = listFlag(run, 'label');
320
+ const onMention = ((_d = run.args.flags) === null || _d === void 0 ? void 0 : _d.mention) !== false;
321
+ if (!onMention && labelNames.length === 0) {
322
+ throw usageError('A linear trigger answers @mentions, labelled issues, or both.', `e.g. ekanos teams triggers add ${team} ${key} linear --label feedback ("ekanos teams connect ${team} linear-app" installs the Ekanos Linear app first). The Linear integration's own events are event triggers: "ekanos catalog linear --json" lists them.`);
323
+ }
324
+ return { type: 'linear', onMention, labelNames, promptTemplate: prompt };
325
+ }
183
326
  default:
184
327
  throw usageError(type ? `Unknown trigger type "${type}".` : 'Name the trigger type.', usageFor('triggers'));
185
328
  }
186
329
  }
187
- function parseFilter(raw) {
188
- if (!raw)
189
- return {};
190
- let parsed;
191
- try {
192
- parsed = JSON.parse(raw);
330
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
331
+ /**
332
+ * A trigger named by key, the name it has in agent.json. Only a template's
333
+ * trigger has one, and it changes at the template, so that is said here
334
+ * with the template-level command rather than left to the host's refusal.
335
+ */
336
+ async function triggerIdByKey(run, team, key, ref) {
337
+ const list = await send(run, TeamAgentTriggerListSchema, 'GET', `${agentPath(team, key)}/triggers`);
338
+ const trigger = list.triggers.find((entry) => entry.key === ref.toLowerCase());
339
+ if (!trigger) {
340
+ throw usageError(`${list.agent.slug} on ${list.team.slug} has no trigger "${ref}".`, `List them: ekanos teams triggers list ${team} ${key}`);
193
341
  }
194
- catch (_a) {
195
- throw usageError('--filter must be a JSON object.', `e.g. --filter '{"priority":["urgent","high"]}'`);
342
+ if (trigger.owner === 'template') {
343
+ throw invalidStateError(`Trigger ${ref} comes from the template, so it can only change there.`, `Remove it from the template for every team: ekanos agents triggers ${key} remove ${ref}, then publish.`);
196
344
  }
197
- if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
198
- throw usageError('--filter must be a JSON object.', `e.g. --filter '{"priority":["urgent","high"]}'`);
345
+ return trigger.id;
346
+ }
347
+ /**
348
+ * A link named by the key of the agent it goes to, as the template level
349
+ * names it. Two links to one agent (talk and delegate) need `--kind`.
350
+ */
351
+ async function linkIdByTarget(run, team, from, to) {
352
+ const list = await send(run, TeamAgentLinkListSchema, 'GET', `${agentPath(team, from)}/links`);
353
+ const kind = flag(run, 'kind');
354
+ const matches = list.links.filter((link) => link.to.slug === to.toLowerCase() && (!kind || link.kind === kind));
355
+ if (matches.length === 0) {
356
+ throw usageError(`${list.agent.slug} on ${list.team.slug} has no link to "${to}"${kind ? ` of kind ${kind}` : ''}.`, `List them: ekanos teams links list ${team} ${from}`);
199
357
  }
200
- const filter = {};
201
- for (const [name, value] of Object.entries(parsed)) {
202
- if (typeof value === 'string' ||
203
- typeof value === 'boolean' ||
204
- (Array.isArray(value) && value.every((item) => typeof item === 'string'))) {
205
- filter[name] = value;
206
- continue;
207
- }
208
- throw usageError(`--filter field "${name}" must be a string, a boolean or a list of strings.`, `e.g. --filter '{"priority":["urgent","high"]}'`);
358
+ if (matches.length > 1) {
359
+ throw usageError(`${list.agent.slug} has more than one link to ${to}.`, `Name which with --kind talk|delegate: ekanos teams links remove ${team} ${from} ${to} --kind delegate`);
209
360
  }
210
- return filter;
361
+ return matches[0].id;
362
+ }
363
+ /** `--filter`, repeatable: `field=value` or a JSON object, as at the template level. */
364
+ function filterFlag(run) {
365
+ var _a;
366
+ const value = (_a = run.args.flags) === null || _a === void 0 ? void 0 : _a.filter;
367
+ if (Array.isArray(value))
368
+ return value;
369
+ return typeof value === 'string' ? [value] : [];
211
370
  }
212
371
  function describeTrigger(trigger) {
213
372
  var _a, _b, _c;
@@ -217,8 +376,11 @@ function describeTrigger(trigger) {
217
376
  ? `event ${(_c = trigger.eventId) !== null && _c !== void 0 ? _c : ''}${trigger.filter && Object.keys(trigger.filter).length > 0 ? ` ${JSON.stringify(trigger.filter)}` : ''}`
218
377
  : trigger.type;
219
378
  const tags = [
220
- trigger.owner === 'template' ? 'from template' : 'team',
379
+ trigger.owner === 'template'
380
+ ? `from template${trigger.key ? ` (key ${trigger.key})` : ''}`
381
+ : 'team',
221
382
  trigger.active ? 'on' : 'off',
383
+ ...(trigger.secretSet === false ? ['no token yet'] : []),
222
384
  ];
223
385
  return `${what} · ${tags.join(' · ')}`;
224
386
  }
@@ -239,6 +401,20 @@ function flag(run, name) {
239
401
  const value = (_a = run.args.flags) === null || _a === void 0 ? void 0 : _a[name];
240
402
  return typeof value === 'string' && value.trim() ? value.trim() : undefined;
241
403
  }
404
+ /** A repeatable flag's values; each may also be comma-separated. */
405
+ function listFlag(run, name) {
406
+ var _a;
407
+ const value = (_a = run.args.flags) === null || _a === void 0 ? void 0 : _a[name];
408
+ const values = Array.isArray(value)
409
+ ? value
410
+ : typeof value === 'string'
411
+ ? [value]
412
+ : [];
413
+ return values
414
+ .flatMap((entry) => entry.split(','))
415
+ .map((entry) => entry.trim())
416
+ .filter(Boolean);
417
+ }
242
418
  function noExtra(operands, count, area) {
243
419
  const extra = operands[count];
244
420
  if (extra !== undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"team-agents-triggers.js","sourceRoot":"","sources":["../../src/commands/team-agents-triggers.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type TeamAgentLink,\n type TeamAgentLinkAddRequest,\n TeamAgentLinkAddResultSchema,\n TeamAgentLinkListSchema,\n TeamAgentRowRemoveResultSchema,\n type TeamAgentTrigger,\n type TeamAgentTriggerAddRequest,\n TeamAgentTriggerAddResultSchema,\n TeamAgentTriggerListSchema,\n} from '@ekanos/integration-schema';\nimport type { z } from 'zod';\n\nimport type { CliContext } from '../context';\nimport { usageError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { call } from '../teams-api';\nimport { type TeamAgentRun, requireOperand, usageFor } from './team-agents';\n\n/**\n * `ekanos teams triggers list|add|remove` and `ekanos teams links\n * list|add|remove` — a team agent's triggers and outgoing links, set up by\n * the Source admin. When the template keeps an area, the host shows the\n * effective rows and refuses changes with the command that hands the area\n * to the team.\n */\n\nexport async function runTeamTriggers(\n ctx: CliContext,\n run: TeamAgentRun,\n): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'triggers');\n const key = requireOperand(run.operands[1], 'agent key', 'triggers');\n const base = agentPath(team, key);\n\n switch (run.verb) {\n case 'list': {\n noExtra(run.operands, 2, 'triggers');\n const list = await send(\n run,\n TeamAgentTriggerListSchema,\n 'GET',\n `${base}/triggers`,\n );\n return ctx.succeed(\n { host: run.host, ...list },\n ctx.ui.result({\n title:\n list.triggers.length === 0\n ? `${list.agent.slug} on ${list.team.slug} has no triggers`\n : `Triggers of ${list.agent.slug} on ${list.team.slug}`,\n tone: list.triggers.length === 0 ? 'warn' : 'ok',\n rows: list.triggers.map((trigger) => [\n trigger.id,\n describeTrigger(trigger),\n ]),\n notes: list.teamOwned\n ? [\n '\"ekanos teams triggers add <team> <key> manual|schedule|webhook|event …\" adds one.',\n ]\n : [\n `These follow the template. To let the team change them: ekanos agents overrides ${key} enable triggers`,\n ],\n }),\n );\n }\n case 'add': {\n const body = triggerBody(run, team, key);\n const added = await send(\n run,\n TeamAgentTriggerAddResultSchema,\n 'POST',\n `${base}/triggers`,\n body,\n );\n const rows: Array<[string, string]> = [\n ['Trigger', added.trigger.id],\n ['Fires on', describeTrigger(added.trigger)],\n ];\n if (added.webhook) {\n rows.push(['URL', added.webhook.url]);\n rows.push(['Bearer token', added.webhook.token]);\n }\n return ctx.succeed(\n { host: run.host, ...added },\n ctx.ui.result({\n title: `Added a ${added.trigger.type} trigger to ${added.agent.slug} on ${added.team.slug}`,\n tone: added.webhook ? 'warn' : 'ok',\n rows,\n notes: added.webhook\n ? [\n 'The URL and token are shown once and cannot be read again. POST JSON to the URL with \"Authorization: Bearer <token>\".',\n ]\n : [],\n }),\n );\n }\n case 'remove': {\n const id = run.operands[2]?.trim();\n if (!id) {\n throw usageError(\n 'Name the trigger to remove.',\n `List them: ekanos teams triggers list ${team} ${key}`,\n );\n }\n noExtra(run.operands, 3, 'triggers');\n const removed = await send(\n run,\n TeamAgentRowRemoveResultSchema,\n 'DELETE',\n `${base}/triggers/${encodeURIComponent(id)}`,\n );\n return ctx.succeed(\n { host: run.host, ...removed },\n ctx.ui.result({\n title: `Removed trigger ${removed.removed} from ${removed.agent.slug}`,\n }),\n );\n }\n default:\n throw usageError(\n `Unknown teams triggers subcommand \"${run.verb}\".`,\n usageFor('triggers'),\n );\n }\n}\n\nexport async function runTeamLinks(\n ctx: CliContext,\n run: TeamAgentRun,\n): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'links');\n const from = requireOperand(run.operands[1], 'agent key', 'links');\n const base = agentPath(team, from);\n\n switch (run.verb) {\n case 'list': {\n noExtra(run.operands, 2, 'links');\n const list = await send(\n run,\n TeamAgentLinkListSchema,\n 'GET',\n `${base}/links`,\n );\n return ctx.succeed(\n { host: run.host, ...list },\n ctx.ui.result({\n title:\n list.links.length === 0\n ? `${list.agent.slug} on ${list.team.slug} has no links`\n : `Links from ${list.agent.slug} on ${list.team.slug}`,\n tone: list.links.length === 0 ? 'warn' : 'ok',\n rows: list.links.map((link) => [link.id, describeLink(link)]),\n notes: list.teamOwned\n ? []\n : [\n `These follow the template. To let the team change them: ekanos agents overrides ${from} enable links`,\n ],\n }),\n );\n }\n case 'add': {\n const to = requireOperand(\n run.operands[2],\n 'agent key to link to',\n 'links',\n );\n noExtra(run.operands, 3, 'links');\n const kind = flag(run, 'kind');\n if (kind !== 'talk' && kind !== 'delegate') {\n throw usageError(\n 'Say what kind of link: --kind talk|delegate.',\n usageFor('links'),\n );\n }\n const mode = flag(run, 'mode');\n if (mode !== undefined && mode !== 'await' && mode !== 'handoff') {\n throw usageError('--mode is await or handoff.', usageFor('links'));\n }\n if (mode !== undefined && kind === 'talk') {\n throw usageError(\n 'Only a delegate link takes --mode.',\n usageFor('links'),\n );\n }\n const body: TeamAgentLinkAddRequest = {\n to,\n kind,\n ...(mode ? { mode } : {}),\n };\n const added = await send(\n run,\n TeamAgentLinkAddResultSchema,\n 'POST',\n `${base}/links`,\n body,\n );\n return ctx.succeed(\n { host: run.host, ...added },\n ctx.ui.result({\n title: `Linked ${added.agent.slug} → ${added.link.to.slug} on ${added.team.slug}`,\n rows: [\n ['Link', added.link.id],\n ['Kind', describeLink(added.link)],\n ],\n }),\n );\n }\n case 'remove': {\n const id = run.operands[2]?.trim();\n if (!id) {\n throw usageError(\n 'Name the link to remove.',\n `List them: ekanos teams links list ${team} ${from}`,\n );\n }\n noExtra(run.operands, 3, 'links');\n const removed = await send(\n run,\n TeamAgentRowRemoveResultSchema,\n 'DELETE',\n `${base}/links/${encodeURIComponent(id)}`,\n );\n return ctx.succeed(\n { host: run.host, ...removed },\n ctx.ui.result({\n title: `Removed link ${removed.removed} from ${removed.agent.slug}`,\n }),\n );\n }\n default:\n throw usageError(\n `Unknown teams links subcommand \"${run.verb}\".`,\n usageFor('links'),\n );\n }\n}\n\nfunction triggerBody(\n run: TeamAgentRun,\n team: string,\n key: string,\n): TeamAgentTriggerAddRequest {\n const type = run.operands[2]?.trim().toLowerCase();\n const prompt = flag(run, 'prompt') ?? '';\n switch (type) {\n case 'manual':\n noExtra(run.operands, 3, 'triggers');\n return { type: 'manual', promptTemplate: prompt };\n case 'schedule': {\n noExtra(run.operands, 3, 'triggers');\n const cron = flag(run, 'cron');\n if (!cron || !prompt) {\n throw usageError(\n 'A schedule needs --cron and --prompt.',\n `e.g. ekanos teams triggers add ${team} ${key} schedule --cron \"0 9 * * 1-5\" --timezone America/Los_Angeles --prompt \"Summarize yesterday's tickets\"`,\n );\n }\n return {\n type: 'schedule',\n scheduleCron: cron,\n timezone: flag(run, 'timezone') ?? 'UTC',\n promptTemplate: prompt,\n };\n }\n case 'webhook':\n noExtra(run.operands, 3, 'triggers');\n if (!prompt) {\n throw usageError(\n 'A webhook needs --prompt: what to do with each request.',\n `e.g. ekanos teams triggers add ${team} ${key} webhook --prompt \"Triage this alert: {{body.title}}\"`,\n );\n }\n return { type: 'webhook', promptTemplate: prompt };\n case 'event':\n case 'integration_event': {\n const eventId = run.operands[3]?.trim();\n if (!eventId) {\n throw usageError(\n 'Name the event, e.g. zendesk.ticket_created.',\n `e.g. ekanos teams triggers add ${team} ${key} event zendesk.ticket_created --filter '{\"priority\":[\"urgent\"]}'`,\n );\n }\n noExtra(run.operands, 4, 'triggers');\n return {\n type: 'integration_event',\n eventId,\n filter: parseFilter(flag(run, 'filter')),\n promptTemplate: prompt,\n };\n }\n case 'slack':\n case 'linear':\n throw usageError(\n `A ${type} trigger is connected in the app, where the team picks its workspace and channels.`,\n 'Open the agent in the app and add it under Triggers.',\n );\n default:\n throw usageError(\n type ? `Unknown trigger type \"${type}\".` : 'Name the trigger type.',\n usageFor('triggers'),\n );\n }\n}\n\nfunction parseFilter(\n raw: string | undefined,\n): Record<string, string | boolean | string[]> {\n if (!raw) return {};\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw usageError(\n '--filter must be a JSON object.',\n `e.g. --filter '{\"priority\":[\"urgent\",\"high\"]}'`,\n );\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw usageError(\n '--filter must be a JSON object.',\n `e.g. --filter '{\"priority\":[\"urgent\",\"high\"]}'`,\n );\n }\n const filter: Record<string, string | boolean | string[]> = {};\n for (const [name, value] of Object.entries(parsed)) {\n if (\n typeof value === 'string' ||\n typeof value === 'boolean' ||\n (Array.isArray(value) && value.every((item) => typeof item === 'string'))\n ) {\n filter[name] = value as string | boolean | string[];\n continue;\n }\n throw usageError(\n `--filter field \"${name}\" must be a string, a boolean or a list of strings.`,\n `e.g. --filter '{\"priority\":[\"urgent\",\"high\"]}'`,\n );\n }\n return filter;\n}\n\nfunction describeTrigger(trigger: TeamAgentTrigger): string {\n const what =\n trigger.type === 'schedule'\n ? `schedule ${trigger.scheduleCron ?? ''} (${trigger.timezone ?? 'UTC'})`\n : trigger.type === 'integration_event'\n ? `event ${trigger.eventId ?? ''}${trigger.filter && Object.keys(trigger.filter).length > 0 ? ` ${JSON.stringify(trigger.filter)}` : ''}`\n : trigger.type;\n const tags = [\n trigger.owner === 'template' ? 'from template' : 'team',\n trigger.active ? 'on' : 'off',\n ];\n return `${what} · ${tags.join(' · ')}`;\n}\n\nfunction describeLink(link: TeamAgentLink): string {\n const kind =\n link.kind === 'delegate' ? `delegate (${link.mode ?? 'await'})` : 'talk';\n const tags = [\n link.owner === 'template' ? 'from template' : 'team',\n ...(link.active ? [] : ['inactive']),\n ];\n return `${kind} → ${link.to.slug} · ${tags.join(' · ')}`;\n}\n\nfunction agentPath(team: string, key: string): string {\n return `/api/partner/teams/${encodeURIComponent(team)}/agents/${encodeURIComponent(key)}`;\n}\n\nfunction flag(run: TeamAgentRun, name: string): string | undefined {\n const value = run.args.flags?.[name];\n return typeof value === 'string' && value.trim() ? value.trim() : undefined;\n}\n\nfunction noExtra(\n operands: readonly string[],\n count: number,\n area: 'triggers' | 'links',\n) {\n const extra = operands[count];\n if (extra !== undefined) {\n throw usageError(`Unexpected argument \"${extra}\".`, usageFor(area));\n }\n}\n\nfunction send<T>(\n run: TeamAgentRun,\n schema: z.ZodType<T>,\n method: 'GET' | 'POST' | 'DELETE',\n path: string,\n body?: unknown,\n): Promise<T> {\n return run.client.call((token) =>\n call(run.host, token, schema, { method, path, source: run.source, body }),\n );\n}\n"]}
1
+ {"version":3,"file":"team-agents-triggers.js","sourceRoot":"","sources":["../../src/commands/team-agents-triggers.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,OAAO,EAGL,4BAA4B,EAC5B,uBAAuB,EACvB,8BAA8B,EAG9B,+BAA+B,EAC/B,0BAA0B,GAC3B,MAAM,4BAA4B,CAAC;AAIpC,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE1D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAqB,cAAc,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE5E;;;;;;GAMG;AAEH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAe,EACf,GAAiB;;;IAEjB,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;IACtE,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAElC,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YACrC,MAAM,IAAI,GAAG,MAAM,IAAI,CACrB,GAAG,EACH,0BAA0B,EAC1B,KAAK,EACL,GAAG,IAAI,WAAW,CACnB,CAAC;YACF,OAAO,GAAG,CAAC,OAAO,iBACd,IAAI,EAAE,GAAG,CAAC,IAAI,IAAK,IAAI,GACzB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC;gBACZ,KAAK,EACH,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;oBACxB,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,kBAAkB;oBAC3D,CAAC,CAAC,eAAe,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;gBAC3D,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;gBAChD,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;oBACnC,OAAO,CAAC,EAAE;oBACV,eAAe,CAAC,OAAO,CAAC;iBACzB,CAAC;gBACF,KAAK,EAAE;oBACL,GAAG,CAAC,IAAI,CAAC,SAAS;wBAChB,CAAC,CAAC;4BACE,oFAAoF;yBACrF;wBACH,CAAC,CAAC;4BACE,mFAAmF,GAAG,kBAAkB;yBACzG,CAAC;oBACN,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CACpB,CAAC,OAAO,EAAE,EAAE,CACV,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,KAAK,CAC5D;wBACC,CAAC,CAAC;4BACE,iGAAiG,IAAI,IAAI,GAAG,qBAAqB;yBAClI;wBACH,CAAC,CAAC,EAAE,CAAC;iBACR;aACF,CAAC,CACH,CAAC;QACJ,CAAC;QACD,KAAK,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YACzC,uEAAuE;YACvE,MAAM,OAAO,GACX,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAClE,MAAM,KAAK,GAAG,MAAM,IAAI,CACtB,GAAG,EACH,+BAA+B,EAC/B,MAAM,EACN,GAAG,IAAI,WAAW,EAClB,IAAI,CACL,CAAC;YACF,MAAM,IAAI,GAA4B;gBACpC,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7B,CAAC,UAAU,EAAE,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;aAC7C,CAAC;YACF,MAAM,EAAE,OAAO,KAAc,KAAK,EAAd,IAAI,UAAK,KAAK,EAA5B,WAAoB,CAAQ,CAAC;YACnC,MAAM,KAAK,GAAG,OAAO;gBACnB,CAAC,CAAC,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE;oBAC7B,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI;oBACrB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;oBACvB,OAAO,QAAE,KAAK,CAAC,OAAO,CAAC,GAAG,mCAAI,KAAK,CAAC,OAAO,CAAC,EAAE;oBAC9C,OAAO;oBACP,KAAK,EAAE,gCAAgC,IAAI,IAAI,GAAG,IAAI,MAAA,KAAK,CAAC,OAAO,CAAC,GAAG,mCAAI,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ;iBACpG,CAAC;gBACJ,CAAC,CAAC,IAAI,CAAC;YACT,IAAI,KAAK;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;YACpC,OAAO,GAAG,CAAC,OAAO,+BACd,IAAI,EAAE,GAAG,CAAC,IAAI,IAAK,IAAI,KAAE,OAAO,QAAE,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,mCAAI,IAAI,KACvD,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC;gBACZ,KAAK,EAAE,WAAW,KAAK,CAAC,OAAO,CAAC,IAAI,eAAe,KAAK,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE;gBAC3F,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;gBAC3B,IAAI;gBACJ,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;aAChC,CAAC,CACH,CAAC;QACJ,CAAC;QACD,KAAK,QAAQ,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,MAAA,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,0CAAE,IAAI,EAAE,CAAC;YACpC,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,UAAU,CACd,+CAA+C,EAC/C,yCAAyC,IAAI,IAAI,GAAG,EAAE,CACvD,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YACrC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;gBAClB,MAAM,iBAAiB,CACrB,oBAAoB,GAAG,SAAS,GAAG,OAAO,IAAI,4GAA4G,EAC1J,mDAAmD,IAAI,IAAI,GAAG,IAAI,GAAG,QAAQ,CAC9E,CAAC;YACJ,CAAC;YACD,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;gBACvB,CAAC,CAAC,GAAG;gBACL,CAAC,CAAC,MAAM,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAC9C,MAAM,OAAO,GAAG,MAAM,IAAI,CACxB,GAAG,EACH,8BAA8B,EAC9B,QAAQ,EACR,GAAG,IAAI,aAAa,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAC7C,CAAC;YACF,OAAO,GAAG,CAAC,OAAO,iBACd,IAAI,EAAE,GAAG,CAAC,IAAI,IAAK,OAAO,GAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC;gBACZ,KAAK,EAAE,mBAAmB,OAAO,CAAC,OAAO,SAAS,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE;aACvE,CAAC,CACH,CAAC;QACJ,CAAC;QACD,KAAK,QAAQ;YACX,OAAO,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QAC3C;YACE,MAAM,UAAU,CACd,sCAAsC,GAAG,CAAC,IAAI,IAAI,EAClD,QAAQ,CAAC,UAAU,CAAC,CACrB,CAAC;IACN,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAe,EACf,GAAiB;;IAEjB,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAEnC,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;YAClC,MAAM,IAAI,GAAG,MAAM,IAAI,CACrB,GAAG,EACH,uBAAuB,EACvB,KAAK,EACL,GAAG,IAAI,QAAQ,CAChB,CAAC;YACF,OAAO,GAAG,CAAC,OAAO,iBACd,IAAI,EAAE,GAAG,CAAC,IAAI,IAAK,IAAI,GACzB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC;gBACZ,KAAK,EACH,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;oBACrB,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe;oBACxD,CAAC,CAAC,cAAc,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;gBAC1D,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;gBAC7C,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC7D,KAAK,EAAE,IAAI,CAAC,SAAS;oBACnB,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC;wBACE,mFAAmF,IAAI,eAAe;qBACvG;aACN,CAAC,CACH,CAAC;QACJ,CAAC;QACD,KAAK,KAAK,EAAE,CAAC;YACX,MAAM,EAAE,GAAG,cAAc,CACvB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EACf,sBAAsB,EACtB,OAAO,CACR,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;YAClC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC/B,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC3C,MAAM,UAAU,CACd,8CAA8C,EAC9C,QAAQ,CAAC,OAAO,CAAC,CAClB,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC/B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACjE,MAAM,UAAU,CAAC,6BAA6B,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YACrE,CAAC;YACD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC1C,MAAM,UAAU,CACd,oCAAoC,EACpC,QAAQ,CAAC,OAAO,CAAC,CAClB,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,mBACR,EAAE;gBACF,IAAI,IACD,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC1B,CAAC;YACF,MAAM,KAAK,GAAG,MAAM,IAAI,CACtB,GAAG,EACH,4BAA4B,EAC5B,MAAM,EACN,GAAG,IAAI,QAAQ,EACf,IAAI,CACL,CAAC;YACF,OAAO,GAAG,CAAC,OAAO,iBACd,IAAI,EAAE,GAAG,CAAC,IAAI,IAAK,KAAK,GAC1B,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC;gBACZ,KAAK,EAAE,UAAU,KAAK,CAAC,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE;gBACjF,IAAI,EAAE;oBACJ,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBACvB,CAAC,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;iBACnC;aACF,CAAC,CACH,CAAC;QACJ,CAAC;QACD,KAAK,QAAQ,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,MAAA,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,0CAAE,IAAI,EAAE,CAAC;YACpC,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,UAAU,CACd,wEAAwE,EACxE,sCAAsC,IAAI,IAAI,IAAI,EAAE,CACrD,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;YAClC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;gBAClB,MAAM,iBAAiB,CACrB,iBAAiB,GAAG,SAAS,IAAI,OAAO,IAAI,UAAU,IAAI,kCAAkC,EAC5F,gDAAgD,IAAI,IAAI,IAAI,IAAI,GAAG,QAAQ,CAC5E,CAAC;YACJ,CAAC;YACD,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;gBACvB,CAAC,CAAC,GAAG;gBACL,CAAC,CAAC,MAAM,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/C,MAAM,OAAO,GAAG,MAAM,IAAI,CACxB,GAAG,EACH,8BAA8B,EAC9B,QAAQ,EACR,GAAG,IAAI,UAAU,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAC1C,CAAC;YACF,OAAO,GAAG,CAAC,OAAO,iBACd,IAAI,EAAE,GAAG,CAAC,IAAI,IAAK,OAAO,GAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC;gBACZ,KAAK,EAAE,gBAAgB,OAAO,CAAC,OAAO,SAAS,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE;aACpE,CAAC,CACH,CAAC;QACJ,CAAC;QACD;YACE,MAAM,UAAU,CACd,mCAAmC,GAAG,CAAC,IAAI,IAAI,EAC/C,QAAQ,CAAC,OAAO,CAAC,CAClB,CAAC;IACN,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,YAAY,CACzB,GAAe,EACf,GAAiB,EACjB,IAAY,EACZ,GAAW;;;IAEX,MAAM,GAAG,GAAG,MAAA,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,0CAAE,IAAI,EAAE,CAAC;IACpC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,UAAU,CACd,6CAA6C,EAC7C,yCAAyC,IAAI,IAAI,GAAG,EAAE,CACvD,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IAErC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,MAAM,IAAI,CACrB,GAAG,EACH,0BAA0B,EAC1B,KAAK,EACL,GAAG,IAAI,WAAW,CACnB,CAAC;IACF,MAAM,OAAO,SACX,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,CAAC,mCAC/C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IACjE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,UAAU,CACd,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,oBAAoB,GAAG,IAAI,EAClE,yCAAyC,IAAI,IAAI,GAAG,EAAE,CACvD,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,UAAU,CACd,IAAI,GAAG,UAAU,OAAO,CAAC,IAAI,yDAAyD,EACtF,yCAAyC,IAAI,IAAI,GAAG,EAAE,CACvD,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,SAAS,KAAK,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACjD,MAAM,iBAAiB,CACrB,GAAG,MAAA,OAAO,CAAC,GAAG,mCAAI,OAAO,CAAC,EAAE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,oIAAoI,EACrL,2FAA2F,IAAI,IAAI,GAAG,IAAI,GAAG,QAAQ,CACtH,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,MAAM,IAAI,CACxB,GAAG,EACH,+BAA+B,EAC/B,MAAM,EACN,GAAG,IAAI,aAAa,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,EACpD,EAAE,MAAM,EAAE,IAAI,EAAE,CACjB,CAAC;IACF,MAAM,EAAE,OAAO,KAAc,OAAO,EAAhB,IAAI,UAAK,OAAO,EAA9B,WAAoB,CAAU,CAAC;IACrC,MAAM,KAAK,GAAG,OAAO;QACnB,CAAC,CAAC,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE;YAC7B,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI;YACvB,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI;YACzB,OAAO,QAAE,OAAO,CAAC,OAAO,CAAC,GAAG,mCAAI,OAAO,CAAC,OAAO,CAAC,EAAE;YAClD,OAAO;YACP,KAAK,EAAE,gCAAgC,IAAI,IAAI,GAAG,IAAI,GAAG,QAAQ;SAClE,CAAC;QACJ,CAAC,CAAC,IAAI,CAAC;IACT,OAAO,GAAG,CAAC,OAAO,+BACd,IAAI,EAAE,GAAG,CAAC,IAAI,IAAK,IAAI,KAAE,OAAO,QAAE,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,mCAAI,IAAI,KACvD,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC;QACZ,KAAK,EAAE,iBAAiB,MAAA,OAAO,CAAC,OAAO,CAAC,GAAG,mCAAI,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE;QAC3F,IAAI,EAAE,MAAM;QACZ,IAAI,QAAE,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,mCAAI,EAAE;QACvB,KAAK,EAAE;YACL,GAAG,OAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,KAAK,mCAAI,EAAE,CAAC;YACvB,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,KAAK;gBAC7B,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC;SACxC;KACF,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CACvB,GAAiB,EACjB,GAAkB,EAClB,KAMC;IAED,MAAM,IAAI,GAAG,eAAe,CAAC,GAAG,aAAH,GAAG,cAAH,GAAG,GAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAClE,KAAK,EAAE,KAAK,CAAC,IAAI;QACjB,IAAI,EAAE,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,gBAAgB;QACrD,OAAO,EAAE,wCAAwC,KAAK,CAAC,OAAO,aAAa,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,IAAI,YAAY,GAAG,CAAC,MAAM,uEAAuE,KAAK,CAAC,OAAO,CAAC,GAAG,GAAG;QAC7N,MAAM,EAAE;YACN,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAC1B,CAAC,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;SACtC;QACD,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC,CAAC;IACH,OAAO;QACL,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE;QAClD,IAAI,EAAE;YACJ,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAC1B,CAAC,cAAc,EAAE,YAAY,IAAI,yBAAyB,CAAC;SACjC;QAC5B,KAAK,EAAE;YACL,oOAAoO;SACrO;KACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAClB,GAAiB,EACjB,IAAY,EACZ,GAAW;;;IAEX,MAAM,IAAI,GAAG,MAAA,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,0CAAE,IAAI,GAAG,WAAW,EAAE,CAAC;IACnD,MAAM,MAAM,SAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,mCAAI,EAAE,CAAC;IACzC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YACrC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;QACpD,KAAK,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YACrC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC/B,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBACrB,MAAM,UAAU,CACd,uCAAuC,EACvC,kCAAkC,IAAI,IAAI,GAAG,wGAAwG,CACtJ,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,IAAI,EAAE,UAAU;gBAChB,YAAY,EAAE,IAAI;gBAClB,QAAQ,QAAE,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,mCAAI,KAAK;gBACxC,cAAc,EAAE,MAAM;aACvB,CAAC;QACJ,CAAC;QACD,KAAK,SAAS;YACZ,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,UAAU,CACd,yDAAyD,EACzD,kCAAkC,IAAI,IAAI,GAAG,uDAAuD,CACrG,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;QACrD,KAAK,OAAO,CAAC;QACb,KAAK,mBAAmB,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,MAAA,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,0CAAE,IAAI,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,UAAU,CACd,8CAA8C,EAC9C,kCAAkC,IAAI,IAAI,GAAG,kEAAkE,CAChH,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YACrC,OAAO;gBACL,IAAI,EAAE,mBAAmB;gBACzB,OAAO;gBACP,MAAM,EAAE,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;gBACrC,cAAc,EAAE,MAAM;aACvB,CAAC;QACJ,CAAC;QACD,KAAK,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YACrC,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAC1C,MAAM,cAAc,GAAG,CAAA,MAAA,GAAG,CAAC,IAAI,CAAC,KAAK,0CAAE,GAAG,MAAK,IAAI,CAAC;YACpD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;gBAC7C,MAAM,UAAU,CACd,gEAAgE,EAChE,kCAAkC,IAAI,IAAI,GAAG,mGAAmG,IAAI,+BAA+B,CACpL,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;gBAClB,MAAM,UAAU,CACd,yHAAyH,EACzH,kFAAkF,CACnF,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,IAAI,EAAE,OAAO;gBACb,QAAQ;gBACR,cAAc;gBACd,cAAc,EAAE,MAAM;gBACtB,eAAe,EAAE,IAAI;aACtB,CAAC;QACJ,CAAC;QACD,KAAK,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YACrC,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAC1C,MAAM,SAAS,GAAG,CAAA,MAAA,GAAG,CAAC,IAAI,CAAC,KAAK,0CAAE,OAAO,MAAK,KAAK,CAAC;YACpD,IAAI,CAAC,SAAS,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1C,MAAM,UAAU,CACd,+DAA+D,EAC/D,kCAAkC,IAAI,IAAI,GAAG,mDAAmD,IAAI,wJAAwJ,CAC7P,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;QAC3E,CAAC;QACD;YACE,MAAM,UAAU,CACd,IAAI,CAAC,CAAC,CAAC,yBAAyB,IAAI,IAAI,CAAC,CAAC,CAAC,wBAAwB,EACnE,QAAQ,CAAC,UAAU,CAAC,CACrB,CAAC;IACN,CAAC;AACH,CAAC;AAED,MAAM,IAAI,GAAG,iEAAiE,CAAC;AAE/E;;;;GAIG;AACH,KAAK,UAAU,cAAc,CAC3B,GAAiB,EACjB,IAAY,EACZ,GAAW,EACX,GAAW;IAEX,MAAM,IAAI,GAAG,MAAM,IAAI,CACrB,GAAG,EACH,0BAA0B,EAC1B,KAAK,EACL,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,WAAW,CACnC,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAChC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,WAAW,EAAE,CAC3C,CAAC;IACF,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,UAAU,CACd,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,oBAAoB,GAAG,IAAI,EAClE,yCAAyC,IAAI,IAAI,GAAG,EAAE,CACvD,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,iBAAiB,CACrB,WAAW,GAAG,wDAAwD,EACtE,sEAAsE,GAAG,WAAW,GAAG,iBAAiB,CACzG,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,EAAE,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,cAAc,CAC3B,GAAiB,EACjB,IAAY,EACZ,IAAY,EACZ,EAAU;IAEV,MAAM,IAAI,GAAG,MAAM,IAAI,CACrB,GAAG,EACH,uBAAuB,EACvB,KAAK,EACL,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CACjC,CAAC;IACF,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAC/B,CAAC,IAAI,EAAE,EAAE,CACP,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CACrE,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,UAAU,CACd,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,oBAAoB,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAClG,sCAAsC,IAAI,IAAI,IAAI,EAAE,CACrD,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,UAAU,CACd,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,8BAA8B,EAAE,GAAG,EACrD,mEAAmE,IAAI,IAAI,IAAI,IAAI,EAAE,kBAAkB,CACxG,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;AACxB,CAAC;AAED,wFAAwF;AACxF,SAAS,UAAU,CAAC,GAAiB;;IACnC,MAAM,KAAK,GAAG,MAAA,GAAG,CAAC,IAAI,CAAC,KAAK,0CAAE,MAAM,CAAC;IACrC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAClD,CAAC;AAED,SAAS,eAAe,CAAC,OAAyB;;IAChD,MAAM,IAAI,GACR,OAAO,CAAC,IAAI,KAAK,UAAU;QACzB,CAAC,CAAC,YAAY,MAAA,OAAO,CAAC,YAAY,mCAAI,EAAE,KAAK,MAAA,OAAO,CAAC,QAAQ,mCAAI,KAAK,GAAG;QACzE,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,mBAAmB;YACpC,CAAC,CAAC,SAAS,MAAA,OAAO,CAAC,OAAO,mCAAI,EAAE,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;YACzI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IACrB,MAAM,IAAI,GAAG;QACX,OAAO,CAAC,KAAK,KAAK,UAAU;YAC1B,CAAC,CAAC,gBAAgB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC9D,CAAC,CAAC,MAAM;QACV,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;QAC7B,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KACzD,CAAC;IACF,OAAO,GAAG,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;AACzC,CAAC;AAED,SAAS,YAAY,CAAC,IAAmB;;IACvC,MAAM,IAAI,GACR,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,aAAa,MAAA,IAAI,CAAC,IAAI,mCAAI,OAAO,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;IAC3E,MAAM,IAAI,GAAG;QACX,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM;QACpD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;KACrC,CAAC;IACF,OAAO,GAAG,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;AAC3D,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,GAAW;IAC1C,OAAO,sBAAsB,kBAAkB,CAAC,IAAI,CAAC,WAAW,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;AAC5F,CAAC;AAED,SAAS,IAAI,CAAC,GAAiB,EAAE,IAAY;;IAC3C,MAAM,KAAK,GAAG,MAAA,GAAG,CAAC,IAAI,CAAC,KAAK,0CAAG,IAAI,CAAC,CAAC;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9E,CAAC;AAED,oEAAoE;AACpE,SAAS,QAAQ,CAAC,GAAiB,EAAE,IAAY;;IAC/C,MAAM,KAAK,GAAG,MAAA,GAAG,CAAC,IAAI,CAAC,KAAK,0CAAG,IAAI,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACjC,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;YACzB,CAAC,CAAC,CAAC,KAAK,CAAC;YACT,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,MAAM;SACV,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;SACpC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,OAAO,CACd,QAA2B,EAC3B,KAAa,EACb,IAA0B;IAE1B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,UAAU,CAAC,wBAAwB,KAAK,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAED,SAAS,IAAI,CACX,GAAiB,EACjB,MAAoB,EACpB,MAAiC,EACjC,IAAY,EACZ,IAAc;IAEd,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAC/B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAC1E,CAAC;AACJ,CAAC","sourcesContent":["import {\n type TeamAgentLink,\n type TeamAgentLinkAddRequest,\n TeamAgentLinkAddResultSchema,\n TeamAgentLinkListSchema,\n TeamAgentRowRemoveResultSchema,\n type TeamAgentTrigger,\n type TeamAgentTriggerAddRequest,\n TeamAgentTriggerAddResultSchema,\n TeamAgentTriggerListSchema,\n} from '@ekanos/integration-schema';\nimport type { z } from 'zod';\n\nimport type { CliContext } from '../context';\nimport { invalidStateError, usageError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { ensureSecretsDir, writeSecretFile } from '../secret-file';\nimport { call } from '../teams-api';\nimport { parseFilters } from './agents-edit';\nimport { type TeamAgentRun, requireOperand, usageFor } from './team-agents';\n\n/**\n * `ekanos teams triggers list|add|remove` and `ekanos teams links\n * list|add|remove` — a team agent's triggers and outgoing links, set up by\n * the Source admin. When the template keeps an area, the host shows the\n * effective rows and refuses changes with the command that hands the area\n * to the team.\n */\n\nexport async function runTeamTriggers(\n ctx: CliContext,\n run: TeamAgentRun,\n): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'triggers');\n const key = requireOperand(run.operands[1], 'agent key', 'triggers');\n const base = agentPath(team, key);\n\n switch (run.verb) {\n case 'list': {\n noExtra(run.operands, 2, 'triggers');\n const list = await send(\n run,\n TeamAgentTriggerListSchema,\n 'GET',\n `${base}/triggers`,\n );\n return ctx.succeed(\n { host: run.host, ...list },\n ctx.ui.result({\n title:\n list.triggers.length === 0\n ? `${list.agent.slug} on ${list.team.slug} has no triggers`\n : `Triggers of ${list.agent.slug} on ${list.team.slug}`,\n tone: list.triggers.length === 0 ? 'warn' : 'ok',\n rows: list.triggers.map((trigger) => [\n trigger.id,\n describeTrigger(trigger),\n ]),\n notes: [\n ...(list.teamOwned\n ? [\n '\"ekanos teams triggers add <team> <key> manual|schedule|webhook|event …\" adds one.',\n ]\n : [\n `These follow the template. To let the team change them: ekanos agents overrides ${key} enable triggers`,\n ]),\n ...(list.triggers.some(\n (trigger) =>\n trigger.type === 'webhook' && trigger.secretSet === false,\n )\n ? [\n `A webhook trigger with no token yet gets its URL and token from \"ekanos teams triggers rotate ${team} ${key} <trigger-key|id>\".`,\n ]\n : []),\n ],\n }),\n );\n }\n case 'add': {\n const body = triggerBody(run, team, key);\n // A webhook trigger's token comes back once: have somewhere to put it.\n const secrets =\n body.type === 'webhook' ? ensureSecretsDir(run.args.env) : null;\n const added = await send(\n run,\n TeamAgentTriggerAddResultSchema,\n 'POST',\n `${base}/triggers`,\n body,\n );\n const rows: Array<[string, string]> = [\n ['Trigger', added.trigger.id],\n ['Fires on', describeTrigger(added.trigger)],\n ];\n const { webhook, ...rest } = added;\n const saved = webhook\n ? saveTriggerToken(run, secrets, {\n team: added.team.slug,\n agent: added.agent.slug,\n trigger: added.trigger.key ?? added.trigger.id,\n webhook,\n again: `ekanos teams triggers rotate ${team} ${key} ${added.trigger.key ?? added.trigger.id} --yes`,\n })\n : null;\n if (saved) rows.push(...saved.rows);\n return ctx.succeed(\n { host: run.host, ...rest, webhook: saved?.json ?? null },\n ctx.ui.result({\n title: `Added a ${added.trigger.type} trigger to ${added.agent.slug} on ${added.team.slug}`,\n tone: saved ? 'warn' : 'ok',\n rows,\n notes: saved ? saved.notes : [],\n }),\n );\n }\n case 'remove': {\n const ref = run.operands[2]?.trim();\n if (!ref) {\n throw usageError(\n 'Name the trigger to remove, by its id or key.',\n `List them: ekanos teams triggers list ${team} ${key}`,\n );\n }\n noExtra(run.operands, 3, 'triggers');\n if (!run.args.yes) {\n throw invalidStateError(\n `Removing trigger ${ref} from ${key} on ${team} stops it starting runs; a webhook trigger's URL stops working for good (adding it again makes a new one).`,\n `Re-run with --yes: ekanos teams triggers remove ${team} ${key} ${ref} --yes`,\n );\n }\n const id = UUID.test(ref)\n ? ref\n : await triggerIdByKey(run, team, key, ref);\n const removed = await send(\n run,\n TeamAgentRowRemoveResultSchema,\n 'DELETE',\n `${base}/triggers/${encodeURIComponent(id)}`,\n );\n return ctx.succeed(\n { host: run.host, ...removed },\n ctx.ui.result({\n title: `Removed trigger ${removed.removed} from ${removed.agent.slug}`,\n }),\n );\n }\n case 'rotate':\n return rotateSecret(ctx, run, team, key);\n default:\n throw usageError(\n `Unknown teams triggers subcommand \"${run.verb}\".`,\n usageFor('triggers'),\n );\n }\n}\n\nexport async function runTeamLinks(\n ctx: CliContext,\n run: TeamAgentRun,\n): Promise<ExitCode> {\n const team = requireOperand(run.operands[0], 'team slug', 'links');\n const from = requireOperand(run.operands[1], 'agent key', 'links');\n const base = agentPath(team, from);\n\n switch (run.verb) {\n case 'list': {\n noExtra(run.operands, 2, 'links');\n const list = await send(\n run,\n TeamAgentLinkListSchema,\n 'GET',\n `${base}/links`,\n );\n return ctx.succeed(\n { host: run.host, ...list },\n ctx.ui.result({\n title:\n list.links.length === 0\n ? `${list.agent.slug} on ${list.team.slug} has no links`\n : `Links from ${list.agent.slug} on ${list.team.slug}`,\n tone: list.links.length === 0 ? 'warn' : 'ok',\n rows: list.links.map((link) => [link.id, describeLink(link)]),\n notes: list.teamOwned\n ? []\n : [\n `These follow the template. To let the team change them: ekanos agents overrides ${from} enable links`,\n ],\n }),\n );\n }\n case 'add': {\n const to = requireOperand(\n run.operands[2],\n 'agent key to link to',\n 'links',\n );\n noExtra(run.operands, 3, 'links');\n const kind = flag(run, 'kind');\n if (kind !== 'talk' && kind !== 'delegate') {\n throw usageError(\n 'Say what kind of link: --kind talk|delegate.',\n usageFor('links'),\n );\n }\n const mode = flag(run, 'mode');\n if (mode !== undefined && mode !== 'await' && mode !== 'handoff') {\n throw usageError('--mode is await or handoff.', usageFor('links'));\n }\n if (mode !== undefined && kind === 'talk') {\n throw usageError(\n 'Only a delegate link takes --mode.',\n usageFor('links'),\n );\n }\n const body: TeamAgentLinkAddRequest = {\n to,\n kind,\n ...(mode ? { mode } : {}),\n };\n const added = await send(\n run,\n TeamAgentLinkAddResultSchema,\n 'POST',\n `${base}/links`,\n body,\n );\n return ctx.succeed(\n { host: run.host, ...added },\n ctx.ui.result({\n title: `Linked ${added.agent.slug} → ${added.link.to.slug} on ${added.team.slug}`,\n rows: [\n ['Link', added.link.id],\n ['Kind', describeLink(added.link)],\n ],\n }),\n );\n }\n case 'remove': {\n const ref = run.operands[2]?.trim();\n if (!ref) {\n throw usageError(\n 'Name the link to remove, by its id or the key of the agent it goes to.',\n `List them: ekanos teams links list ${team} ${from}`,\n );\n }\n noExtra(run.operands, 3, 'links');\n if (!run.args.yes) {\n throw invalidStateError(\n `Removing link ${ref} from ${from} on ${team} means ${from} can no longer reach that agent.`,\n `Re-run with --yes: ekanos teams links remove ${team} ${from} ${ref} --yes`,\n );\n }\n const id = UUID.test(ref)\n ? ref\n : await linkIdByTarget(run, team, from, ref);\n const removed = await send(\n run,\n TeamAgentRowRemoveResultSchema,\n 'DELETE',\n `${base}/links/${encodeURIComponent(id)}`,\n );\n return ctx.succeed(\n { host: run.host, ...removed },\n ctx.ui.result({\n title: `Removed link ${removed.removed} from ${removed.agent.slug}`,\n }),\n );\n }\n default:\n throw usageError(\n `Unknown teams links subcommand \"${run.verb}\".`,\n usageFor('links'),\n );\n }\n}\n\n/**\n * `triggers rotate <team> <key> <trigger-key|id>`: a webhook trigger's new\n * bearer token, the old one revoked — shown once, as `add` shows it. A\n * template's webhook trigger starts with no token, so this is also how its\n * team gets one. Replacing a live token cuts off whoever sends with it, so\n * that needs `--yes`, as `teams webhook` does.\n */\nasync function rotateSecret(\n ctx: CliContext,\n run: TeamAgentRun,\n team: string,\n key: string,\n): Promise<ExitCode> {\n const ref = run.operands[2]?.trim();\n if (!ref) {\n throw usageError(\n 'Name the webhook trigger, by its key or id.',\n `List them: ekanos teams triggers list ${team} ${key}`,\n );\n }\n noExtra(run.operands, 3, 'triggers');\n\n const base = agentPath(team, key);\n const list = await send(\n run,\n TeamAgentTriggerListSchema,\n 'GET',\n `${base}/triggers`,\n );\n const trigger =\n list.triggers.find((entry) => entry.id === ref) ??\n list.triggers.find((entry) => entry.key === ref.toLowerCase());\n if (!trigger) {\n throw usageError(\n `${list.agent.slug} on ${list.team.slug} has no trigger \"${ref}\".`,\n `List them: ekanos teams triggers list ${team} ${key}`,\n );\n }\n if (trigger.type !== 'webhook') {\n throw usageError(\n `\"${ref}\" is a ${trigger.type} trigger; only a webhook trigger has a token to rotate.`,\n `List them: ekanos teams triggers list ${team} ${key}`,\n );\n }\n if (trigger.secretSet !== false && !run.args.yes) {\n throw invalidStateError(\n `${trigger.key ?? trigger.id} on ${list.team.slug} already has a token. A new one revokes it, and whatever sends to the URL with the old token is refused until it uses the new one.`,\n `Re-run with --yes when you are ready to update the sender: ekanos teams triggers rotate ${team} ${key} ${ref} --yes`,\n );\n }\n\n const secrets = ensureSecretsDir(run.args.env);\n const rotated = await send(\n run,\n TeamAgentTriggerAddResultSchema,\n 'POST',\n `${base}/triggers/${encodeURIComponent(trigger.id)}`,\n { rotate: true },\n );\n const { webhook, ...rest } = rotated;\n const saved = webhook\n ? saveTriggerToken(run, secrets, {\n team: rotated.team.slug,\n agent: rotated.agent.slug,\n trigger: rotated.trigger.key ?? rotated.trigger.id,\n webhook,\n again: `ekanos teams triggers rotate ${team} ${key} ${ref} --yes`,\n })\n : null;\n return ctx.succeed(\n { host: run.host, ...rest, webhook: saved?.json ?? null },\n ctx.ui.result({\n title: `New token for ${rotated.trigger.key ?? rotated.trigger.id} on ${rotated.team.slug}`,\n tone: 'warn',\n rows: saved?.rows ?? [],\n notes: [\n ...(saved?.notes ?? []),\n ...(trigger.secretSet === false\n ? []\n : ['The previous token is revoked.']),\n ],\n }),\n );\n}\n\n/**\n * A webhook trigger's bearer token goes to a 0600 file, never to the output\n * (a terminal, or an agent's context). The URL is not a secret — the trigger\n * id — so it is still printed. JSON carries `{ url, secretFile }`.\n */\nfunction saveTriggerToken(\n run: TeamAgentRun,\n dir: string | null,\n input: {\n team: string;\n agent: string;\n trigger: string;\n webhook: { url: string; token: string };\n again: string;\n },\n) {\n const file = writeSecretFile(dir ?? ensureSecretsDir(run.args.env), {\n owner: input.team,\n what: `${input.agent}-${input.trigger}-trigger-token`,\n purpose: `Bearer token for the webhook trigger ${input.trigger} of agent ${input.agent} on team ${input.team} (source ${run.source}). Send it as \"Authorization: Bearer <token>\" when you POST JSON to ${input.webhook.url}.`,\n values: [\n ['URL', input.webhook.url],\n ['BEARER_TOKEN', input.webhook.token],\n ],\n again: input.again,\n });\n return {\n json: { url: input.webhook.url, secretFile: file },\n rows: [\n ['URL', input.webhook.url],\n ['Bearer token', `saved to ${file} (readable only by you)`],\n ] as Array<[string, string]>,\n notes: [\n 'The token is shown nowhere else and cannot be read again. Copy it from that file into the sender yourself — not into a chat or an agent session — then delete the file. POST JSON to the URL with \"Authorization: Bearer <token>\".',\n ],\n };\n}\n\nfunction triggerBody(\n run: TeamAgentRun,\n team: string,\n key: string,\n): TeamAgentTriggerAddRequest {\n const type = run.operands[2]?.trim().toLowerCase();\n const prompt = flag(run, 'prompt') ?? '';\n switch (type) {\n case 'manual':\n noExtra(run.operands, 3, 'triggers');\n return { type: 'manual', promptTemplate: prompt };\n case 'schedule': {\n noExtra(run.operands, 3, 'triggers');\n const cron = flag(run, 'cron');\n if (!cron || !prompt) {\n throw usageError(\n 'A schedule needs --cron and --prompt.',\n `e.g. ekanos teams triggers add ${team} ${key} schedule --cron \"0 9 * * 1-5\" --timezone America/Los_Angeles --prompt \"Summarize yesterday's tickets\"`,\n );\n }\n return {\n type: 'schedule',\n scheduleCron: cron,\n timezone: flag(run, 'timezone') ?? 'UTC',\n promptTemplate: prompt,\n };\n }\n case 'webhook':\n noExtra(run.operands, 3, 'triggers');\n if (!prompt) {\n throw usageError(\n 'A webhook needs --prompt: what to do with each request.',\n `e.g. ekanos teams triggers add ${team} ${key} webhook --prompt \"Triage this alert: {{body.title}}\"`,\n );\n }\n return { type: 'webhook', promptTemplate: prompt };\n case 'event':\n case 'integration_event': {\n const eventId = run.operands[3]?.trim();\n if (!eventId) {\n throw usageError(\n 'Name the event, e.g. zendesk.ticket_created.',\n `e.g. ekanos teams triggers add ${team} ${key} event zendesk.ticket_created --filter '{\"priority\":[\"urgent\"]}'`,\n );\n }\n noExtra(run.operands, 4, 'triggers');\n return {\n type: 'integration_event',\n eventId,\n filter: parseFilters(filterFlag(run)),\n promptTemplate: prompt,\n };\n }\n case 'slack': {\n noExtra(run.operands, 3, 'triggers');\n const channels = listFlag(run, 'channel');\n const directMessages = run.args.flags?.dms === true;\n if (channels.length === 0 && !directMessages) {\n throw usageError(\n 'A slack trigger answers in channels, direct messages, or both.',\n `e.g. ekanos teams triggers add ${team} ${key} slack --channel '#support' --dms --yes (the bot must be in each channel; \"ekanos teams connect ${team} slack\" installs Slack first)`,\n );\n }\n if (!run.args.yes) {\n throw usageError(\n 'Anyone in those channels, and anyone who messages the bot, can then ask the agent to act with everything it is granted.',\n 'Pass --yes to confirm that audience, as the app asks before it adds the trigger.',\n );\n }\n return {\n type: 'slack',\n channels,\n directMessages,\n promptTemplate: prompt,\n confirmAudience: true,\n };\n }\n case 'linear': {\n noExtra(run.operands, 3, 'triggers');\n const labelNames = listFlag(run, 'label');\n const onMention = run.args.flags?.mention !== false;\n if (!onMention && labelNames.length === 0) {\n throw usageError(\n 'A linear trigger answers @mentions, labelled issues, or both.',\n `e.g. ekanos teams triggers add ${team} ${key} linear --label feedback (\"ekanos teams connect ${team} linear-app\" installs the Ekanos Linear app first). The Linear integration's own events are event triggers: \"ekanos catalog linear --json\" lists them.`,\n );\n }\n return { type: 'linear', onMention, labelNames, promptTemplate: prompt };\n }\n default:\n throw usageError(\n type ? `Unknown trigger type \"${type}\".` : 'Name the trigger type.',\n usageFor('triggers'),\n );\n }\n}\n\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * A trigger named by key, the name it has in agent.json. Only a template's\n * trigger has one, and it changes at the template, so that is said here\n * with the template-level command rather than left to the host's refusal.\n */\nasync function triggerIdByKey(\n run: TeamAgentRun,\n team: string,\n key: string,\n ref: string,\n): Promise<string> {\n const list = await send(\n run,\n TeamAgentTriggerListSchema,\n 'GET',\n `${agentPath(team, key)}/triggers`,\n );\n const trigger = list.triggers.find(\n (entry) => entry.key === ref.toLowerCase(),\n );\n if (!trigger) {\n throw usageError(\n `${list.agent.slug} on ${list.team.slug} has no trigger \"${ref}\".`,\n `List them: ekanos teams triggers list ${team} ${key}`,\n );\n }\n if (trigger.owner === 'template') {\n throw invalidStateError(\n `Trigger ${ref} comes from the template, so it can only change there.`,\n `Remove it from the template for every team: ekanos agents triggers ${key} remove ${ref}, then publish.`,\n );\n }\n return trigger.id;\n}\n\n/**\n * A link named by the key of the agent it goes to, as the template level\n * names it. Two links to one agent (talk and delegate) need `--kind`.\n */\nasync function linkIdByTarget(\n run: TeamAgentRun,\n team: string,\n from: string,\n to: string,\n): Promise<string> {\n const list = await send(\n run,\n TeamAgentLinkListSchema,\n 'GET',\n `${agentPath(team, from)}/links`,\n );\n const kind = flag(run, 'kind');\n const matches = list.links.filter(\n (link) =>\n link.to.slug === to.toLowerCase() && (!kind || link.kind === kind),\n );\n if (matches.length === 0) {\n throw usageError(\n `${list.agent.slug} on ${list.team.slug} has no link to \"${to}\"${kind ? ` of kind ${kind}` : ''}.`,\n `List them: ekanos teams links list ${team} ${from}`,\n );\n }\n if (matches.length > 1) {\n throw usageError(\n `${list.agent.slug} has more than one link to ${to}.`,\n `Name which with --kind talk|delegate: ekanos teams links remove ${team} ${from} ${to} --kind delegate`,\n );\n }\n return matches[0]!.id;\n}\n\n/** `--filter`, repeatable: `field=value` or a JSON object, as at the template level. */\nfunction filterFlag(run: TeamAgentRun): readonly string[] {\n const value = run.args.flags?.filter;\n if (Array.isArray(value)) return value;\n return typeof value === 'string' ? [value] : [];\n}\n\nfunction describeTrigger(trigger: TeamAgentTrigger): string {\n const what =\n trigger.type === 'schedule'\n ? `schedule ${trigger.scheduleCron ?? ''} (${trigger.timezone ?? 'UTC'})`\n : trigger.type === 'integration_event'\n ? `event ${trigger.eventId ?? ''}${trigger.filter && Object.keys(trigger.filter).length > 0 ? ` ${JSON.stringify(trigger.filter)}` : ''}`\n : trigger.type;\n const tags = [\n trigger.owner === 'template'\n ? `from template${trigger.key ? ` (key ${trigger.key})` : ''}`\n : 'team',\n trigger.active ? 'on' : 'off',\n ...(trigger.secretSet === false ? ['no token yet'] : []),\n ];\n return `${what} · ${tags.join(' · ')}`;\n}\n\nfunction describeLink(link: TeamAgentLink): string {\n const kind =\n link.kind === 'delegate' ? `delegate (${link.mode ?? 'await'})` : 'talk';\n const tags = [\n link.owner === 'template' ? 'from template' : 'team',\n ...(link.active ? [] : ['inactive']),\n ];\n return `${kind} → ${link.to.slug} · ${tags.join(' · ')}`;\n}\n\nfunction agentPath(team: string, key: string): string {\n return `/api/partner/teams/${encodeURIComponent(team)}/agents/${encodeURIComponent(key)}`;\n}\n\nfunction flag(run: TeamAgentRun, name: string): string | undefined {\n const value = run.args.flags?.[name];\n return typeof value === 'string' && value.trim() ? value.trim() : undefined;\n}\n\n/** A repeatable flag's values; each may also be comma-separated. */\nfunction listFlag(run: TeamAgentRun, name: string): string[] {\n const value = run.args.flags?.[name];\n const values = Array.isArray(value)\n ? value\n : typeof value === 'string'\n ? [value]\n : [];\n return values\n .flatMap((entry) => entry.split(','))\n .map((entry) => entry.trim())\n .filter(Boolean);\n}\n\nfunction noExtra(\n operands: readonly string[],\n count: number,\n area: 'triggers' | 'links',\n) {\n const extra = operands[count];\n if (extra !== undefined) {\n throw usageError(`Unexpected argument \"${extra}\".`, usageFor(area));\n }\n}\n\nfunction send<T>(\n run: TeamAgentRun,\n schema: z.ZodType<T>,\n method: 'GET' | 'POST' | 'DELETE',\n path: string,\n body?: unknown,\n): Promise<T> {\n return run.client.call((token) =>\n call(run.host, token, schema, { method, path, source: run.source, body }),\n );\n}\n"]}
@@ -8,7 +8,9 @@ import { TeamsClient, type TeamsArgs } from './teams.js';
8
8
  * through the same checks the app's agent pages make and leaves an Admin
9
9
  * Audit row naming the person.
10
10
  *
11
- * The shape is always `teams <area> <verb> <team> [<agent-key> …]`.
11
+ * The shape is always `teams <area> <verb> <team> [<agent-key> …]`; the
12
+ * team may also be named with `--team <slug>`, as `runs`, `approvals`,
13
+ * `skills` and `knowledge` name it.
12
14
  */
13
15
  export declare const TEAM_AGENT_AREAS: readonly ['agents', 'triggers', 'links', 'mcp'];
14
16
  export type TeamAgentArea = (typeof TEAM_AGENT_AREAS)[number];
@@ -12,24 +12,28 @@ import { TeamsClient } from './teams.js';
12
12
  * through the same checks the app's agent pages make and leaves an Admin
13
13
  * Audit row naming the person.
14
14
  *
15
- * The shape is always `teams <area> <verb> <team> [<agent-key> …]`.
15
+ * The shape is always `teams <area> <verb> <team> [<agent-key> …]`; the
16
+ * team may also be named with `--team <slug>`, as `runs`, `approvals`,
17
+ * `skills` and `knowledge` name it.
16
18
  */
17
19
  export const TEAM_AGENT_AREAS = ['agents', 'triggers', 'links', 'mcp'];
18
20
  export function isTeamAgentArea(value) {
19
21
  return TEAM_AGENT_AREAS.some((area) => area === value);
20
22
  }
21
23
  export async function runTeamAgentCommands(ctx, args) {
22
- const [area, verb, ...operands] = args.positionals;
24
+ var _a;
25
+ const [area, verb, ...positional] = args.positionals;
23
26
  if (!isTeamAgentArea(area)) {
24
27
  throw usageError(`Unknown teams area "${area !== null && area !== void 0 ? area : ''}".`, 'See "ekanos teams --help".');
25
28
  }
26
29
  if (!verb) {
27
30
  throw usageError(`teams ${area} needs a subcommand.`, usageFor(area));
28
31
  }
32
+ const operands = withTeamFlag(positional, (_a = args.flags) === null || _a === void 0 ? void 0 : _a.team);
29
33
  const env = resolveAuthEnvironment(ctx, args.host, args.env, {
30
34
  projectDir: args.dir,
31
35
  });
32
- const resolved = await resolveSourceTarget(env, requireSession(env.store, env.host), args);
36
+ const resolved = await resolveSourceTarget(env, requireSession(env), args);
33
37
  const run = {
34
38
  args,
35
39
  client: new TeamsClient(env, resolved.session),
@@ -52,15 +56,31 @@ export async function runTeamAgentCommands(ctx, args) {
52
56
  export function usageFor(area) {
53
57
  switch (area) {
54
58
  case 'agents':
55
- return 'Run one of: ekanos teams agents list <team> | enable <team> <key> [--as <member-email>] | disable <team> <key> | pin <team> <key> <version> | unpin <team> <key> | policy <team> <key> [set <tool> auto|approve | unset <tool> | --reads auto|approve --writes auto|approve].';
59
+ return 'Run one of: ekanos teams agents list <team> | show <team> <key> | enable <team> <key> [--as <member-email>] [--draft] [--confirm-access] | confirm <team> <key> | disable <team> <key> --yes | pin <team> <key> <version> | pin <team> <key> --draft | unpin <team> <key> | policy <team> <key> [set <tool> auto|approve | unset <tool> | --reads auto|approve --writes auto|approve] [--confirm-access] | skills <team> <key> [add|remove <skill>].';
56
60
  case 'triggers':
57
- return 'Run one of: ekanos teams triggers list <team> <key> | add <team> <key> <manual|schedule|webhook|event> … | remove <team> <key> <trigger-id>.';
61
+ return 'Run one of: ekanos teams triggers list <team> <key> | add <team> <key> <manual|schedule|webhook|event|slack|linear> … | remove <team> <key> <trigger-id|key> --yes | rotate <team> <key> <trigger-key|id> [--yes].';
58
62
  case 'links':
59
- return 'Run one of: ekanos teams links list <team> <key> | add <team> <from-key> <to-key> --kind talk|delegate [--mode await|handoff] | remove <team> <from-key> <link-id>.';
63
+ return 'Run one of: ekanos teams links list <team> <key> | add <team> <from-key> <to-key> --kind talk|delegate [--mode await|handoff] | remove <team> <from-key> <link-id|to-key> [--kind talk|delegate] --yes. The team may be --team <slug> instead.';
60
64
  case 'mcp':
61
- return 'Run one of: ekanos teams mcp list <team> | add <team> <server-key> --url <url> [--auth none|token|oauth] [--name <name>] | status <team> <server-key> | token <team> <server-key> (hidden input at your terminal) | effect <team> <server-key> <tool> read|write.';
65
+ return 'Run one of: ekanos teams mcp list <team> | add <team> <server-key> --url <url> [--auth none|token|oauth] [--name <name>] | status <team> <server-key> | token <team> <server-key> (hidden input at your terminal) | effect <team> <server-key> <tool> read|write | remove <team> <server-key> --yes.';
62
66
  }
63
67
  }
68
+ /**
69
+ * `--team <slug>` in place of the leading team operand. Given both, they
70
+ * must agree; given only the flag, it becomes the first operand.
71
+ */
72
+ function withTeamFlag(operands, flag) {
73
+ var _a;
74
+ if (flag === undefined)
75
+ return operands;
76
+ const team = typeof flag === 'string' ? flag.trim().toLowerCase() : '';
77
+ if (!team) {
78
+ throw usageError('--team needs a team slug.', 'e.g. --team bank-a');
79
+ }
80
+ return ((_a = operands[0]) === null || _a === void 0 ? void 0 : _a.trim().toLowerCase()) === team
81
+ ? operands
82
+ : [team, ...operands];
83
+ }
64
84
  /** A slug operand (team, agent key, server key), or a usage error naming it. */
65
85
  export function requireOperand(value, what, area) {
66
86
  const slug = value === null || value === void 0 ? void 0 : value.trim().toLowerCase();