@ekanos/cli 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,12 +9,7 @@ export interface ReadinessStep {
9
9
  export interface AgentReadiness {
10
10
  live: boolean;
11
11
  steps: ReadinessStep[];
12
- /**
13
- * An update waiting for the runs-as person's confirmation; the agent runs
14
- * its current version meanwhile. Null when none.
15
- */
16
- pending: ReadinessStep | null;
17
- /** The first step's fix, else the pending update's; null when neither. */
12
+ /** The first step's fix; null when there is none. */
18
13
  next: string | null;
19
14
  }
20
15
  export interface ReadinessTarget {
@@ -23,7 +18,8 @@ export interface ReadinessTarget {
23
18
  }
24
19
  export declare function agentReadiness(entry: TeamAgentEntry, target: ReadinessTarget): AgentReadiness;
25
20
  /**
26
- * What a waiting version adds over the one running, in words:
21
+ * What a newer version adds over the one a team runs, in words (a publish's
22
+ * report of the teams pinned to another version):
27
23
  * "adds zendesk_update_ticket; lets zendesk_add_tag run without approval".
28
24
  */
29
25
  export declare function describeHold(hold: TeamAgentHold): string;
@@ -36,14 +32,8 @@ export declare function channelFix(channel: ChannelRequirement, team: string, so
36
32
  export declare function reachedVia(channel: ChannelRequirement): string;
37
33
  /** A fix as a line: a command is run in the terminal, an app step is not. */
38
34
  export declare function fixLine(fix: string): string;
39
- /**
40
- * "Live: yes" or "Live: no — N steps left", and an update waiting for
41
- * confirmation: "Live: yes (on v4; v5 waiting for confirmation)".
42
- */
43
- export declare function liveLine(readiness: AgentReadiness, agent?: {
44
- version: number | null;
45
- held?: TeamAgentHold | null;
46
- } | null): string;
35
+ /** "Live: yes" or "Live: no — N steps left". */
36
+ export declare function liveLine(readiness: AgentReadiness): string;
47
37
  /** What happened lately, read alongside the agent; each part optional. */
48
38
  export interface AgentActivity {
49
39
  /** The agent's recent runs, newest first. */
@@ -5,43 +5,26 @@ import { scopeFix, scopeHiddenWords } from './scope-notice.js';
5
5
  * from what the host already reports (CLI audit 2026-10-19, §3).
6
6
  *
7
7
  * Live is: on, on a published version, every connection it needs made,
8
- * access confirmed by the person it runs as, at least one trigger on, and
9
- * every trigger's events able to reach it. Each gap is a step with one fix,
10
- * in the order they have to be done; the first step's fix is "Next".
11
- *
12
- * An agent HELD on an earlier version (a newer one reaches further than the
13
- * person it runs as confirmed) is still live — it runs the version it is on
14
- * — so the hold is not a step: it is `pending`, said beside "Live", and its
15
- * confirm command is "Next" once nothing else is.
8
+ * access confirmed by someone who sets it up (a team manager or the Source
9
+ * admin, plan 247.2), at least one trigger on, and every trigger's events
10
+ * able to reach it. Each gap is a step with one fix, in the order they have
11
+ * to be done; the first step's fix is "Next". A publish holds no team, so
12
+ * there is no update waiting.
16
13
  */
17
14
  const CLI = 'npx @ekanos/cli';
18
15
  export function agentReadiness(entry, target) {
19
16
  var _a;
20
- var _b, _c;
17
+ var _b;
21
18
  const steps = readinessSteps(entry, target);
22
- const pending = pendingUpdate(entry, target);
23
19
  return {
24
20
  live: steps.length === 0,
25
21
  steps,
26
- pending,
27
- next: (_c = (_b = (_a = steps[0]) === null || _a === void 0 ? void 0 : _a.fix) !== null && _b !== void 0 ? _b : pending === null || pending === void 0 ? void 0 : pending.fix) !== null && _c !== void 0 ? _c : null,
28
- };
29
- }
30
- /** The update a held agent waits for, and who confirms it. */
31
- function pendingUpdate(entry, { team, source }) {
32
- var _a, _b;
33
- const agent = entry.agent;
34
- if (!(agent === null || agent === void 0 ? void 0 : agent.held))
35
- return null;
36
- const who = (_a = agent.runsAs) !== null && _a !== void 0 ? _a : 'the person it runs as';
37
- return {
38
- problem: `held on v${(_b = agent.version) !== null && _b !== void 0 ? _b : '?'}: v${agent.held.waiting} ${describeHold(agent.held)}, and waits for ${who} to confirm`,
39
- // Only that person can confirm, signed in as themselves.
40
- fix: `${who} runs: ${CLI} teams agents confirm ${team} ${entry.key} --source ${source} (or confirms in the app: Agents › ${entry.name} › Setup)`,
22
+ next: (_b = (_a = steps[0]) === null || _a === void 0 ? void 0 : _a.fix) !== null && _b !== void 0 ? _b : null,
41
23
  };
42
24
  }
43
25
  /**
44
- * What a waiting version adds over the one running, in words:
26
+ * What a newer version adds over the one a team runs, in words (a publish's
27
+ * report of the teams pinned to another version):
45
28
  * "adds zendesk_update_ticket; lets zendesk_add_tag run without approval".
46
29
  */
47
30
  export function describeHold(hold) {
@@ -68,7 +51,7 @@ export function describeHold(hold) {
68
51
  return parts.length > 0 ? parts.join('; ') : 'reaches further';
69
52
  }
70
53
  function readinessSteps(entry, { team, source }) {
71
- var _a, _b, _c, _d, _e, _f;
54
+ var _a, _b, _c, _d, _e;
72
55
  const enable = `${CLI} teams agents enable ${team} ${entry.key} --source ${source}`;
73
56
  const agent = entry.agent;
74
57
  if (!agent)
@@ -97,11 +80,11 @@ function readinessSteps(entry, { team, source }) {
97
80
  });
98
81
  }
99
82
  if (!agent.accessConfirmed) {
100
- const who = (_d = agent.runsAs) !== null && _d !== void 0 ? _d : 'the person it runs as';
101
83
  steps.push({
102
- problem: `${who} has not confirmed it may use their connections`,
103
- // Only that person can confirm, signed in as themselves.
104
- fix: `${who} runs: ${CLI} teams agents confirm ${team} ${entry.key} --source ${source} (or confirms in the app: Agents › ${entry.name} › Setup)`,
84
+ problem: 'nobody has confirmed what it may use',
85
+ // Whoever sets it up confirms, as themselves: the Source admin here,
86
+ // or a team manager in the app (plan 247.2).
87
+ fix: `${CLI} teams agents confirm ${team} ${entry.key} --source ${source} (or a team manager confirms in the app: Agents › ${entry.name} › Setup)`,
105
88
  });
106
89
  }
107
90
  if (!agent.triggers.some((trigger) => trigger.enabled)) {
@@ -110,11 +93,11 @@ function readinessSteps(entry, { team, source }) {
110
93
  fix: `${CLI} teams triggers add ${team} ${entry.key} event <event-id> --source ${source} (event ids: ${CLI} catalog --source ${source})`,
111
94
  });
112
95
  }
113
- for (const channel of (_e = agent.channels) !== null && _e !== void 0 ? _e : []) {
96
+ for (const channel of (_d = agent.channels) !== null && _d !== void 0 ? _d : []) {
114
97
  if (channel.ready)
115
98
  continue;
116
99
  steps.push({
117
- problem: (_f = channel.problem) !== null && _f !== void 0 ? _f : `${channel.name} not ready`,
100
+ problem: (_e = channel.problem) !== null && _e !== void 0 ? _e : `${channel.name} not ready`,
118
101
  fix: channelFix(channel, team, source),
119
102
  });
120
103
  }
@@ -182,19 +165,12 @@ export function reachedVia(channel) {
182
165
  export function fixLine(fix) {
183
166
  return fix.startsWith(CLI) ? `in your terminal: ${fix}` : fix;
184
167
  }
185
- /**
186
- * "Live: yes" or "Live: no — N steps left", and an update waiting for
187
- * confirmation: "Live: yes (on v4; v5 waiting for confirmation)".
188
- */
189
- export function liveLine(readiness, agent) {
190
- var _a;
168
+ /** "Live: yes" or "Live: no — N steps left". */
169
+ export function liveLine(readiness) {
191
170
  const left = readiness.steps.length;
192
- const held = (agent === null || agent === void 0 ? void 0 : agent.held)
193
- ? ` (on v${(_a = agent.version) !== null && _a !== void 0 ? _a : '?'}; v${agent.held.waiting} waiting for confirmation)`
194
- : '';
195
171
  return readiness.live
196
- ? `Live: yes${held}`
197
- : `Live: no — ${left} step${left === 1 ? '' : 's'} left${held}`;
172
+ ? 'Live: yes'
173
+ : `Live: no — ${left} step${left === 1 ? '' : 's'} left`;
198
174
  }
199
175
  /**
200
176
  * One line per product, per trigger, then Live and Next. A product the
@@ -202,7 +178,7 @@ export function liveLine(readiness, agent) {
202
178
  * the team cannot see it there (`scope`, the team's scopes).
203
179
  */
204
180
  export function describeAgentReadiness(entry, target, readiness, activity, scope) {
205
- var _a, _b, _c, _d, _e;
181
+ var _a, _b, _c, _d;
206
182
  const agent = entry.agent;
207
183
  if (!agent) {
208
184
  return [
@@ -215,11 +191,9 @@ export function describeAgentReadiness(entry, target, readiness, activity, scope
215
191
  `${entry.key} on ${target.team}`,
216
192
  agent.draft
217
193
  ? `draft v${(_b = agent.version) !== null && _b !== void 0 ? _b : '?'} (testing, unpublished)`
218
- : agent.held
219
- ? `held on v${(_c = agent.version) !== null && _c !== void 0 ? _c : '?'}, v${agent.held.waiting} waiting for confirmation`
220
- : `v${(_d = agent.version) !== null && _d !== void 0 ? _d : '?'} (${agent.pinned ? 'pinned' : 'following'})`,
194
+ : `v${(_c = agent.version) !== null && _c !== void 0 ? _c : '?'} (${agent.pinned ? 'pinned' : 'following'})`,
221
195
  ...(agent.status === 'active' ? [] : [agent.status]),
222
- `runs as ${(_e = agent.runsAs) !== null && _e !== void 0 ? _e : 'nobody'}`,
196
+ `runs as ${(_d = agent.runsAs) !== null && _d !== void 0 ? _d : 'nobody'}`,
223
197
  agent.accessConfirmed ? '✓ access confirmed' : '✗ access not confirmed',
224
198
  ].join(' · ');
225
199
  const width = Math.max(8, ...agent.requirements.map((item) => item.key.length));
@@ -292,18 +266,11 @@ export function describeAgentReadiness(entry, target, readiness, activity, scope
292
266
  : []),
293
267
  ];
294
268
  });
295
- const update = readiness.pending
296
- ? [
297
- ` ${pad('update')} ${readiness.pending.problem}`,
298
- `${indent}→ ${readiness.pending.fix}`,
299
- ]
300
- : [];
301
269
  return [
302
270
  head,
303
271
  ...products,
304
272
  ...(agent.triggers.length > 0 ? triggers : [` ${pad('triggers')} none`]),
305
- ...update,
306
- ` ${liveLine(readiness, agent)}`,
273
+ ` ${liveLine(readiness)}`,
307
274
  ...(readiness.next ? [` Next: ${readiness.next}`] : []),
308
275
  ].join('\n');
309
276
  }
@@ -1 +1 @@
1
- {"version":3,"file":"team-agent-readiness.js","sourceRoot":"","sources":["../../src/commands/team-agent-readiness.ts"],"names":[],"mappings":"AASA,OAAO,EAAmB,QAAQ,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAE7E;;;;;;;;;;;;;;GAcG;AAEH,MAAM,GAAG,GAAG,iBAAiB,CAAC;AA0B9B,MAAM,UAAU,cAAc,CAC5B,KAAqB,EACrB,MAAuB;;;IAEvB,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC7C,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC;QACxB,KAAK;QACL,OAAO;QACP,IAAI,cAAE,MAAA,KAAK,CAAC,CAAC,CAAC,0CAAE,GAAG,mCAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,GAAG,mCAAI,IAAI;KAC5C,CAAC;AACJ,CAAC;AAED,8DAA8D;AAC9D,SAAS,aAAa,CACpB,KAAqB,EACrB,EAAE,IAAI,EAAE,MAAM,EAAmB;;IAEjC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1B,IAAI,EAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,CAAA;QAAE,OAAO,IAAI,CAAC;IAC9B,MAAM,GAAG,SAAG,KAAK,CAAC,MAAM,mCAAI,uBAAuB,CAAC;IACpD,OAAO;QACL,OAAO,EAAE,YAAY,MAAA,KAAK,CAAC,OAAO,mCAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,GAAG,aAAa;QAChI,yDAAyD;QACzD,GAAG,EAAE,GAAG,GAAG,UAAU,GAAG,yBAAyB,IAAI,IAAI,KAAK,CAAC,GAAG,aAAa,MAAM,uCAAuC,KAAK,CAAC,IAAI,WAAW;KAClJ,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAmB;IAC9C,MAAM,IAAI,GAAG;QACX,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK;YAC3B,CAAC,CAAC,CAAC,yCAAyC,CAAC;YAC7C,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,WAAW;gBAC/B,CAAC,CAAC,CAAC,yCAAyC,CAAC;gBAC7C,CAAC,CAAC,EAAE,CAAC;QACT,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,eAAe,CAAC;QACtE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK;KACnB,CAAC;IACF,MAAM,OAAO,GAAG;QACd,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1C,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK;KACtB,CAAC;IACF,MAAM,KAAK,GAAG;QACZ,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YACpB,CAAC,CAAC,CAAC,QAAQ,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC;YACrD,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IACF,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC;AACjE,CAAC;AAED,SAAS,cAAc,CACrB,KAAqB,EACrB,EAAE,IAAI,EAAE,MAAM,EAAmB;;IAEjC,MAAM,MAAM,GAAG,GAAG,GAAG,wBAAwB,IAAI,IAAI,KAAK,CAAC,GAAG,aAAa,MAAM,EAAE,CAAC;IACpF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1B,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,EAAE,OAAO,EAAE,WAAW,IAAI,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IACjE,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,QAAQ,IAAI,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,KAAK,GAAoB,EAAE,CAAC;IAClC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,4DAA4D;QAC5D,KAAK,CAAC,IAAI,CAAC;YACT,OAAO,EAAE,8BAA8B,MAAA,KAAK,CAAC,OAAO,mCAAI,GAAG,gCAAgC;YAC3F,GAAG,EAAE,GAAG,GAAG,mBAAmB,KAAK,CAAC,GAAG,aAAa,MAAM,EAAE;SAC7D,CAAC,CAAC;IACL,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC;YACT,OAAO,EAAE,sBAAsB;YAC/B,GAAG,EAAE,GAAG,GAAG,mBAAmB,KAAK,CAAC,GAAG,aAAa,MAAM,EAAE;SAC7D,CAAC,CAAC;IACL,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC;YACT,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,YAAY,OAAC,IAAI,CAAC,MAAM,mCAAI,eAAe,CAAC,EAAE;YACxE,GAAG,QACD,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,mCAClC,GAAG,GAAG,qBAAqB,IAAI,IAAI,IAAI,CAAC,GAAG,aAAa,MAAM,EAAE;SACnE,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;QAC3B,MAAM,GAAG,SAAG,KAAK,CAAC,MAAM,mCAAI,uBAAuB,CAAC;QACpD,KAAK,CAAC,IAAI,CAAC;YACT,OAAO,EAAE,GAAG,GAAG,iDAAiD;YAChE,yDAAyD;YACzD,GAAG,EAAE,GAAG,GAAG,UAAU,GAAG,yBAAyB,IAAI,IAAI,KAAK,CAAC,GAAG,aAAa,MAAM,uCAAuC,KAAK,CAAC,IAAI,WAAW;SAClJ,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACvD,KAAK,CAAC,IAAI,CAAC;YACT,OAAO,EAAE,wDAAwD;YACjE,GAAG,EAAE,GAAG,GAAG,uBAAuB,IAAI,IAAI,KAAK,CAAC,GAAG,8BAA8B,MAAM,iBAAiB,GAAG,qBAAqB,MAAM,GAAG;SAC1I,CAAC,CAAC;IACL,CAAC;IACD,KAAK,MAAM,OAAO,UAAI,KAAK,CAAC,QAAQ,mCAAI,EAAE,EAAE,CAAC;QAC3C,IAAI,OAAO,CAAC,KAAK;YAAE,SAAS;QAC5B,KAAK,CAAC,IAAI,CAAC;YACT,OAAO,QAAE,OAAO,CAAC,OAAO,mCAAI,GAAG,OAAO,CAAC,IAAI,YAAY;YACvD,GAAG,EAAE,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC;SACvC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAGrB;IACF,aAAa,EAAE,eAAe;IAC9B,QAAQ,EAAE,2DAA2D;IACrE,kBAAkB,EAAE,wDAAwD;IAC5E,mBAAmB,EAAE,2CAA2C;IAChE,oBAAoB,EAAE,mCAAmC;CAC1D,CAAC;AAEF,uEAAuE;AACvE,MAAM,UAAU,cAAc,CAC5B,IAAiB,EACjB,IAAY,EACZ,MAAc;IAEd,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACrC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,UAAU;YACb,OAAO,GAAG,GAAG,eAAe,IAAI,CAAC,GAAG,YAAY,IAAI,aAAa,MAAM,cAAc,GAAG,mBAAmB,IAAI,CAAC,GAAG,aAAa,MAAM,GAAG,CAAC;QAC5I,KAAK,sBAAsB;YACzB,OAAO,GAAG,GAAG,iBAAiB,IAAI,CAAC,GAAG,aAAa,MAAM,EAAE,CAAC;QAC9D,KAAK,qBAAqB;YACxB,OAAO,4CAA4C,GAAG,8BAA8B,MAAM,GAAG,CAAC;QAChG,KAAK,oBAAoB;YACvB,OAAO,mBAAmB,IAAI,CAAC,GAAG,wCAAwC,GAAG,eAAe,CAAC;QAC/F;YACE,IAAI,IAAI,CAAC,SAAS;gBAAE,OAAO,IAAI,CAAC;YAChC,mEAAmE;YACnE,6DAA6D;YAC7D,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,SAAS;gBAC5C,CAAC,CAAC,GAAG,GAAG,kBAAkB,IAAI,IAAI,IAAI,CAAC,GAAG,SAAS,IAAI,CAAC,SAAS,aAAa,MAAM,EAAE;gBACtF,CAAC,CAAC,GAAG,GAAG,kBAAkB,IAAI,IAAI,IAAI,CAAC,GAAG,aAAa,MAAM,EAAE,CAAC;IACtE,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,UAAU,CACxB,OAA2B,EAC3B,IAAY,EACZ,MAAc;IAEd,QAAQ,OAAO,CAAC,OAAO,EAAE,CAAC;QACxB,KAAK,cAAc;YACjB,OAAO,GAAG,GAAG,kBAAkB,IAAI,IAAI,OAAO,CAAC,OAAO,aAAa,MAAM,EAAE,CAAC;QAC9E,KAAK,cAAc;YACjB,OAAO,OAAO,CAAC,OAAO;gBACpB,CAAC,CAAC,GAAG,GAAG,eAAe,OAAO,CAAC,OAAO,YAAY,IAAI,aAAa,MAAM,cAAc,GAAG,mBAAmB,OAAO,CAAC,OAAO,aAAa,MAAM,GAAG;gBAClJ,CAAC,CAAC,GAAG,GAAG,mBAAmB,OAAO,CAAC,OAAO,aAAa,MAAM,EAAE,CAAC;QACpE;YACE,OAAO,OAAO,CAAC,YAAY;gBACzB,CAAC,CAAC,GAAG,GAAG,kBAAkB,IAAI,IAAI,OAAO,CAAC,OAAO,iBAAiB,OAAO,CAAC,YAAY,aAAa,MAAM,EAAE;gBAC3G,CAAC,CAAC,OAAO,CAAC,GAAG,KAAK,OAAO,IAAI,OAAO,CAAC,GAAG,KAAK,YAAY;oBACvD,CAAC,CAAC,GAAG,GAAG,kBAAkB,IAAI,IAAI,OAAO,CAAC,GAAG,aAAa,MAAM,EAAE;oBAClE,CAAC,CAAC,mDAAmD,CAAC;IAC9D,CAAC;AACH,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,UAAU,CAAC,OAA2B;IACpD,QAAQ,OAAO,CAAC,OAAO,EAAE,CAAC;QACxB,KAAK,cAAc;YACjB,OAAO,cAAc,CAAC;QACxB,KAAK,cAAc;YACjB,OAAO,wBAAwB,CAAC;QAClC;YACE,OAAO,GAAG,OAAO,CAAC,IAAI,YAAY,CAAC;IACvC,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,OAAO,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACtB,SAAyB,EACzB,KAAsE;;IAEtE,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC;IACpC,MAAM,IAAI,GAAG,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI;QACtB,CAAC,CAAC,SAAS,MAAA,KAAK,CAAC,OAAO,mCAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,4BAA4B;QACnF,CAAC,CAAC,EAAE,CAAC;IACP,OAAO,SAAS,CAAC,IAAI;QACnB,CAAC,CAAC,YAAY,IAAI,EAAE;QACpB,CAAC,CAAC,cAAc,IAAI,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,EAAE,CAAC;AACpE,CAAC;AAcD;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAAqB,EACrB,MAAuB,EACvB,SAAyB,EACzB,QAAuB,EACvB,KAAkB;;IAElB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,GAAG,KAAK,CAAC,GAAG,OAAO,MAAM,CAAC,IAAI,aAAa,MAAA,KAAK,CAAC,gBAAgB,mCAAI,GAAG,YAAY;YACpF,KAAK,QAAQ,CAAC,SAAS,CAAC,EAAE;YAC1B,WAAW,SAAS,CAAC,IAAI,EAAE;SAC5B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IAED,MAAM,IAAI,GAAG;QACX,GAAG,KAAK,CAAC,GAAG,OAAO,MAAM,CAAC,IAAI,EAAE;QAChC,KAAK,CAAC,KAAK;YACT,CAAC,CAAC,UAAU,MAAA,KAAK,CAAC,OAAO,mCAAI,GAAG,yBAAyB;YACzD,CAAC,CAAC,KAAK,CAAC,IAAI;gBACV,CAAC,CAAC,YAAY,MAAA,KAAK,CAAC,OAAO,mCAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,2BAA2B;gBACrF,CAAC,CAAC,IAAI,MAAA,KAAK,CAAC,OAAO,mCAAI,GAAG,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,GAAG;QAC3E,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACpD,WAAW,MAAA,KAAK,CAAC,MAAM,mCAAI,QAAQ,EAAE;QACrC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,wBAAwB;KACxE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEd,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,CAAC,EACD,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CACrD,CAAC;IACF,MAAM,GAAG,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAErC,MAAM,QAAQ,GAAG,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;;QACnD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS;YACxB,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,OAAC,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,mCACjD,GAAG,GAAG,qBAAqB,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,aAAa,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACpF,MAAM,MAAM,GACV,IAAI,CAAC,aAAa,IAAI,KAAK;YACzB,CAAC,CAAC;gBACE,GAAG,MAAM,KAAK,gBAAgB,CAAC,KAAK,CAAC,EAAE;gBACvC,GAAG,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,KAAK,kCAAO,MAAM,KAAE,OAAO,EAAE,IAAI,CAAC,GAAG,IAAG,CAAC,EAAE;aAC3E;YACH,CAAC,CAAC,EAAE,CAAC;QACT,OAAO;YACL,KAAK,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,YAAY,CAAC,IAAI,CAAC,EAAE;YAC3C,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9C,GAAG,MAAM;SACV,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CACxB,CAAC,EACD,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CACnB,CAAC,OAAO,EAAE,EAAE,kBAAC,OAAC,OAAO,CAAC,OAAO,mCAAI,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,GAAA,CACtD,CACF,CAAC;IACF,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;;;QACzD,MAAM,KAAK,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,OAAC,OAAO,CAAC,OAAO,mCAAI,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,OAAO,CAAC,KAAK,KAAK,KAAK,IAAI,QAAQ,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,OAAC,KAAK,CAAC,QAAQ,mCAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,kBACxD,SAAS,CAAC,QAAQ,CAAC,QAAQ,OAAC,OAAO,CAAC,OAAO,mCAAI,OAAO,CAAC,IAAI,CAAC,GAAA,CAC7D,CAAC;QACF,MAAM,KAAK,GAAG,OAAO;YACnB,CAAC,CAAC,OAAO,CAAC,KAAK;gBACb,CAAC,CAAC,gBAAgB,UAAU,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,mBAAmB,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG;gBACpH,CAAC,CAAC,KAAK,MAAA,OAAO,CAAC,OAAO,mCAAI,GAAG,OAAO,CAAC,IAAI,YAAY,EAAE;YACzD,CAAC,CAAC,KAAK,MAAA,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,mCAAI,WAAW,EAAE,CAAC;QACtD,mEAAmE;QACnE,gEAAgE;QAChE,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO;YAC/B,CAAC,CAAC,OAAC,QAAQ,CAAC,MAAM,mCAAI,EAAE,CAAC,CAAC,MAAM,CAC5B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAC7C;YACH,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO;YAC7B,CAAC,CAAC,MAAA,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,0CAAE,IAAI,CAAC,CAAC,CAAC;YAC3D,CAAC,CAAC,MAAA,QAAQ,CAAC,IAAI,0CAAE,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/D,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAChE,MAAM,KAAK,GAAG;YACZ,KAAK;YACL,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC,MAAM;gBACpC,CAAC,CAAC;oBACE,SAAS;wBACP,CAAC,CAAC,cAAc,SAAS,CAAC,UAAU,IAAI,SAAS,CAAC,MAAM,EAAE;wBAC1D,CAAC,CAAC,cAAc;iBACnB;gBACH,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,KAAK;gBACP,CAAC,CAAC;oBACE,OAAO;wBACL,CAAC,CAAC,YAAY,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE;wBACnD,CAAC,CAAC,YAAY;iBACjB;gBACH,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;QACF,OAAO;YACL,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YAC3C,GAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK;gBAC3B,CAAC,CAAC;oBACE,GAAG,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE;iBACzE;gBACH,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO;QAC9B,CAAC,CAAC;YACE,KAAK,GAAG,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE;YAClD,GAAG,MAAM,KAAK,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE;SACtC;QACH,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;QACL,IAAI;QACJ,GAAG,QAAQ;QACX,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC1E,GAAG,MAAM;QACT,KAAK,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE;QACjC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KACzD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,aAAa,GAA2B;IAC5C,MAAM,EAAE,iBAAiB;IACzB,QAAQ,EAAE,sBAAsB;IAChC,OAAO,EAAE,8BAA8B;CACxC,CAAC;AAEF,SAAS,YAAY,CAAC,IAAiB;;IACrC,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,SAAS;YACnB,CAAC,CAAC,wBAAwB;YAC1B,CAAC,CAAC,4BAA4B,CAAC;IACnC,CAAC;IACD,MAAM,GAAG,GACP,IAAI,CAAC,GAAG,KAAK,QAAQ;QACnB,CAAC,CAAC,uBAAuB;QACzB,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ;YACrB,CAAC,CAAC,OAAO,MAAA,IAAI,CAAC,SAAS,mCAAI,oBAAoB,wBAAwB;YACvE,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,MAAM;gBACnB,CAAC,CAAC,qBAAqB;gBACvB,CAAC,CAAC,IAAI,CAAC;IACf,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,MAAM,MAAM,GACV,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,SAAS;YACrC,CAAC,CAAC,cAAc,IAAI,CAAC,SAAS,EAAE;YAChC,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,QAAQ,GACZ,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,eAAe;YAC5C,CAAC,CAAC,KAAK,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG;YACnC,CAAC,CAAC,EAAE,CAAC;QACT,OAAO,KAAK,GAAG,aAAH,GAAG,cAAH,GAAG,GAAI,WAAW,GAAG,MAAM,GAAG,QAAQ,EAAE,CAAC;IACvD,CAAC;IACD,MAAM,MAAM,GAAG,YAAY,OAAC,IAAI,CAAC,MAAM,mCAAI,eAAe,CAAC,CAAC;IAC5D,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;AACrF,CAAC","sourcesContent":["import type {\n AgentRunSummary,\n ChannelRequirement,\n Requirement,\n TeamAgentEntry,\n TeamAgentHold,\n TeamIntegrationEvent,\n} from '@ekanos/integration-schema';\n\nimport { type ScopeFacts, scopeFix, scopeHiddenWords } from './scope-notice';\n\n/**\n * \"Is this agent live on this team, and if not, why?\" — one answer for\n * `teams agents show` and the summary line of `teams agents list`, built only\n * from what the host already reports (CLI audit 2026-10-19, §3).\n *\n * Live is: on, on a published version, every connection it needs made,\n * access confirmed by the person it runs as, at least one trigger on, and\n * every trigger's events able to reach it. Each gap is a step with one fix,\n * in the order they have to be done; the first step's fix is \"Next\".\n *\n * An agent HELD on an earlier version (a newer one reaches further than the\n * person it runs as confirmed) is still live — it runs the version it is on\n * — so the hold is not a step: it is `pending`, said beside \"Live\", and its\n * confirm command is \"Next\" once nothing else is.\n */\n\nconst CLI = 'npx @ekanos/cli';\n\nexport interface ReadinessStep {\n /** What is missing, in words. */\n problem: string;\n /** The one command (or app step) that fixes it. */\n fix: string;\n}\n\nexport interface AgentReadiness {\n live: boolean;\n steps: ReadinessStep[];\n /**\n * An update waiting for the runs-as person's confirmation; the agent runs\n * its current version meanwhile. Null when none.\n */\n pending: ReadinessStep | null;\n /** The first step's fix, else the pending update's; null when neither. */\n next: string | null;\n}\n\nexport interface ReadinessTarget {\n team: string;\n source: string;\n}\n\nexport function agentReadiness(\n entry: TeamAgentEntry,\n target: ReadinessTarget,\n): AgentReadiness {\n const steps = readinessSteps(entry, target);\n const pending = pendingUpdate(entry, target);\n return {\n live: steps.length === 0,\n steps,\n pending,\n next: steps[0]?.fix ?? pending?.fix ?? null,\n };\n}\n\n/** The update a held agent waits for, and who confirms it. */\nfunction pendingUpdate(\n entry: TeamAgentEntry,\n { team, source }: ReadinessTarget,\n): ReadinessStep | null {\n const agent = entry.agent;\n if (!agent?.held) return null;\n const who = agent.runsAs ?? 'the person it runs as';\n return {\n problem: `held on v${agent.version ?? '?'}: v${agent.held.waiting} ${describeHold(agent.held)}, and waits for ${who} to confirm`,\n // Only that person can confirm, signed in as themselves.\n fix: `${who} runs: ${CLI} teams agents confirm ${team} ${entry.key} --source ${source} (or confirms in the app: Agents › ${entry.name} › Setup)`,\n };\n}\n\n/**\n * What a waiting version adds over the one running, in words:\n * \"adds zendesk_update_ticket; lets zendesk_add_tag run without approval\".\n */\nexport function describeHold(hold: TeamAgentHold): string {\n const adds = [\n ...(hold.adds.scope === 'all'\n ? ['every tool of the products it can reach']\n : hold.adds.scope === 'read_only'\n ? ['every read of the products it can reach']\n : []),\n ...hold.adds.products.map((product) => `${product.name} (every tool)`),\n ...hold.adds.tools,\n ];\n const loosens = [\n ...(hold.loosens.writes ? ['writes'] : []),\n ...(hold.loosens.reads ? ['reads'] : []),\n ...hold.loosens.tools,\n ];\n const parts = [\n ...(adds.length > 0 ? [`adds ${adds.join(', ')}`] : []),\n ...(loosens.length > 0\n ? [`lets ${loosens.join(', ')} run without approval`]\n : []),\n ];\n return parts.length > 0 ? parts.join('; ') : 'reaches further';\n}\n\nfunction readinessSteps(\n entry: TeamAgentEntry,\n { team, source }: ReadinessTarget,\n): ReadinessStep[] {\n const enable = `${CLI} teams agents enable ${team} ${entry.key} --source ${source}`;\n const agent = entry.agent;\n if (!agent) return [{ problem: `off for ${team}`, fix: enable }];\n if (agent.status !== 'active') {\n return [{ problem: `${agent.status} for ${team}`, fix: enable }];\n }\n\n const steps: ReadinessStep[] = [];\n if (agent.draft) {\n // A team testing a draft runs it only when started by hand.\n steps.push({\n problem: `testing unpublished draft v${agent.version ?? '?'}: its triggers do not start it`,\n fix: `${CLI} agents publish ${entry.key} --source ${source}`,\n });\n } else if (agent.version === null) {\n steps.push({\n problem: 'no published version',\n fix: `${CLI} agents publish ${entry.key} --source ${source}`,\n });\n }\n for (const item of agent.missing) {\n steps.push({\n problem: `${item.name}: ${REASON_WORDS[item.reason ?? 'not_connected']}`,\n fix:\n requirementFix(item, team, source) ??\n `${CLI} teams mcp status ${team} ${item.key} --source ${source}`,\n });\n }\n if (!agent.accessConfirmed) {\n const who = agent.runsAs ?? 'the person it runs as';\n steps.push({\n problem: `${who} has not confirmed it may use their connections`,\n // Only that person can confirm, signed in as themselves.\n fix: `${who} runs: ${CLI} teams agents confirm ${team} ${entry.key} --source ${source} (or confirms in the app: Agents › ${entry.name} › Setup)`,\n });\n }\n if (!agent.triggers.some((trigger) => trigger.enabled)) {\n steps.push({\n problem: 'no trigger is on, so it only runs when started by hand',\n fix: `${CLI} teams triggers add ${team} ${entry.key} event <event-id> --source ${source} (event ids: ${CLI} catalog --source ${source})`,\n });\n }\n for (const channel of agent.channels ?? []) {\n if (channel.ready) continue;\n steps.push({\n problem: channel.problem ?? `${channel.name} not ready`,\n fix: channelFix(channel, team, source),\n });\n }\n return steps;\n}\n\nexport const REASON_WORDS: Record<\n NonNullable<Requirement['reason']>,\n string\n> = {\n not_connected: 'not connected',\n no_route: 'no route maps the Source connection’s events to this team',\n source_unsupported: 'the integration no longer supports a Source connection',\n source_not_entitled: 'the product is not enabled for the Source',\n source_not_connected: 'the Source connection is not made',\n};\n\n/** The one command that makes a requirement, or null when none can. */\nexport function requirementFix(\n item: Requirement,\n team: string,\n source: string,\n): string | null {\n if (item.kind === 'mcp') return null;\n switch (item.reason) {\n case 'no_route':\n return `${CLI} routes set ${item.key} <value> ${team} --source ${source} (values: ${CLI} routes options ${item.key} --source ${source})`;\n case 'source_not_connected':\n return `${CLI} apps connect ${item.key} --source ${source}`;\n case 'source_not_entitled':\n return `a super-admin enables it for the Source (${CLI} sources products --source ${source})`;\n case 'source_unsupported':\n return `set connections.${item.key}.owner to \"team\" in agent.json, then ${CLI} agents apply`;\n default:\n if (item.connected) return null;\n // A per-person product is the runs-as person's connection, not the\n // caller's: connecting your own leaves the agent missing it.\n return item.via === 'person' && item.viaDetail\n ? `${CLI} teams connect ${team} ${item.key} --as ${item.viaDetail} --source ${source}`\n : `${CLI} teams connect ${team} ${item.key} --source ${source}`;\n }\n}\n\n/** The one command that makes a channel ready, or the app step. */\nexport function channelFix(\n channel: ChannelRequirement,\n team: string,\n source: string,\n): string {\n switch (channel.arrival) {\n case 'team-webhook':\n return `${CLI} teams webhook ${team} ${channel.product} --source ${source}`;\n case 'source-route':\n return channel.webhook\n ? `${CLI} routes set ${channel.product} <value> ${team} --source ${source} (values: ${CLI} routes options ${channel.product} --source ${source})`\n : `${CLI} routes webhook ${channel.product} --source ${source}`;\n default:\n return channel.connectionId\n ? `${CLI} teams connect ${team} ${channel.product} --connection ${channel.connectionId} --source ${source}`\n : channel.key === 'slack' || channel.key === 'linear-app'\n ? `${CLI} teams connect ${team} ${channel.key} --source ${source}`\n : `install it on the agent's Triggers tab in the app`;\n }\n}\n\n/** How the events of a ready channel reach the agent. */\nexport function reachedVia(channel: ChannelRequirement): string {\n switch (channel.arrival) {\n case 'team-webhook':\n return 'team webhook';\n case 'source-route':\n return 'Source webhook, routed';\n default:\n return `${channel.name} installed`;\n }\n}\n\n/** A fix as a line: a command is run in the terminal, an app step is not. */\nexport function fixLine(fix: string): string {\n return fix.startsWith(CLI) ? `in your terminal: ${fix}` : fix;\n}\n\n/**\n * \"Live: yes\" or \"Live: no — N steps left\", and an update waiting for\n * confirmation: \"Live: yes (on v4; v5 waiting for confirmation)\".\n */\nexport function liveLine(\n readiness: AgentReadiness,\n agent?: { version: number | null; held?: TeamAgentHold | null } | null,\n): string {\n const left = readiness.steps.length;\n const held = agent?.held\n ? ` (on v${agent.version ?? '?'}; v${agent.held.waiting} waiting for confirmation)`\n : '';\n return readiness.live\n ? `Live: yes${held}`\n : `Live: no — ${left} step${left === 1 ? '' : 's'} left${held}`;\n}\n\n/* ---------------------------------------------------------------------- */\n/* teams agents show */\n/* ---------------------------------------------------------------------- */\n\n/** What happened lately, read alongside the agent; each part optional. */\nexport interface AgentActivity {\n /** The agent's recent runs, newest first. */\n runs: AgentRunSummary[] | null;\n /** The team's recent integration events, newest first. */\n events: TeamIntegrationEvent[] | null;\n}\n\n/**\n * One line per product, per trigger, then Live and Next. A product the\n * team's product scopes hide from it in the app says so — connected or not,\n * the team cannot see it there (`scope`, the team's scopes).\n */\nexport function describeAgentReadiness(\n entry: TeamAgentEntry,\n target: ReadinessTarget,\n readiness: AgentReadiness,\n activity: AgentActivity,\n scope?: ScopeFacts,\n): string {\n const agent = entry.agent;\n if (!agent) {\n return [\n `${entry.key} on ${target.team} · off · v${entry.publishedVersion ?? '?'} published`,\n ` ${liveLine(readiness)}`,\n ` Next: ${readiness.next}`,\n ].join('\\n');\n }\n\n const head = [\n `${entry.key} on ${target.team}`,\n agent.draft\n ? `draft v${agent.version ?? '?'} (testing, unpublished)`\n : agent.held\n ? `held on v${agent.version ?? '?'}, v${agent.held.waiting} waiting for confirmation`\n : `v${agent.version ?? '?'} (${agent.pinned ? 'pinned' : 'following'})`,\n ...(agent.status === 'active' ? [] : [agent.status]),\n `runs as ${agent.runsAs ?? 'nobody'}`,\n agent.accessConfirmed ? '✓ access confirmed' : '✗ access not confirmed',\n ].join(' · ');\n\n const width = Math.max(\n 8,\n ...agent.requirements.map((item) => item.key.length),\n );\n const pad = (label: string) => label.padEnd(width);\n const indent = ' '.repeat(width + 4);\n\n const products = agent.requirements.flatMap((item) => {\n const fix = item.connected\n ? null\n : (requirementFix(item, target.team, target.source) ??\n `${CLI} teams mcp status ${target.team} ${item.key} --source ${target.source}`);\n const hidden =\n item.hiddenByScope && scope\n ? [\n `${indent}! ${scopeHiddenWords(scope)}`,\n `${indent}→ ${fixLine(scopeFix(scope, { ...target, product: item.key }))}`,\n ]\n : [];\n return [\n ` ${pad(item.key)} ${productState(item)}`,\n ...(fix ? [`${indent}→ ${fixLine(fix)}`] : []),\n ...hidden,\n ];\n });\n\n const nameWidth = Math.max(\n 0,\n ...agent.triggers.map(\n (trigger) => (trigger.eventId ?? trigger.type).length,\n ),\n );\n const triggers = agent.triggers.flatMap((trigger, index) => {\n const label = index === 0 ? pad('triggers') : pad('');\n const name = (trigger.eventId ?? trigger.type).padEnd(nameWidth);\n if (!trigger.enabled) return [` ${label} ${name} (off)`];\n const channel = (agent.channels ?? []).find((candidate) =>\n candidate.triggers.includes(trigger.eventId ?? trigger.type),\n );\n const reach = channel\n ? channel.ready\n ? `✓ reachable (${reachedVia(channel)}${channel.lastDeliveryAt ? `, last delivery ${channel.lastDeliveryAt}` : ''})`\n : `✗ ${channel.problem ?? `${channel.name} not ready`}`\n : `✓ ${TRIGGER_REACH[trigger.type] ?? 'reachable'}`;\n // An event trigger's runs are the ones its own events started; any\n // other trigger's, the agent's latest run of that trigger type.\n const ownEvents = trigger.eventId\n ? (activity.events ?? []).filter(\n (event) => event.eventId === trigger.eventId,\n )\n : [];\n const lastEvent = ownEvents[0];\n const lastRun = trigger.eventId\n ? ownEvents.find((event) => event.runs.length > 0)?.runs[0]\n : activity.runs?.find((run) => run.trigger === trigger.type);\n const known = trigger.eventId ? activity.events : activity.runs;\n const facts = [\n reach,\n ...(trigger.eventId && activity.events\n ? [\n lastEvent\n ? `last event ${lastEvent.receivedAt} ${lastEvent.status}`\n : 'no event yet',\n ]\n : []),\n ...(known\n ? [\n lastRun\n ? `last run ${lastRun.startedAt} ${lastRun.status}`\n : 'no run yet',\n ]\n : []),\n ];\n return [\n ` ${label} ${name} ${facts.join(' · ')}`,\n ...(channel && !channel.ready\n ? [\n `${indent}→ ${fixLine(channelFix(channel, target.team, target.source))}`,\n ]\n : []),\n ];\n });\n\n const update = readiness.pending\n ? [\n ` ${pad('update')} ${readiness.pending.problem}`,\n `${indent}→ ${readiness.pending.fix}`,\n ]\n : [];\n\n return [\n head,\n ...products,\n ...(agent.triggers.length > 0 ? triggers : [` ${pad('triggers')} none`]),\n ...update,\n ` ${liveLine(readiness, agent)}`,\n ...(readiness.next ? [` Next: ${readiness.next}`] : []),\n ].join('\\n');\n}\n\nconst TRIGGER_REACH: Record<string, string> = {\n manual: 'started by hand',\n schedule: 'runs on its schedule',\n webhook: 'reachable at its trigger URL',\n};\n\nfunction productState(item: Requirement): string {\n if (item.kind === 'mcp') {\n return item.connected\n ? '✓ MCP server connected'\n : '✗ MCP server not signed in';\n }\n const via =\n item.via === 'source'\n ? 'via Source connection'\n : item.via === 'person'\n ? `via ${item.viaDetail ?? 'the runs-as person'}'s personal connection`\n : item.via === 'team'\n ? 'via team connection'\n : null;\n if (item.connected) {\n const routes =\n item.via === 'source' && item.viaDetail\n ? ` · routes: ${item.viaDetail}`\n : '';\n const fallback =\n item.reason && item.reason !== 'not_connected'\n ? ` (${REASON_WORDS[item.reason]})`\n : '';\n return `✓ ${via ?? 'connected'}${routes}${fallback}`;\n }\n const reason = REASON_WORDS[item.reason ?? 'not_connected'];\n return `✗ ${via ? `${via} — ` : ''}${reason}${item.required ? '' : ' (optional)'}`;\n}\n"]}
1
+ {"version":3,"file":"team-agent-readiness.js","sourceRoot":"","sources":["../../src/commands/team-agent-readiness.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AgentRunSummary,\n ChannelRequirement,\n Requirement,\n TeamAgentEntry,\n TeamAgentHold,\n TeamIntegrationEvent,\n} from '@ekanos/integration-schema';\n\nimport { type ScopeFacts, scopeFix, scopeHiddenWords } from './scope-notice';\n\n/**\n * \"Is this agent live on this team, and if not, why?\" — one answer for\n * `teams agents show` and the summary line of `teams agents list`, built only\n * from what the host already reports (CLI audit 2026-10-19, §3).\n *\n * Live is: on, on a published version, every connection it needs made,\n * access confirmed by someone who sets it up (a team manager or the Source\n * admin, plan 247.2), at least one trigger on, and every trigger's events\n * able to reach it. Each gap is a step with one fix, in the order they have\n * to be done; the first step's fix is \"Next\". A publish holds no team, so\n * there is no update waiting.\n */\n\nconst CLI = 'npx @ekanos/cli';\n\nexport interface ReadinessStep {\n /** What is missing, in words. */\n problem: string;\n /** The one command (or app step) that fixes it. */\n fix: string;\n}\n\nexport interface AgentReadiness {\n live: boolean;\n steps: ReadinessStep[];\n /** The first step's fix; null when there is none. */\n next: string | null;\n}\n\nexport interface ReadinessTarget {\n team: string;\n source: string;\n}\n\nexport function agentReadiness(\n entry: TeamAgentEntry,\n target: ReadinessTarget,\n): AgentReadiness {\n const steps = readinessSteps(entry, target);\n return {\n live: steps.length === 0,\n steps,\n next: steps[0]?.fix ?? null,\n };\n}\n\n/**\n * What a newer version adds over the one a team runs, in words (a publish's\n * report of the teams pinned to another version):\n * \"adds zendesk_update_ticket; lets zendesk_add_tag run without approval\".\n */\nexport function describeHold(hold: TeamAgentHold): string {\n const adds = [\n ...(hold.adds.scope === 'all'\n ? ['every tool of the products it can reach']\n : hold.adds.scope === 'read_only'\n ? ['every read of the products it can reach']\n : []),\n ...hold.adds.products.map((product) => `${product.name} (every tool)`),\n ...hold.adds.tools,\n ];\n const loosens = [\n ...(hold.loosens.writes ? ['writes'] : []),\n ...(hold.loosens.reads ? ['reads'] : []),\n ...hold.loosens.tools,\n ];\n const parts = [\n ...(adds.length > 0 ? [`adds ${adds.join(', ')}`] : []),\n ...(loosens.length > 0\n ? [`lets ${loosens.join(', ')} run without approval`]\n : []),\n ];\n return parts.length > 0 ? parts.join('; ') : 'reaches further';\n}\n\nfunction readinessSteps(\n entry: TeamAgentEntry,\n { team, source }: ReadinessTarget,\n): ReadinessStep[] {\n const enable = `${CLI} teams agents enable ${team} ${entry.key} --source ${source}`;\n const agent = entry.agent;\n if (!agent) return [{ problem: `off for ${team}`, fix: enable }];\n if (agent.status !== 'active') {\n return [{ problem: `${agent.status} for ${team}`, fix: enable }];\n }\n\n const steps: ReadinessStep[] = [];\n if (agent.draft) {\n // A team testing a draft runs it only when started by hand.\n steps.push({\n problem: `testing unpublished draft v${agent.version ?? '?'}: its triggers do not start it`,\n fix: `${CLI} agents publish ${entry.key} --source ${source}`,\n });\n } else if (agent.version === null) {\n steps.push({\n problem: 'no published version',\n fix: `${CLI} agents publish ${entry.key} --source ${source}`,\n });\n }\n for (const item of agent.missing) {\n steps.push({\n problem: `${item.name}: ${REASON_WORDS[item.reason ?? 'not_connected']}`,\n fix:\n requirementFix(item, team, source) ??\n `${CLI} teams mcp status ${team} ${item.key} --source ${source}`,\n });\n }\n if (!agent.accessConfirmed) {\n steps.push({\n problem: 'nobody has confirmed what it may use',\n // Whoever sets it up confirms, as themselves: the Source admin here,\n // or a team manager in the app (plan 247.2).\n fix: `${CLI} teams agents confirm ${team} ${entry.key} --source ${source} (or a team manager confirms in the app: Agents › ${entry.name} › Setup)`,\n });\n }\n if (!agent.triggers.some((trigger) => trigger.enabled)) {\n steps.push({\n problem: 'no trigger is on, so it only runs when started by hand',\n fix: `${CLI} teams triggers add ${team} ${entry.key} event <event-id> --source ${source} (event ids: ${CLI} catalog --source ${source})`,\n });\n }\n for (const channel of agent.channels ?? []) {\n if (channel.ready) continue;\n steps.push({\n problem: channel.problem ?? `${channel.name} not ready`,\n fix: channelFix(channel, team, source),\n });\n }\n return steps;\n}\n\nexport const REASON_WORDS: Record<\n NonNullable<Requirement['reason']>,\n string\n> = {\n not_connected: 'not connected',\n no_route: 'no route maps the Source connection’s events to this team',\n source_unsupported: 'the integration no longer supports a Source connection',\n source_not_entitled: 'the product is not enabled for the Source',\n source_not_connected: 'the Source connection is not made',\n};\n\n/** The one command that makes a requirement, or null when none can. */\nexport function requirementFix(\n item: Requirement,\n team: string,\n source: string,\n): string | null {\n if (item.kind === 'mcp') return null;\n switch (item.reason) {\n case 'no_route':\n return `${CLI} routes set ${item.key} <value> ${team} --source ${source} (values: ${CLI} routes options ${item.key} --source ${source})`;\n case 'source_not_connected':\n return `${CLI} apps connect ${item.key} --source ${source}`;\n case 'source_not_entitled':\n return `a super-admin enables it for the Source (${CLI} sources products --source ${source})`;\n case 'source_unsupported':\n return `set connections.${item.key}.owner to \"team\" in agent.json, then ${CLI} agents apply`;\n default:\n if (item.connected) return null;\n // A per-person product is the runs-as person's connection, not the\n // caller's: connecting your own leaves the agent missing it.\n return item.via === 'person' && item.viaDetail\n ? `${CLI} teams connect ${team} ${item.key} --as ${item.viaDetail} --source ${source}`\n : `${CLI} teams connect ${team} ${item.key} --source ${source}`;\n }\n}\n\n/** The one command that makes a channel ready, or the app step. */\nexport function channelFix(\n channel: ChannelRequirement,\n team: string,\n source: string,\n): string {\n switch (channel.arrival) {\n case 'team-webhook':\n return `${CLI} teams webhook ${team} ${channel.product} --source ${source}`;\n case 'source-route':\n return channel.webhook\n ? `${CLI} routes set ${channel.product} <value> ${team} --source ${source} (values: ${CLI} routes options ${channel.product} --source ${source})`\n : `${CLI} routes webhook ${channel.product} --source ${source}`;\n default:\n return channel.connectionId\n ? `${CLI} teams connect ${team} ${channel.product} --connection ${channel.connectionId} --source ${source}`\n : channel.key === 'slack' || channel.key === 'linear-app'\n ? `${CLI} teams connect ${team} ${channel.key} --source ${source}`\n : `install it on the agent's Triggers tab in the app`;\n }\n}\n\n/** How the events of a ready channel reach the agent. */\nexport function reachedVia(channel: ChannelRequirement): string {\n switch (channel.arrival) {\n case 'team-webhook':\n return 'team webhook';\n case 'source-route':\n return 'Source webhook, routed';\n default:\n return `${channel.name} installed`;\n }\n}\n\n/** A fix as a line: a command is run in the terminal, an app step is not. */\nexport function fixLine(fix: string): string {\n return fix.startsWith(CLI) ? `in your terminal: ${fix}` : fix;\n}\n\n/** \"Live: yes\" or \"Live: no — N steps left\". */\nexport function liveLine(readiness: AgentReadiness): string {\n const left = readiness.steps.length;\n return readiness.live\n ? 'Live: yes'\n : `Live: no — ${left} step${left === 1 ? '' : 's'} left`;\n}\n\n/* ---------------------------------------------------------------------- */\n/* teams agents show */\n/* ---------------------------------------------------------------------- */\n\n/** What happened lately, read alongside the agent; each part optional. */\nexport interface AgentActivity {\n /** The agent's recent runs, newest first. */\n runs: AgentRunSummary[] | null;\n /** The team's recent integration events, newest first. */\n events: TeamIntegrationEvent[] | null;\n}\n\n/**\n * One line per product, per trigger, then Live and Next. A product the\n * team's product scopes hide from it in the app says so — connected or not,\n * the team cannot see it there (`scope`, the team's scopes).\n */\nexport function describeAgentReadiness(\n entry: TeamAgentEntry,\n target: ReadinessTarget,\n readiness: AgentReadiness,\n activity: AgentActivity,\n scope?: ScopeFacts,\n): string {\n const agent = entry.agent;\n if (!agent) {\n return [\n `${entry.key} on ${target.team} · off · v${entry.publishedVersion ?? '?'} published`,\n ` ${liveLine(readiness)}`,\n ` Next: ${readiness.next}`,\n ].join('\\n');\n }\n\n const head = [\n `${entry.key} on ${target.team}`,\n agent.draft\n ? `draft v${agent.version ?? '?'} (testing, unpublished)`\n : `v${agent.version ?? '?'} (${agent.pinned ? 'pinned' : 'following'})`,\n ...(agent.status === 'active' ? [] : [agent.status]),\n `runs as ${agent.runsAs ?? 'nobody'}`,\n agent.accessConfirmed ? '✓ access confirmed' : '✗ access not confirmed',\n ].join(' · ');\n\n const width = Math.max(\n 8,\n ...agent.requirements.map((item) => item.key.length),\n );\n const pad = (label: string) => label.padEnd(width);\n const indent = ' '.repeat(width + 4);\n\n const products = agent.requirements.flatMap((item) => {\n const fix = item.connected\n ? null\n : (requirementFix(item, target.team, target.source) ??\n `${CLI} teams mcp status ${target.team} ${item.key} --source ${target.source}`);\n const hidden =\n item.hiddenByScope && scope\n ? [\n `${indent}! ${scopeHiddenWords(scope)}`,\n `${indent}→ ${fixLine(scopeFix(scope, { ...target, product: item.key }))}`,\n ]\n : [];\n return [\n ` ${pad(item.key)} ${productState(item)}`,\n ...(fix ? [`${indent}→ ${fixLine(fix)}`] : []),\n ...hidden,\n ];\n });\n\n const nameWidth = Math.max(\n 0,\n ...agent.triggers.map(\n (trigger) => (trigger.eventId ?? trigger.type).length,\n ),\n );\n const triggers = agent.triggers.flatMap((trigger, index) => {\n const label = index === 0 ? pad('triggers') : pad('');\n const name = (trigger.eventId ?? trigger.type).padEnd(nameWidth);\n if (!trigger.enabled) return [` ${label} ${name} (off)`];\n const channel = (agent.channels ?? []).find((candidate) =>\n candidate.triggers.includes(trigger.eventId ?? trigger.type),\n );\n const reach = channel\n ? channel.ready\n ? `✓ reachable (${reachedVia(channel)}${channel.lastDeliveryAt ? `, last delivery ${channel.lastDeliveryAt}` : ''})`\n : `✗ ${channel.problem ?? `${channel.name} not ready`}`\n : `✓ ${TRIGGER_REACH[trigger.type] ?? 'reachable'}`;\n // An event trigger's runs are the ones its own events started; any\n // other trigger's, the agent's latest run of that trigger type.\n const ownEvents = trigger.eventId\n ? (activity.events ?? []).filter(\n (event) => event.eventId === trigger.eventId,\n )\n : [];\n const lastEvent = ownEvents[0];\n const lastRun = trigger.eventId\n ? ownEvents.find((event) => event.runs.length > 0)?.runs[0]\n : activity.runs?.find((run) => run.trigger === trigger.type);\n const known = trigger.eventId ? activity.events : activity.runs;\n const facts = [\n reach,\n ...(trigger.eventId && activity.events\n ? [\n lastEvent\n ? `last event ${lastEvent.receivedAt} ${lastEvent.status}`\n : 'no event yet',\n ]\n : []),\n ...(known\n ? [\n lastRun\n ? `last run ${lastRun.startedAt} ${lastRun.status}`\n : 'no run yet',\n ]\n : []),\n ];\n return [\n ` ${label} ${name} ${facts.join(' · ')}`,\n ...(channel && !channel.ready\n ? [\n `${indent}→ ${fixLine(channelFix(channel, target.team, target.source))}`,\n ]\n : []),\n ];\n });\n\n return [\n head,\n ...products,\n ...(agent.triggers.length > 0 ? triggers : [` ${pad('triggers')} none`]),\n ` ${liveLine(readiness)}`,\n ...(readiness.next ? [` Next: ${readiness.next}`] : []),\n ].join('\\n');\n}\n\nconst TRIGGER_REACH: Record<string, string> = {\n manual: 'started by hand',\n schedule: 'runs on its schedule',\n webhook: 'reachable at its trigger URL',\n};\n\nfunction productState(item: Requirement): string {\n if (item.kind === 'mcp') {\n return item.connected\n ? '✓ MCP server connected'\n : '✗ MCP server not signed in';\n }\n const via =\n item.via === 'source'\n ? 'via Source connection'\n : item.via === 'person'\n ? `via ${item.viaDetail ?? 'the runs-as person'}'s personal connection`\n : item.via === 'team'\n ? 'via team connection'\n : null;\n if (item.connected) {\n const routes =\n item.via === 'source' && item.viaDetail\n ? ` · routes: ${item.viaDetail}`\n : '';\n const fallback =\n item.reason && item.reason !== 'not_connected'\n ? ` (${REASON_WORDS[item.reason]})`\n : '';\n return `✓ ${via ?? 'connected'}${routes}${fallback}`;\n }\n const reason = REASON_WORDS[item.reason ?? 'not_connected'];\n return `✗ ${via ? `${via} — ` : ''}${reason}${item.required ? '' : ' (optional)'}`;\n}\n"]}
@@ -7,9 +7,9 @@ import { type TeamAgentRun } from './team-agents.js';
7
7
  * a team's provided agents, turned on, versioned, given an approval policy
8
8
  * and skills by the Source admin. `enable|pin … --draft` puts one team on
9
9
  * the template's latest, unpublished version to test it there before
10
- * publishing. `confirm` (and `--confirm-access`) is the one thing only the
11
- * person the agent runs as can do: consent, as themselves, that it may use
12
- * their connections in runs no one watches.
10
+ * publishing. `confirm` (and `--confirm-access`) records the caller's own
11
+ * confirmation that it may use its connections in runs no one watches:
12
+ * whoever sets an agent up confirms it (plan 247.2), never a member.
13
13
  * `show` answers "is this agent live, and if not, why?" for one agent; `list`
14
14
  * ends each agent with the same verdict.
15
15
  */
@@ -1,16 +1,16 @@
1
1
  import { AgentRunListSchema, TeamAgentChangeResultSchema, TeamAgentListSchema, TeamAgentPolicySchema, TeamAgentSkillsSchema, } from '@ekanos/integration-schema';
2
2
  import { invalidStateError, notFoundError, usageError } from '../errors.js';
3
3
  import { call, listTeamEvents } from '../teams-api.js';
4
- import { REASON_WORDS, agentReadiness, channelFix, describeAgentReadiness, describeHold, fixLine, liveLine, reachedVia, requirementFix, } from './team-agent-readiness.js';
4
+ import { REASON_WORDS, agentReadiness, channelFix, describeAgentReadiness, fixLine, liveLine, reachedVia, requirementFix, } from './team-agent-readiness.js';
5
5
  import { requireOperand, usageFor } from './team-agents.js';
6
6
  /**
7
7
  * `ekanos teams agents list|show|enable|confirm|disable|pin|unpin|policy|skills` —
8
8
  * a team's provided agents, turned on, versioned, given an approval policy
9
9
  * and skills by the Source admin. `enable|pin … --draft` puts one team on
10
10
  * the template's latest, unpublished version to test it there before
11
- * publishing. `confirm` (and `--confirm-access`) is the one thing only the
12
- * person the agent runs as can do: consent, as themselves, that it may use
13
- * their connections in runs no one watches.
11
+ * publishing. `confirm` (and `--confirm-access`) records the caller's own
12
+ * confirmation that it may use its connections in runs no one watches:
13
+ * whoever sets an agent up confirms it (plan 247.2), never a member.
14
14
  * `show` answers "is this agent live, and if not, why?" for one agent; `list`
15
15
  * ends each agent with the same verdict.
16
16
  */
@@ -58,7 +58,7 @@ export async function runTeamAgentsArea(ctx, run) {
58
58
  requireDraftHost(result, 'enabled');
59
59
  return ctx.succeed(Object.assign({ host: run.host }, result), describeChange(result, `${draft
60
60
  ? `Testing draft v${(_d = result.version) !== null && _d !== void 0 ? _d : '?'} of ${result.slug} on ${result.team.slug}`
61
- : `Turned on ${result.slug} for ${result.team.slug}`}${confirmAccess && result.accessConfirmed ? ', and you confirmed it may use your connections' : ''}`, run.source, { confirmRequested: confirmAccess }));
61
+ : `Turned on ${result.slug} for ${result.team.slug}`}${confirmAccess && result.accessConfirmed ? ', and you confirmed what it may use' : ''}`, run.source, { confirmRequested: confirmAccess }));
62
62
  }
63
63
  case 'confirm': {
64
64
  expectOperands(run, 2);
@@ -66,9 +66,7 @@ export async function runTeamAgentsArea(ctx, run) {
66
66
  // the host refuses if the version moved (AGENT_VERSION_CHANGED).
67
67
  const shown = await shownVersion(ctx, run, base, key);
68
68
  const result = await change(run, `${path}/confirm`, 'POST', shown === null ? {} : { expectedVersion: shown });
69
- return ctx.succeed(Object.assign({ host: run.host }, result), describeChange(result, result.advanced
70
- ? `You confirmed the update: ${result.slug} on ${result.team.slug} moved from v${result.advanced.from} to v${result.advanced.to}`
71
- : `You confirmed ${result.slug} on ${result.team.slug} may use your connections`, run.source, { confirmRequested: true }));
69
+ return ctx.succeed(Object.assign({ host: run.host }, result), describeChange(result, `You confirmed what ${result.slug} on ${result.team.slug} may use`, run.source, { confirmRequested: true }));
72
70
  }
73
71
  case 'disable': {
74
72
  expectOperands(run, 2);
@@ -254,7 +252,6 @@ function describeSkills(ctx, result, change) {
254
252
  ]))}`;
255
253
  }
256
254
  function describePolicy(ctx, policy, changed, source) {
257
- var _a;
258
255
  // Absent from an older host: say nothing rather than guess.
259
256
  const unconfirmed = policy.accessConfirmed === false;
260
257
  const head = ctx.ui.result({
@@ -271,7 +268,7 @@ function describePolicy(ctx, policy, changed, source) {
271
268
  ...(policy.lockedReason ? [policy.lockedReason] : []),
272
269
  ...(unconfirmed
273
270
  ? [
274
- `Not confirmed: until ${(_a = policy.runsAs) !== null && _a !== void 0 ? _a : 'the person it runs as'} confirms it may use their connections, it uses only what needs no confirmation (a looser policy drops a confirmation). They run: ${confirmCommand(policy.team.slug, policy.key, source)} — or, for the team's own agent, confirm on its page in the app`,
271
+ `Not confirmed: until you or one of the team's agent managers confirms what it may use, it uses only what needs no confirmation (a looser policy drops a confirmation). Confirm it as yourself with --confirm-access on the change, or for a provided agent ${confirmCommand(policy.team.slug, policy.key, source)}; a team manager can also confirm on its page in the app`,
275
272
  ]
276
273
  : []),
277
274
  ],
@@ -287,28 +284,21 @@ function describePolicy(ctx, policy, changed, source) {
287
284
  ]))}`;
288
285
  }
289
286
  /**
290
- * The version `confirm` is about to approve — the one waiting on a held
291
- * agent, else the one it runs — printed before it is sent, so the person
292
- * confirms what they saw. Null when the team's agent has no version to name.
287
+ * The version `confirm` is about to approve — the one it runs — printed
288
+ * before it is sent, so the person confirms what they saw. Null when the
289
+ * team's agent has no version to name.
293
290
  */
294
291
  async function shownVersion(ctx, run, base, key) {
295
292
  var _a;
296
- var _b;
297
293
  const list = await run.client.call((token) => call(run.host, token, TeamAgentListSchema, {
298
294
  method: 'GET',
299
295
  path: base,
300
296
  source: run.source,
301
297
  }));
302
298
  const agent = (_a = list.agents.find((entry) => entry.key === key)) === null || _a === void 0 ? void 0 : _a.agent;
303
- if (!agent)
304
- return null;
305
- if (agent.held) {
306
- ctx.log(`Confirming v${agent.held.waiting} of ${key} on ${list.team.slug}: ${describeHold(agent.held)}. It runs v${(_b = agent.version) !== null && _b !== void 0 ? _b : '?'} until then.`);
307
- return agent.held.waiting;
308
- }
309
- if (agent.version === null)
299
+ if (!agent || agent.version === null)
310
300
  return null;
311
- ctx.log(`Confirming ${key} v${agent.version} on ${list.team.slug} may use your connections.`);
301
+ ctx.log(`Confirming what ${key} v${agent.version} on ${list.team.slug} may use${agent.runsAs ? ` (it runs as ${agent.runsAs})` : ''}.`);
312
302
  return agent.version;
313
303
  }
314
304
  function change(run, path, method, body) {
@@ -320,7 +310,7 @@ function change(run, path, method, body) {
320
310
  }));
321
311
  }
322
312
  function describeEntry(entry, team, source) {
323
- var _a, _b, _c, _d, _e, _f, _g;
313
+ var _a, _b, _c;
324
314
  const readiness = agentReadiness(entry, { team, source });
325
315
  if (!entry.agent) {
326
316
  return `\n${entry.key} — ${entry.name}\n off · v${(_a = entry.publishedVersion) !== null && _a !== void 0 ? _a : '?'} published\n ${liveLine(readiness)} · Next: ${readiness.next}`;
@@ -329,29 +319,22 @@ function describeEntry(entry, team, source) {
329
319
  const version = versionLabel(agent);
330
320
  const lines = [
331
321
  `\n${entry.key} — ${entry.name}`,
332
- ` ${agent.status} · ${version} · runs as ${(_b = agent.runsAs) !== null && _b !== void 0 ? _b : 'nobody'}${agent.accessConfirmed ? '' : ` · access not confirmed (${(_c = agent.runsAs) !== null && _c !== void 0 ? _c : 'they'}: ekanos teams agents confirm ${team} ${entry.key})`}`,
333
- ...(agent.held
334
- ? [
335
- ` ! held on v${(_d = agent.version) !== null && _d !== void 0 ? _d : '?'}: v${agent.held.waiting} ${describeHold(agent.held)}. It keeps running v${(_e = agent.version) !== null && _e !== void 0 ? _e : '?'} until ${(_f = agent.runsAs) !== null && _f !== void 0 ? _f : 'the person it runs as'} confirms: ${confirmCommand(team, entry.key, source)}`,
336
- ]
337
- : []),
322
+ ` ${agent.status} · ${version} · runs as ${(_b = agent.runsAs) !== null && _b !== void 0 ? _b : 'nobody'}${agent.accessConfirmed ? '' : ` · access not confirmed (${confirmCommand(team, entry.key, source)})`}`,
338
323
  ` triggers: ${agent.triggers.length === 0 ? 'none' : agent.triggers.map((trigger) => `${trigger.type}${trigger.enabled ? '' : ' (off)'}`).join(', ')}`,
339
324
  ` links: ${agent.links.length === 0 ? 'none' : agent.links.map((link) => `${link.kind}${link.mode ? `/${link.mode}` : ''} → ${link.to}`).join(', ')}`,
340
325
  ];
341
326
  lines.push(...requirementLines(agent.requirements, agent.missing, team, source));
342
327
  if (agent.draft)
343
328
  lines.push(...draftLines(team, entry.key));
344
- lines.push(...channelLines((_g = agent.channels) !== null && _g !== void 0 ? _g : [], team, source));
345
- lines.push(` ${liveLine(readiness, agent)}${readiness.next ? ` · Next: ${readiness.next}` : ''}`);
329
+ lines.push(...channelLines((_c = agent.channels) !== null && _c !== void 0 ? _c : [], team, source));
330
+ lines.push(` ${liveLine(readiness)}${readiness.next ? ` · Next: ${readiness.next}` : ''}`);
346
331
  return lines.join('\n');
347
332
  }
348
333
  function versionLabel(agent) {
349
- var _a, _b, _c;
334
+ var _a, _b;
350
335
  if (agent.draft)
351
336
  return `draft v${(_a = agent.version) !== null && _a !== void 0 ? _a : '?'} (testing, unpublished)`;
352
- if (agent.held)
353
- return `v${(_b = agent.version) !== null && _b !== void 0 ? _b : '?'} (held, v${agent.held.waiting} waiting for confirmation)`;
354
- return `v${(_c = agent.version) !== null && _c !== void 0 ? _c : '?'} ${agent.pinned ? '(pinned)' : '(following)'}`;
337
+ return `v${(_b = agent.version) !== null && _b !== void 0 ? _b : '?'} ${agent.pinned ? '(pinned)' : '(following)'}`;
355
338
  }
356
339
  /** What testing a draft on a team means, and the next step. */
357
340
  function draftLines(team, key) {
@@ -416,7 +399,7 @@ export function channelLines(channels, team, source) {
416
399
  ]; });
417
400
  }
418
401
  function describeChange(result, title, source, options = {}) {
419
- var _a, _b, _c, _d, _e, _f;
402
+ var _a, _b;
420
403
  const covers = result.access ? describeAccess(result.access) : null;
421
404
  const lines = [
422
405
  `${options.confirmRequested && !result.accessConfirmed ? '!' : '✓'} ${title}`,
@@ -424,12 +407,7 @@ function describeChange(result, title, source, options = {}) {
424
407
  ];
425
408
  if (result.accessConfirmed) {
426
409
  if (covers) {
427
- lines.push(result.advanced
428
- ? ` Now allowed: in runs no one watches it may use ${result.runsAs ? `${result.runsAs}'s` : 'their'} connections to ${covers}.`
429
- : ` Confirmed: in runs no one watches it may use ${result.runsAs ? `${result.runsAs}'s` : 'their'} connections to ${covers}.`);
430
- }
431
- if (result.held) {
432
- lines.push(` Held on v${(_b = result.version) !== null && _b !== void 0 ? _b : '?'}: v${result.held.waiting} ${describeHold(result.held)}. ${(_c = result.runsAs) !== null && _c !== void 0 ? _c : 'The person it runs as'} moves it by confirming: ${confirmCommand(result.team.slug, result.key, source)}`);
410
+ lines.push(` Confirmed: in runs no one watches it may use ${result.runsAs ? `${result.runsAs}'s` : 'their'} connections to ${covers}.`);
433
411
  }
434
412
  }
435
413
  else {
@@ -437,12 +415,12 @@ function describeChange(result, title, source, options = {}) {
437
415
  // An older host ignores confirmAccess rather than refusing it.
438
416
  lines.push(' This host did not record the confirmation: it may not support confirming from the CLI yet.');
439
417
  }
440
- lines.push(` Not confirmed: until ${(_d = result.runsAs) !== null && _d !== void 0 ? _d : 'the person it runs as'} confirms it may use their connections${covers ? ` (to ${covers})` : ''}, it uses only what needs no confirmation.`, ` → ${(_e = result.runsAs) !== null && _e !== void 0 ? _e : 'They'}, as themselves: ${confirmCommand(result.team.slug, result.key, source)}`);
418
+ lines.push(` Not confirmed: until you or one of the team's agent managers confirms what it may use${covers ? ` (${result.runsAs ? `${result.runsAs}'s` : 'its'} connections, to ${covers})` : ''}, it uses only what needs no confirmation.`, ` → ${confirmCommand(result.team.slug, result.key, source)}`);
441
419
  }
442
420
  lines.push(...requirementLines([], result.missing, result.team.slug, source));
443
421
  if (result.draft)
444
422
  lines.push(...draftLines(result.team.slug, result.key));
445
- lines.push(...channelLines((_f = result.channels) !== null && _f !== void 0 ? _f : [], result.team.slug, source));
423
+ lines.push(...channelLines((_b = result.channels) !== null && _b !== void 0 ? _b : [], result.team.slug, source));
446
424
  return lines.join('\n');
447
425
  }
448
426
  /** What a confirmation covers, in words: whose connections, to what. */