@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,4 +1,5 @@
1
1
  import { setProviderApp, showProviderApp, } from '../apps-api.js';
2
+ import { loginHint } from '../auth/host-trust.js';
2
3
  import { refreshStoredSession, requireSession, resolveAuthEnvironment, } from '../auth/session.js';
3
4
  import { deleteConnection, listConnections, showConnection, startConnection, } from '../connections-api.js';
4
5
  import { authRequiredError, invalidStateError, usageError, validationError, } from '../errors.js';
@@ -15,9 +16,9 @@ export const APPS_SUBCOMMANDS = [
15
16
  * `apps` — a Source's provider apps: the OAuth client an integration signs
16
17
  * every team in through (Linear's, say). `show` says whether the Source has
17
18
  * one and which callback URL to register; `set` takes the client id and
18
- * secret from the Source admin at the terminal — never from a flag, a file
19
- * or a non-interactive run, so an agent driving the CLI never handles the
20
- * secret.
19
+ * secret from the Source admin at the terminal — either on its own, Enter
20
+ * keeping the saved one — never from a flag, a file or a non-interactive
21
+ * run, so an agent driving the CLI never handles the secret.
21
22
  */
22
23
  export async function runApps(ctx, args) {
23
24
  var _a, _b, _c;
@@ -34,7 +35,7 @@ export async function runApps(ctx, args) {
34
35
  const env = resolveAuthEnvironment(ctx, args.host, args.env, {
35
36
  projectDir: args.dir,
36
37
  });
37
- const resolved = await resolveSourceTarget(env, requireSession(env.store, env.host), args);
38
+ const resolved = await resolveSourceTarget(env, requireSession(env), args);
38
39
  const client = new AppsClient(env, resolved.session);
39
40
  const source = resolved.source;
40
41
  if (subcommand === 'show') {
@@ -42,29 +43,32 @@ export async function runApps(ctx, args) {
42
43
  }
43
44
  const status = await client.call((token) => showProviderApp(env.host, token, source, product));
44
45
  ctx.log(walkthrough(status).join('\n'));
45
- if (status.configured) {
46
- const replace = await ((_a = args.confirm) !== null && _a !== void 0 ? _a : promptYesNo)(`${status.source.slug} already has ${status.product.name} credentials. Replace them? [y/N]`);
47
- if (!replace) {
48
- throw validationError('Nothing was changed.', `Run "ekanos apps show ${product}" to see the current state.`);
49
- }
50
- }
51
- const clientId = (await ((_b = args.ask) !== null && _b !== void 0 ? _b : promptLine)('Client ID: ')).trim();
52
- const clientSecret = (await ((_c = args.askSecret) !== null && _c !== void 0 ? _c : promptHidden)('Client secret (hidden): ')).trim();
53
- if (!clientId || !clientSecret) {
54
- throw validationError('Both the client ID and the client secret are needed.', `Run "ekanos apps set ${product}" again.`);
46
+ // Either credential on its own: Enter keeps what is saved. An older host
47
+ // sends no `fields`; then `configured` says whether both are saved.
48
+ const saved = (name) => { var _a; var _b; return (_b = (_a = status.fields) === null || _a === void 0 ? void 0 : _a.find((field) => field.name === name)) !== null && _b !== void 0 ? _b : {
49
+ set: status.configured,
50
+ value: null,
51
+ }; };
52
+ const savedId = saved('clientId');
53
+ const savedSecret = saved('clientSecret');
54
+ const clientId = (await ((_a = args.ask) !== null && _a !== void 0 ? _a : promptLine)(savedId.set
55
+ ? `Client ID (current: ${(_b = savedId.value) !== null && _b !== void 0 ? _b : 'saved'} — Enter to keep): `
56
+ : 'Client ID: ')).trim();
57
+ const clientSecret = (await ((_c = args.askSecret) !== null && _c !== void 0 ? _c : promptHidden)(savedSecret.set
58
+ ? 'Client secret (saved — Enter to keep, hidden): '
59
+ : 'Client secret (hidden): ')).trim();
60
+ if (!clientId && !clientSecret) {
61
+ throw validationError('Nothing was changed.', `Run "ekanos apps show ${product}" to see the current state.`);
55
62
  }
56
- const result = await client.call((token) => setProviderApp(env.host, token, {
57
- source,
58
- product,
59
- clientId,
60
- clientSecret,
61
- }));
63
+ const result = await client.call((token) => setProviderApp(env.host, token, Object.assign(Object.assign({ source,
64
+ product }, (clientId ? { clientId } : {})), (clientSecret ? { clientSecret } : {}))));
62
65
  return ctx.succeed(Object.assign({ host: env.host }, result), ctx.ui.result({
63
66
  title: result.replaced
64
- ? `Replaced the ${result.product.name} app`
67
+ ? `Updated the ${result.product.name} app`
65
68
  : `Set up the ${result.product.name} app`,
66
69
  rows: [
67
70
  ['Source', result.source.slug],
71
+ ...providerFieldRows(result),
68
72
  ['Teams can connect', result.configured ? 'yes' : 'not yet'],
69
73
  ['Callback URLs', callbackUrls(result)],
70
74
  ],
@@ -112,8 +116,9 @@ function summary(ctx, status) {
112
116
  ],
113
117
  ]
114
118
  : []),
119
+ ...providerFieldRows(status),
115
120
  [
116
- 'Set up',
121
+ 'App ready',
117
122
  status.configured
118
123
  ? 'yes — teams can connect'
119
124
  : 'no — no team can connect yet',
@@ -209,7 +214,7 @@ async function runConnection(ctx, args, subcommand, product) {
209
214
  }
210
215
  const shown = await client.connection((token) => showConnection(env.host, token, source, product));
211
216
  if (shown.status === 'unsupported') {
212
- throw invalidStateError(shown.message, `Each team connects ${product} itself, from the team's Integrations page.`);
217
+ throw invalidStateError(shown.message, `Each team connects ${product} itself: "ekanos teams connect <team> ${product}".`);
213
218
  }
214
219
  if (shown.status !== 'ok') {
215
220
  throw invalidStateError('The host could not read the connection.', 'Retry shortly.');
@@ -284,7 +289,10 @@ async function askFields(ctx, args, current, product) {
284
289
  }
285
290
  async function disconnect(ctx, args, client, host, source, product) {
286
291
  var _a;
287
- if (canPrompt(ctx, args)) {
292
+ if (!args.yes && !canPrompt(ctx, args)) {
293
+ throw invalidStateError(`Disconnecting ${product} on ${source} stops it for every team's provided agents that use the Source connection, until someone connects it again.`, `Re-run with --yes: ekanos apps disconnect ${product} --source ${source} --yes`);
294
+ }
295
+ if (!args.yes) {
288
296
  const sure = await ((_a = args.confirm) !== null && _a !== void 0 ? _a : promptYesNo)(`Disconnect ${product} for every team's provided agents on ${source}? [y/N]`);
289
297
  if (!sure) {
290
298
  throw validationError('Nothing was changed.', `Run "ekanos apps show ${product}" to see the current state.`);
@@ -292,15 +300,15 @@ async function disconnect(ctx, args, client, host, source, product) {
292
300
  }
293
301
  const result = await client.connection((token) => deleteConnection(host, token, source, product));
294
302
  if (result.status === 'unsupported') {
295
- throw invalidStateError(result.message, `Each team connects ${product} itself, from the team's Integrations page.`);
303
+ throw invalidStateError(result.message, `Each team connects ${product} itself: "ekanos teams connect <team> ${product}".`);
296
304
  }
297
305
  if (result.status !== 'ok') {
298
306
  throw invalidStateError('The host could not disconnect.', 'Retry shortly.');
299
307
  }
300
308
  return ctx.succeed(Object.assign({ host, product }, result.data), ctx.ui.result({
301
309
  title: result.data.removed
302
- ? `Disconnected ${product} for ${source}`
303
- : `${product} was not connected for ${source}`,
310
+ ? `Disconnected the ${product} Source connection on ${source}`
311
+ : `${product} had no Source connection on ${source}`,
304
312
  rows: [
305
313
  [
306
314
  'Provided agents',
@@ -325,12 +333,12 @@ function connectionSummary(ctx, connection, meta) {
325
333
  ['Redirect URL', meta.callbackUrls],
326
334
  [
327
335
  'Used by',
328
- 'provided agents whose template says connections.<product>.owner: "source", in every team',
336
+ `provided agents whose template says connections.${connection.slug}.owner: "source", in every team`,
329
337
  ],
330
338
  ];
331
339
  return [
332
340
  ctx.ui.result({
333
- title: `${connection.name} — one connection for the whole Source`,
341
+ title: `${connection.name} — Source connection (one for every team's provided agents)`,
334
342
  rows,
335
343
  }),
336
344
  ...(connection.connected
@@ -344,7 +352,7 @@ async function openClient(ctx, args) {
344
352
  const env = resolveAuthEnvironment(ctx, args.host, args.env, {
345
353
  projectDir: args.dir,
346
354
  });
347
- const resolved = await resolveSourceTarget(env, requireSession(env.store, env.host), args);
355
+ const resolved = await resolveSourceTarget(env, requireSession(env), args);
348
356
  return {
349
357
  env,
350
358
  client: new AppsClient(env, resolved.session),
@@ -364,7 +372,7 @@ class AppsClient {
364
372
  }
365
373
  if (result.status === 'ok')
366
374
  return result.data;
367
- throw authRequiredError(`The session for ${this.env.host} could not authorize the apps call.`, `Run "ekanos login --host ${this.env.host}" and retry.`);
375
+ throw authRequiredError(`The session for ${this.env.host} could not authorize the apps call.`, loginHint(this.env));
368
376
  }
369
377
  /** As `call`, for the connections client, whose 409s are answers. */
370
378
  async connection(send) {
@@ -375,7 +383,7 @@ class AppsClient {
375
383
  }
376
384
  if (result.status !== 'unauthorized')
377
385
  return result;
378
- throw authRequiredError(`The session for ${this.env.host} could not authorize the connections call.`, `Run "ekanos login --host ${this.env.host}" and retry.`);
386
+ throw authRequiredError(`The session for ${this.env.host} could not authorize the connections call.`, loginHint(this.env));
379
387
  }
380
388
  }
381
389
  function canPrompt(ctx, args) {
@@ -409,27 +417,101 @@ export async function promptLine(question) {
409
417
  rl.close();
410
418
  }
411
419
  }
412
- /** Read a line without echoing it: the secret never appears on screen or in scrollback. */
420
+ /**
421
+ * Read a line without echoing it: the secret never appears on screen or in
422
+ * scrollback. The question is always printed; only the typed characters are
423
+ * hidden (each shows as `*`, so a paste visibly landed).
424
+ *
425
+ * Raw mode by hand rather than readline: a terminal readline redraws its
426
+ * line on `question()` — cursor to column 0, clear to the end of the screen —
427
+ * which erased the question written before it, so the terminal sat on an
428
+ * empty line and a hidden field looked skipped.
429
+ */
413
430
  export async function promptHidden(question) {
414
- const readline = await import('node:readline');
415
- process.stderr.write(question);
416
- const rl = readline.createInterface({
417
- input: process.stdin,
418
- output: process.stderr,
419
- terminal: true,
420
- });
421
- // Swallow readline's echo of each keystroke; the question is already written.
422
- rl._writeToOutput =
423
- () => { };
424
- try {
425
- return await new Promise((resolve) => {
426
- rl.question('', resolve);
427
- });
428
- }
429
- finally {
430
- rl.close();
431
- process.stderr.write('\n');
431
+ const stdin = process.stdin;
432
+ const stderr = process.stderr;
433
+ stderr.write(question);
434
+ if (!stdin.isTTY) {
435
+ // Piped stdin echoes nothing: read one line as is.
436
+ const readline = await import('node:readline/promises');
437
+ const rl = readline.createInterface({ input: stdin, terminal: false });
438
+ try {
439
+ return await rl.question('');
440
+ }
441
+ finally {
442
+ rl.close();
443
+ stderr.write('\n');
444
+ }
432
445
  }
446
+ return new Promise((resolve) => {
447
+ let value = '';
448
+ let inEscape = false;
449
+ const wasRaw = stdin.isRaw;
450
+ const finish = () => {
451
+ stdin.off('data', onData);
452
+ stdin.setRawMode(wasRaw);
453
+ stdin.pause();
454
+ stderr.write('\n');
455
+ };
456
+ const onData = (chunk) => {
457
+ for (const char of typeof chunk === 'string'
458
+ ? chunk
459
+ : chunk.toString('utf8')) {
460
+ if (inEscape) {
461
+ // An escape sequence (an arrow key) ends at its final letter.
462
+ if (/[A-Za-z~]/.test(char))
463
+ inEscape = false;
464
+ continue;
465
+ }
466
+ if (char === '\u001b') {
467
+ inEscape = true;
468
+ continue;
469
+ }
470
+ if (char === '\r' || char === '\n' || char === '\u0004') {
471
+ finish();
472
+ resolve(value);
473
+ return;
474
+ }
475
+ if (char === '\u0003') {
476
+ // Ctrl-C: raw mode swallowed the signal, so leave as SIGINT would.
477
+ finish();
478
+ process.exit(130);
479
+ }
480
+ if (char === '\u007f' || char === '\b') {
481
+ if (value.length > 0) {
482
+ value = value.slice(0, -1);
483
+ stderr.write('\b \b');
484
+ }
485
+ continue;
486
+ }
487
+ if (char === '\u0015') {
488
+ // Ctrl-U: clear what was typed.
489
+ stderr.write('\b \b'.repeat(value.length));
490
+ value = '';
491
+ continue;
492
+ }
493
+ if (char < ' ')
494
+ continue;
495
+ value += char;
496
+ stderr.write('*');
497
+ }
498
+ };
499
+ stdin.setRawMode(true);
500
+ stdin.resume();
501
+ stdin.on('data', onData);
502
+ });
503
+ }
504
+ /** Each credential's state: the client id's value, the secret as saved or not. */
505
+ function providerFieldRows(status) {
506
+ var _a;
507
+ return ((_a = status.fields) !== null && _a !== void 0 ? _a : []).map((field) => { var _a; return [
508
+ field.label,
509
+ !field.set
510
+ ? 'not set'
511
+ : field.sensitive
512
+ ? 'saved'
513
+ : ((_a = field.value) !== null && _a !== void 0 ? _a : 'saved'),
514
+ ]; });
433
515
  }
434
516
  /** Every redirect URI to register; an older host sends only the one. */
435
517
  function callbackUrls(status) {
@@ -1 +1 @@
1
- {"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/commands/apps.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ProviderAppStatus } from '@ekanos/integration-schema';\n\nimport {\n type AppsApiResult,\n setProviderApp,\n showProviderApp,\n} from '../apps-api';\nimport type { StoredSession } from '../auth/credential-store';\nimport {\n type AuthEnvironment,\n refreshStoredSession,\n requireSession,\n resolveAuthEnvironment,\n} from '../auth/session';\nimport {\n type ConnectionsApiResult,\n type SourceConnection,\n deleteConnection,\n listConnections,\n showConnection,\n startConnection,\n} from '../connections-api';\nimport type { CliContext } from '../context';\nimport {\n authRequiredError,\n invalidStateError,\n usageError,\n validationError,\n} from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { resolveSourceTarget } from '../source-target';\nimport type { ResultRow } from '../ui';\nimport { promptYesNo } from './publish';\n\nexport const APPS_SUBCOMMANDS = [\n 'show',\n 'set',\n 'list',\n 'connect',\n 'disconnect',\n] as const;\ntype AppsSubcommand = (typeof APPS_SUBCOMMANDS)[number];\n\nexport interface AppsArgs {\n host?: string;\n source?: string;\n subcommand?: string;\n product?: string;\n dir: string;\n env: Record<string, string | undefined>;\n stdinIsTTY?: boolean;\n /** Test seams for the questions `set` and `connect` ask. */\n ask?: (question: string) => Promise<string>;\n askSecret?: (question: string) => Promise<string>;\n confirm?: (question: string) => Promise<boolean>;\n /** Test seam: `connect`'s wait between status polls. */\n pollDelayMs?: number;\n /** `connect --no-wait`: print the URL and return without polling. */\n noWait?: boolean;\n}\n\n/**\n * `apps` — a Source's provider apps: the OAuth client an integration signs\n * every team in through (Linear's, say). `show` says whether the Source has\n * one and which callback URL to register; `set` takes the client id and\n * secret from the Source admin at the terminal — never from a flag, a file\n * or a non-interactive run, so an agent driving the CLI never handles the\n * secret.\n */\nexport async function runApps(\n ctx: CliContext,\n args: AppsArgs,\n): Promise<ExitCode> {\n const subcommand = parseSubcommand(args.subcommand);\n if (subcommand === 'list') return runList(ctx, args);\n const product = requireProduct(args.product, subcommand);\n if (subcommand === 'connect' || subcommand === 'disconnect') {\n return runConnection(ctx, args, subcommand, product);\n }\n\n if (subcommand === 'set' && !canPrompt(ctx, args)) {\n throw usageError(\n 'apps set takes the client secret at a terminal, never in a script or an agent run.',\n `Run it yourself in your terminal: npx @ekanos/cli apps set ${product}${args.source ? ` --source ${args.source}` : ''}`,\n );\n }\n\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const resolved = await resolveSourceTarget(\n env,\n requireSession(env.store, env.host),\n args,\n );\n const client = new AppsClient(env, resolved.session);\n const source = resolved.source;\n\n if (subcommand === 'show') {\n return showApp(ctx, env.host, client, source, product);\n }\n\n const status = await client.call((token) =>\n showProviderApp(env.host, token, source, product),\n );\n\n ctx.log(walkthrough(status).join('\\n'));\n if (status.configured) {\n const replace = await (args.confirm ?? promptYesNo)(\n `${status.source.slug} already has ${status.product.name} credentials. Replace them? [y/N]`,\n );\n if (!replace) {\n throw validationError(\n 'Nothing was changed.',\n `Run \"ekanos apps show ${product}\" to see the current state.`,\n );\n }\n }\n\n const clientId = (await (args.ask ?? promptLine)('Client ID: ')).trim();\n const clientSecret = (\n await (args.askSecret ?? promptHidden)('Client secret (hidden): ')\n ).trim();\n if (!clientId || !clientSecret) {\n throw validationError(\n 'Both the client ID and the client secret are needed.',\n `Run \"ekanos apps set ${product}\" again.`,\n );\n }\n\n const result = await client.call((token) =>\n setProviderApp(env.host, token, {\n source,\n product,\n clientId,\n clientSecret,\n }),\n );\n return ctx.succeed(\n { host: env.host, ...result },\n ctx.ui.result({\n title: result.replaced\n ? `Replaced the ${result.product.name} app`\n : `Set up the ${result.product.name} app`,\n rows: [\n ['Source', result.source.slug],\n ['Teams can connect', result.configured ? 'yes' : 'not yet'],\n ['Callback URLs', callbackUrls(result)],\n ],\n }),\n );\n}\n\n/**\n * How to create the app: the integration's own steps (`oauth.setup`, with the\n * callback URL filled in) when it declares them, else the generic three.\n */\nexport function walkthrough(status: ProviderAppStatus): string[] {\n const name = status.product.name;\n const lines = [`${name} app for ${status.source.slug}`];\n if (status.setup?.consoleUrl) {\n lines.push(` Open: ${status.setup.consoleUrl}`);\n }\n const steps = status.setup?.steps.length\n ? [\n ...status.setup.steps,\n `Check the app lists exactly: ${callbackUrls(status).join(', ')}`,\n ]\n : [\n `In ${name}, create an OAuth app (or open the one you use).`,\n `Register exactly these callback URLs: ${callbackUrls(status).join(', ')}`,\n ];\n steps.push(\n \"Enter its client ID and secret below. The secret is stored in Ekanos's vault and never shown again.\",\n );\n lines.push(...steps.map((step, index) => ` ${index + 1}. ${step}`));\n if (status.setup?.guideUrl) lines.push(` Guide: ${status.setup.guideUrl}`);\n return lines;\n}\n\nfunction summary(ctx: CliContext, status: ProviderAppStatus): string {\n const rows: ResultRow[] = [\n ['Source', status.source.slug],\n ...(status.setup\n ? ([\n [\n 'How to create it',\n [\n ...(status.setup.consoleUrl\n ? [`Open ${status.setup.consoleUrl}`]\n : []),\n ...status.setup.steps.map(\n (step, index) => `${index + 1}. ${step}`,\n ),\n ],\n ],\n ] as const)\n : []),\n [\n 'Set up',\n status.configured\n ? 'yes — teams can connect'\n : 'no — no team can connect yet',\n ],\n ['Callback URLs', callbackUrls(status)],\n ];\n return [\n ctx.ui.result({ title: `${status.product.name} app`, rows }),\n ...(status.configured\n ? []\n : [\n ctx.ui.hint(\n `Run \"ekanos apps set ${status.product.slug}\" in your terminal to enter its credentials.`,\n ),\n ]),\n ].join('\\n');\n}\n\n/**\n * `apps show <product>`: the Source provider app, and — for an integration\n * that supports one — the Source connection (plan 241). A `teamApp`\n * integration (Zendesk) has no provider app but can have a Source\n * connection, so either half may be absent.\n */\nasync function showApp(\n ctx: CliContext,\n host: string,\n client: AppsClient,\n source: string,\n product: string,\n): Promise<ExitCode> {\n const [app, connection] = await Promise.all([\n client\n .call((token) => showProviderApp(host, token, source, product))\n .then(\n (status) => ({ ok: true as const, status }),\n (error: unknown) => ({ ok: false as const, error }),\n ),\n // A host without the connections routes (before plan 241), or one that\n // refuses, leaves `show` exactly as it was: the provider app alone.\n client\n .connection((token) => showConnection(host, token, source, product))\n .catch(() => ({ status: 'unavailable' as const })),\n ]);\n\n if (!app.ok && connection.status !== 'ok') throw app.error;\n\n const parts: string[] = [];\n if (app.ok) parts.push(summary(ctx, app.status));\n if (connection.status === 'ok') {\n parts.push(\n connectionSummary(ctx, connection.data.connection, {\n sourceSlug: connection.data.source.slug,\n callbackUrls: connection.data.callbackUrls,\n }),\n );\n }\n\n return ctx.succeed(\n {\n host,\n ...(app.ok ? app.status : {}),\n ...(connection.status === 'ok'\n ? {\n sourceConnection: connection.data.connection,\n sourceConnectionCallbackUrls: connection.data.callbackUrls,\n }\n : {}),\n },\n parts.join('\\n'),\n );\n}\n\n/** `apps list`: every integration the Source can connect once, with status. */\nasync function runList(ctx: CliContext, args: AppsArgs): Promise<ExitCode> {\n const { env, client, source } = await openClient(ctx, args);\n const result = await client.connection((token) =>\n listConnections(env.host, token, source),\n );\n if (result.status !== 'ok') {\n throw invalidStateError(\n 'The host could not list the connections.',\n 'Retry shortly.',\n );\n }\n const { connections } = result.data;\n const rows: ResultRow[] = connections.map((connection) => [\n `${connection.name} (${connection.slug})`,\n connectionState(connection),\n ]);\n return ctx.succeed(\n { host: env.host, ...result.data },\n connections.length === 0\n ? ctx.ui.hint(\n `No integration on ${result.data.source.slug} supports one connection for the whole Source yet.`,\n )\n : ctx.ui.result({\n title: `Source connections on ${result.data.source.slug}`,\n rows,\n }),\n );\n}\n\nfunction connectionState(connection: SourceConnection): string {\n if (connection.connected) {\n return [\n 'connected',\n connection.connectedAt ? ` ${connection.connectedAt}` : '',\n connection.connectedBy ? ` by ${connection.connectedBy}` : '',\n ].join('');\n }\n return connection.missing.length > 0\n ? `not connected — app fields missing: ${connection.missing.join(', ')}`\n : 'not connected';\n}\n\n/**\n * `apps connect <product>`: connect the integration ONCE for the whole Source,\n * for the Source's provided agents whose template says `owner: \"source\"`.\n * Asks for any missing app fields at the terminal (secrets hidden, never from\n * a flag), prints the provider's consent URL, then waits until the browser\n * finishes. `apps disconnect <product>` removes it.\n */\nasync function runConnection(\n ctx: CliContext,\n args: AppsArgs,\n subcommand: 'connect' | 'disconnect',\n product: string,\n): Promise<ExitCode> {\n const { env, client, source } = await openClient(ctx, args);\n\n if (subcommand === 'disconnect') {\n return disconnect(ctx, args, client, env.host, source, product);\n }\n\n const shown = await client.connection((token) =>\n showConnection(env.host, token, source, product),\n );\n if (shown.status === 'unsupported') {\n throw invalidStateError(\n shown.message,\n `Each team connects ${product} itself, from the team's Integrations page.`,\n );\n }\n if (shown.status !== 'ok') {\n throw invalidStateError(\n 'The host could not read the connection.',\n 'Retry shortly.',\n );\n }\n const current = shown.data.connection;\n\n if (current.app === 'fields') {\n ctx.log(\n [\n `${current.name} app for ${shown.data.source.slug} (one for the whole Source)`,\n ` Register this redirect URL in the app: ${shown.data.callbackUrls.join(', ')}`,\n ].join('\\n'),\n );\n }\n\n const fields = await askFields(ctx, args, current, product);\n\n const started = await client.connection((token) =>\n startConnection(env.host, token, {\n source,\n product,\n ...(Object.keys(fields).length > 0 ? { fields } : {}),\n }),\n );\n if (started.status === 'not-configured') {\n throw validationError(\n `${current.name} is not set up for the Source yet — missing: ${started.missing.join(', ')}.`,\n current.app === 'source-app'\n ? `Run \"ekanos apps set ${product}\" to enter the Source's app first.`\n : `Run \"ekanos apps connect ${product}\" again and fill every field.`,\n );\n }\n if (started.status !== 'ok') {\n throw invalidStateError(\n 'The host could not start the connection.',\n 'Retry shortly.',\n );\n }\n\n ctx.log(\n [\n `Open this link and approve ${current.name} as the account the Source's agents should act as:`,\n ` ${started.data.authorizeUrl}`,\n ].join('\\n'),\n );\n\n if (args.noWait || ctx.jsonMode) {\n return ctx.succeed(\n {\n host: env.host,\n product,\n authorizeUrl: started.data.authorizeUrl,\n callbackUrl: started.data.callbackUrl,\n connected: false,\n },\n ctx.ui.hint(`Then check with \"ekanos apps show ${product}\".`),\n );\n }\n\n const deadline = Date.now() + 10 * 60 * 1000;\n const before = current.connectedAt;\n while (Date.now() < deadline) {\n await new Promise((resolve) =>\n setTimeout(resolve, args.pollDelayMs ?? 3000),\n );\n const polled = await client.connection((token) =>\n showConnection(env.host, token, source, product),\n );\n if (\n polled.status === 'ok' &&\n polled.data.connection.connected &&\n polled.data.connection.connectedAt !== before\n ) {\n return ctx.succeed(\n { host: env.host, product, connection: polled.data.connection },\n connectionSummary(ctx, polled.data.connection, {\n sourceSlug: polled.data.source.slug,\n callbackUrls: polled.data.callbackUrls,\n }),\n );\n }\n }\n throw validationError(\n 'The connection did not finish within ten minutes.',\n `Run \"ekanos apps connect ${product}\" again for a fresh link.`,\n );\n}\n\nasync function askFields(\n ctx: CliContext,\n args: AppsArgs,\n current: SourceConnection,\n product: string,\n): Promise<Record<string, string>> {\n const toAsk = current.fields.filter(\n (field) => !field.set || current.missing.includes(field.name),\n );\n if (toAsk.length === 0) return {};\n if (!canPrompt(ctx, args)) {\n throw usageError(\n `${current.name} needs its app fields entered for the Source: ${toAsk.map((field) => field.label).join(', ')}.`,\n `Run it yourself in your terminal: npx @ekanos/cli apps connect ${product}${args.source ? ` --source ${args.source}` : ''}`,\n );\n }\n const fields: Record<string, string> = {};\n for (const field of toAsk) {\n const question = field.sensitive\n ? `${field.label} (hidden): `\n : `${field.label}: `;\n const value = (\n await (\n field.sensitive\n ? (args.askSecret ?? promptHidden)\n : (args.ask ?? promptLine)\n )(question)\n ).trim();\n if (value) fields[field.name] = value;\n }\n return fields;\n}\n\nasync function disconnect(\n ctx: CliContext,\n args: AppsArgs,\n client: AppsClient,\n host: string,\n source: string,\n product: string,\n): Promise<ExitCode> {\n if (canPrompt(ctx, args)) {\n const sure = await (args.confirm ?? promptYesNo)(\n `Disconnect ${product} for every team's provided agents on ${source}? [y/N]`,\n );\n if (!sure) {\n throw validationError(\n 'Nothing was changed.',\n `Run \"ekanos apps show ${product}\" to see the current state.`,\n );\n }\n }\n const result = await client.connection((token) =>\n deleteConnection(host, token, source, product),\n );\n if (result.status === 'unsupported') {\n throw invalidStateError(\n result.message,\n `Each team connects ${product} itself, from the team's Integrations page.`,\n );\n }\n if (result.status !== 'ok') {\n throw invalidStateError('The host could not disconnect.', 'Retry shortly.');\n }\n return ctx.succeed(\n { host, product, ...result.data },\n ctx.ui.result({\n title: result.data.removed\n ? `Disconnected ${product} for ${source}`\n : `${product} was not connected for ${source}`,\n rows: [\n [\n 'Provided agents',\n 'their tools for this product stop until you connect again',\n ],\n ],\n }),\n );\n}\n\nfunction connectionSummary(\n ctx: CliContext,\n connection: SourceConnection,\n meta: { sourceSlug: string; callbackUrls: string[] },\n): string {\n const rows: ResultRow[] = [\n ['Source', meta.sourceSlug],\n ['Connected', connectionState(connection)],\n ...(connection.scope ? ([['Scope', connection.scope]] as ResultRow[]) : []),\n ...(connection.fields.length > 0\n ? ([\n [\n 'App fields',\n connection.fields.map(\n (field) =>\n `${field.label}: ${field.set ? (field.value ?? 'set') : 'missing'}`,\n ),\n ],\n ] as ResultRow[])\n : []),\n ['Redirect URL', meta.callbackUrls],\n [\n 'Used by',\n 'provided agents whose template says connections.<product>.owner: \"source\", in every team',\n ],\n ];\n return [\n ctx.ui.result({\n title: `${connection.name} — one connection for the whole Source`,\n rows,\n }),\n ...(connection.connected\n ? []\n : [\n ctx.ui.hint(\n `Run \"ekanos apps connect ${connection.slug}\" in your terminal to connect it.`,\n ),\n ]),\n ].join('\\n');\n}\n\nasync function openClient(ctx: CliContext, args: AppsArgs) {\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const resolved = await resolveSourceTarget(\n env,\n requireSession(env.store, env.host),\n args,\n );\n return {\n env,\n client: new AppsClient(env, resolved.session),\n source: resolved.source,\n };\n}\n\nclass AppsClient {\n constructor(\n private readonly env: AuthEnvironment,\n private session: StoredSession,\n ) {}\n\n async call<T>(\n send: (accessToken: string) => Promise<AppsApiResult<T>>,\n ): Promise<T> {\n let result = await send(this.session.accessToken);\n if (result.status === 'unauthorized') {\n this.session = await refreshStoredSession(this.env, this.session);\n result = await send(this.session.accessToken);\n }\n if (result.status === 'ok') return result.data;\n throw authRequiredError(\n `The session for ${this.env.host} could not authorize the apps call.`,\n `Run \"ekanos login --host ${this.env.host}\" and retry.`,\n );\n }\n\n /** As `call`, for the connections client, whose 409s are answers. */\n async connection<T>(\n send: (accessToken: string) => Promise<ConnectionsApiResult<T>>,\n ): Promise<Exclude<ConnectionsApiResult<T>, { status: 'unauthorized' }>> {\n let result = await send(this.session.accessToken);\n if (result.status === 'unauthorized') {\n this.session = await refreshStoredSession(this.env, this.session);\n result = await send(this.session.accessToken);\n }\n if (result.status !== 'unauthorized') return result;\n throw authRequiredError(\n `The session for ${this.env.host} could not authorize the connections call.`,\n `Run \"ekanos login --host ${this.env.host}\" and retry.`,\n );\n }\n}\n\nfunction canPrompt(ctx: CliContext, args: AppsArgs): boolean {\n return !ctx.jsonMode && (args.stdinIsTTY ?? process.stdin.isTTY === true);\n}\n\nfunction parseSubcommand(value: string | undefined): AppsSubcommand {\n const match = APPS_SUBCOMMANDS.find((name) => name === value);\n if (match) return match;\n throw usageError(\n value ? `Unknown apps subcommand \"${value}\".` : 'apps needs a subcommand.',\n `Run one of: ${APPS_SUBCOMMANDS.map((name) => `ekanos apps ${name} <product>`).join(', ')}.`,\n );\n}\n\nfunction requireProduct(value: string | undefined, verb: string): string {\n const slug = value?.trim().toLowerCase();\n if (slug && /^[a-z0-9][a-z0-9-]*$/.test(slug)) return slug;\n throw usageError(\n value\n ? `\"${value}\" is not a product slug.`\n : `apps ${verb} needs a product.`,\n `Pass the product's slug, e.g. \"ekanos apps ${verb} linear\". \"ekanos catalog\" lists them.`,\n );\n}\n\nexport async function promptLine(question: string): Promise<string> {\n const readline = await import('node:readline/promises');\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n try {\n return await rl.question(question);\n } finally {\n rl.close();\n }\n}\n\n/** Read a line without echoing it: the secret never appears on screen or in scrollback. */\nexport async function promptHidden(question: string): Promise<string> {\n const readline = await import('node:readline');\n process.stderr.write(question);\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n terminal: true,\n });\n // Swallow readline's echo of each keystroke; the question is already written.\n (rl as unknown as { _writeToOutput: (text: string) => void })._writeToOutput =\n () => {};\n try {\n return await new Promise<string>((resolve) => {\n rl.question('', resolve);\n });\n } finally {\n rl.close();\n process.stderr.write('\\n');\n }\n}\n\n/** Every redirect URI to register; an older host sends only the one. */\nfunction callbackUrls(status: ProviderAppStatus): string[] {\n return status.callbackUrls?.length\n ? status.callbackUrls\n : [status.callbackUrl];\n}\n"]}
1
+ {"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/commands/apps.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ProviderAppStatus } from '@ekanos/integration-schema';\n\nimport {\n type AppsApiResult,\n setProviderApp,\n showProviderApp,\n} from '../apps-api';\nimport type { StoredSession } from '../auth/credential-store';\nimport { loginHint } from '../auth/host-trust';\nimport {\n type AuthEnvironment,\n refreshStoredSession,\n requireSession,\n resolveAuthEnvironment,\n} from '../auth/session';\nimport {\n type ConnectionsApiResult,\n type SourceConnection,\n deleteConnection,\n listConnections,\n showConnection,\n startConnection,\n} from '../connections-api';\nimport type { CliContext } from '../context';\nimport {\n authRequiredError,\n invalidStateError,\n usageError,\n validationError,\n} from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { resolveSourceTarget } from '../source-target';\nimport type { ResultRow } from '../ui';\nimport { promptYesNo } from './publish';\n\nexport const APPS_SUBCOMMANDS = [\n 'show',\n 'set',\n 'list',\n 'connect',\n 'disconnect',\n] as const;\ntype AppsSubcommand = (typeof APPS_SUBCOMMANDS)[number];\n\nexport interface AppsArgs {\n host?: string;\n source?: string;\n subcommand?: string;\n product?: string;\n dir: string;\n env: Record<string, string | undefined>;\n stdinIsTTY?: boolean;\n /** Test seams for the questions `set` and `connect` ask. */\n ask?: (question: string) => Promise<string>;\n askSecret?: (question: string) => Promise<string>;\n confirm?: (question: string) => Promise<boolean>;\n /** Test seam: `connect`'s wait between status polls. */\n pollDelayMs?: number;\n /** `connect --no-wait`: print the URL and return without polling. */\n noWait?: boolean;\n /** `disconnect --yes`: confirm without the question (a script, an agent run). */\n yes?: boolean;\n}\n\n/**\n * `apps` — a Source's provider apps: the OAuth client an integration signs\n * every team in through (Linear's, say). `show` says whether the Source has\n * one and which callback URL to register; `set` takes the client id and\n * secret from the Source admin at the terminal — either on its own, Enter\n * keeping the saved one — never from a flag, a file or a non-interactive\n * run, so an agent driving the CLI never handles the secret.\n */\nexport async function runApps(\n ctx: CliContext,\n args: AppsArgs,\n): Promise<ExitCode> {\n const subcommand = parseSubcommand(args.subcommand);\n if (subcommand === 'list') return runList(ctx, args);\n const product = requireProduct(args.product, subcommand);\n if (subcommand === 'connect' || subcommand === 'disconnect') {\n return runConnection(ctx, args, subcommand, product);\n }\n\n if (subcommand === 'set' && !canPrompt(ctx, args)) {\n throw usageError(\n 'apps set takes the client secret at a terminal, never in a script or an agent run.',\n `Run it yourself in your terminal: npx @ekanos/cli apps set ${product}${args.source ? ` --source ${args.source}` : ''}`,\n );\n }\n\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const resolved = await resolveSourceTarget(env, requireSession(env), args);\n const client = new AppsClient(env, resolved.session);\n const source = resolved.source;\n\n if (subcommand === 'show') {\n return showApp(ctx, env.host, client, source, product);\n }\n\n const status = await client.call((token) =>\n showProviderApp(env.host, token, source, product),\n );\n\n ctx.log(walkthrough(status).join('\\n'));\n\n // Either credential on its own: Enter keeps what is saved. An older host\n // sends no `fields`; then `configured` says whether both are saved.\n const saved = (name: 'clientId' | 'clientSecret') =>\n status.fields?.find((field) => field.name === name) ?? {\n set: status.configured,\n value: null,\n };\n const savedId = saved('clientId');\n const savedSecret = saved('clientSecret');\n const clientId = (\n await (args.ask ?? promptLine)(\n savedId.set\n ? `Client ID (current: ${savedId.value ?? 'saved'} — Enter to keep): `\n : 'Client ID: ',\n )\n ).trim();\n const clientSecret = (\n await (args.askSecret ?? promptHidden)(\n savedSecret.set\n ? 'Client secret (saved — Enter to keep, hidden): '\n : 'Client secret (hidden): ',\n )\n ).trim();\n if (!clientId && !clientSecret) {\n throw validationError(\n 'Nothing was changed.',\n `Run \"ekanos apps show ${product}\" to see the current state.`,\n );\n }\n\n const result = await client.call((token) =>\n setProviderApp(env.host, token, {\n source,\n product,\n ...(clientId ? { clientId } : {}),\n ...(clientSecret ? { clientSecret } : {}),\n }),\n );\n return ctx.succeed(\n { host: env.host, ...result },\n ctx.ui.result({\n title: result.replaced\n ? `Updated the ${result.product.name} app`\n : `Set up the ${result.product.name} app`,\n rows: [\n ['Source', result.source.slug],\n ...providerFieldRows(result),\n ['Teams can connect', result.configured ? 'yes' : 'not yet'],\n ['Callback URLs', callbackUrls(result)],\n ],\n }),\n );\n}\n\n/**\n * How to create the app: the integration's own steps (`oauth.setup`, with the\n * callback URL filled in) when it declares them, else the generic three.\n */\nexport function walkthrough(status: ProviderAppStatus): string[] {\n const name = status.product.name;\n const lines = [`${name} app for ${status.source.slug}`];\n if (status.setup?.consoleUrl) {\n lines.push(` Open: ${status.setup.consoleUrl}`);\n }\n const steps = status.setup?.steps.length\n ? [\n ...status.setup.steps,\n `Check the app lists exactly: ${callbackUrls(status).join(', ')}`,\n ]\n : [\n `In ${name}, create an OAuth app (or open the one you use).`,\n `Register exactly these callback URLs: ${callbackUrls(status).join(', ')}`,\n ];\n steps.push(\n \"Enter its client ID and secret below. The secret is stored in Ekanos's vault and never shown again.\",\n );\n lines.push(...steps.map((step, index) => ` ${index + 1}. ${step}`));\n if (status.setup?.guideUrl) lines.push(` Guide: ${status.setup.guideUrl}`);\n return lines;\n}\n\nfunction summary(ctx: CliContext, status: ProviderAppStatus): string {\n const rows: ResultRow[] = [\n ['Source', status.source.slug],\n ...(status.setup\n ? ([\n [\n 'How to create it',\n [\n ...(status.setup.consoleUrl\n ? [`Open ${status.setup.consoleUrl}`]\n : []),\n ...status.setup.steps.map(\n (step, index) => `${index + 1}. ${step}`,\n ),\n ],\n ],\n ] as const)\n : []),\n ...providerFieldRows(status),\n [\n 'App ready',\n status.configured\n ? 'yes — teams can connect'\n : 'no — no team can connect yet',\n ],\n ['Callback URLs', callbackUrls(status)],\n ];\n return [\n ctx.ui.result({ title: `${status.product.name} app`, rows }),\n ...(status.configured\n ? []\n : [\n ctx.ui.hint(\n `Run \"ekanos apps set ${status.product.slug}\" in your terminal to enter its credentials.`,\n ),\n ]),\n ].join('\\n');\n}\n\n/**\n * `apps show <product>`: the Source provider app, and — for an integration\n * that supports one — the Source connection (plan 241). A `teamApp`\n * integration (Zendesk) has no provider app but can have a Source\n * connection, so either half may be absent.\n */\nasync function showApp(\n ctx: CliContext,\n host: string,\n client: AppsClient,\n source: string,\n product: string,\n): Promise<ExitCode> {\n const [app, connection] = await Promise.all([\n client\n .call((token) => showProviderApp(host, token, source, product))\n .then(\n (status) => ({ ok: true as const, status }),\n (error: unknown) => ({ ok: false as const, error }),\n ),\n // A host without the connections routes (before plan 241), or one that\n // refuses, leaves `show` exactly as it was: the provider app alone.\n client\n .connection((token) => showConnection(host, token, source, product))\n .catch(() => ({ status: 'unavailable' as const })),\n ]);\n\n if (!app.ok && connection.status !== 'ok') throw app.error;\n\n const parts: string[] = [];\n if (app.ok) parts.push(summary(ctx, app.status));\n if (connection.status === 'ok') {\n parts.push(\n connectionSummary(ctx, connection.data.connection, {\n sourceSlug: connection.data.source.slug,\n callbackUrls: connection.data.callbackUrls,\n }),\n );\n }\n\n return ctx.succeed(\n {\n host,\n ...(app.ok ? app.status : {}),\n ...(connection.status === 'ok'\n ? {\n sourceConnection: connection.data.connection,\n sourceConnectionCallbackUrls: connection.data.callbackUrls,\n }\n : {}),\n },\n parts.join('\\n'),\n );\n}\n\n/** `apps list`: every integration the Source can connect once, with status. */\nasync function runList(ctx: CliContext, args: AppsArgs): Promise<ExitCode> {\n const { env, client, source } = await openClient(ctx, args);\n const result = await client.connection((token) =>\n listConnections(env.host, token, source),\n );\n if (result.status !== 'ok') {\n throw invalidStateError(\n 'The host could not list the connections.',\n 'Retry shortly.',\n );\n }\n const { connections } = result.data;\n const rows: ResultRow[] = connections.map((connection) => [\n `${connection.name} (${connection.slug})`,\n connectionState(connection),\n ]);\n return ctx.succeed(\n { host: env.host, ...result.data },\n connections.length === 0\n ? ctx.ui.hint(\n `No integration on ${result.data.source.slug} supports one connection for the whole Source yet.`,\n )\n : ctx.ui.result({\n title: `Source connections on ${result.data.source.slug}`,\n rows,\n }),\n );\n}\n\nfunction connectionState(connection: SourceConnection): string {\n if (connection.connected) {\n return [\n 'connected',\n connection.connectedAt ? ` ${connection.connectedAt}` : '',\n connection.connectedBy ? ` by ${connection.connectedBy}` : '',\n ].join('');\n }\n return connection.missing.length > 0\n ? `not connected — app fields missing: ${connection.missing.join(', ')}`\n : 'not connected';\n}\n\n/**\n * `apps connect <product>`: connect the integration ONCE for the whole Source,\n * for the Source's provided agents whose template says `owner: \"source\"`.\n * Asks for any missing app fields at the terminal (secrets hidden, never from\n * a flag), prints the provider's consent URL, then waits until the browser\n * finishes. `apps disconnect <product>` removes it.\n */\nasync function runConnection(\n ctx: CliContext,\n args: AppsArgs,\n subcommand: 'connect' | 'disconnect',\n product: string,\n): Promise<ExitCode> {\n const { env, client, source } = await openClient(ctx, args);\n\n if (subcommand === 'disconnect') {\n return disconnect(ctx, args, client, env.host, source, product);\n }\n\n const shown = await client.connection((token) =>\n showConnection(env.host, token, source, product),\n );\n if (shown.status === 'unsupported') {\n throw invalidStateError(\n shown.message,\n `Each team connects ${product} itself: \"ekanos teams connect <team> ${product}\".`,\n );\n }\n if (shown.status !== 'ok') {\n throw invalidStateError(\n 'The host could not read the connection.',\n 'Retry shortly.',\n );\n }\n const current = shown.data.connection;\n\n if (current.app === 'fields') {\n ctx.log(\n [\n `${current.name} app for ${shown.data.source.slug} (one for the whole Source)`,\n ` Register this redirect URL in the app: ${shown.data.callbackUrls.join(', ')}`,\n ].join('\\n'),\n );\n }\n\n const fields = await askFields(ctx, args, current, product);\n\n const started = await client.connection((token) =>\n startConnection(env.host, token, {\n source,\n product,\n ...(Object.keys(fields).length > 0 ? { fields } : {}),\n }),\n );\n if (started.status === 'not-configured') {\n throw validationError(\n `${current.name} is not set up for the Source yet — missing: ${started.missing.join(', ')}.`,\n current.app === 'source-app'\n ? `Run \"ekanos apps set ${product}\" to enter the Source's app first.`\n : `Run \"ekanos apps connect ${product}\" again and fill every field.`,\n );\n }\n if (started.status !== 'ok') {\n throw invalidStateError(\n 'The host could not start the connection.',\n 'Retry shortly.',\n );\n }\n\n ctx.log(\n [\n `Open this link and approve ${current.name} as the account the Source's agents should act as:`,\n ` ${started.data.authorizeUrl}`,\n ].join('\\n'),\n );\n\n if (args.noWait || ctx.jsonMode) {\n return ctx.succeed(\n {\n host: env.host,\n product,\n authorizeUrl: started.data.authorizeUrl,\n callbackUrl: started.data.callbackUrl,\n connected: false,\n },\n ctx.ui.hint(`Then check with \"ekanos apps show ${product}\".`),\n );\n }\n\n const deadline = Date.now() + 10 * 60 * 1000;\n const before = current.connectedAt;\n while (Date.now() < deadline) {\n await new Promise((resolve) =>\n setTimeout(resolve, args.pollDelayMs ?? 3000),\n );\n const polled = await client.connection((token) =>\n showConnection(env.host, token, source, product),\n );\n if (\n polled.status === 'ok' &&\n polled.data.connection.connected &&\n polled.data.connection.connectedAt !== before\n ) {\n return ctx.succeed(\n { host: env.host, product, connection: polled.data.connection },\n connectionSummary(ctx, polled.data.connection, {\n sourceSlug: polled.data.source.slug,\n callbackUrls: polled.data.callbackUrls,\n }),\n );\n }\n }\n throw validationError(\n 'The connection did not finish within ten minutes.',\n `Run \"ekanos apps connect ${product}\" again for a fresh link.`,\n );\n}\n\nasync function askFields(\n ctx: CliContext,\n args: AppsArgs,\n current: SourceConnection,\n product: string,\n): Promise<Record<string, string>> {\n const toAsk = current.fields.filter(\n (field) => !field.set || current.missing.includes(field.name),\n );\n if (toAsk.length === 0) return {};\n if (!canPrompt(ctx, args)) {\n throw usageError(\n `${current.name} needs its app fields entered for the Source: ${toAsk.map((field) => field.label).join(', ')}.`,\n `Run it yourself in your terminal: npx @ekanos/cli apps connect ${product}${args.source ? ` --source ${args.source}` : ''}`,\n );\n }\n const fields: Record<string, string> = {};\n for (const field of toAsk) {\n const question = field.sensitive\n ? `${field.label} (hidden): `\n : `${field.label}: `;\n const value = (\n await (\n field.sensitive\n ? (args.askSecret ?? promptHidden)\n : (args.ask ?? promptLine)\n )(question)\n ).trim();\n if (value) fields[field.name] = value;\n }\n return fields;\n}\n\nasync function disconnect(\n ctx: CliContext,\n args: AppsArgs,\n client: AppsClient,\n host: string,\n source: string,\n product: string,\n): Promise<ExitCode> {\n if (!args.yes && !canPrompt(ctx, args)) {\n throw invalidStateError(\n `Disconnecting ${product} on ${source} stops it for every team's provided agents that use the Source connection, until someone connects it again.`,\n `Re-run with --yes: ekanos apps disconnect ${product} --source ${source} --yes`,\n );\n }\n if (!args.yes) {\n const sure = await (args.confirm ?? promptYesNo)(\n `Disconnect ${product} for every team's provided agents on ${source}? [y/N]`,\n );\n if (!sure) {\n throw validationError(\n 'Nothing was changed.',\n `Run \"ekanos apps show ${product}\" to see the current state.`,\n );\n }\n }\n const result = await client.connection((token) =>\n deleteConnection(host, token, source, product),\n );\n if (result.status === 'unsupported') {\n throw invalidStateError(\n result.message,\n `Each team connects ${product} itself: \"ekanos teams connect <team> ${product}\".`,\n );\n }\n if (result.status !== 'ok') {\n throw invalidStateError('The host could not disconnect.', 'Retry shortly.');\n }\n return ctx.succeed(\n { host, product, ...result.data },\n ctx.ui.result({\n title: result.data.removed\n ? `Disconnected the ${product} Source connection on ${source}`\n : `${product} had no Source connection on ${source}`,\n rows: [\n [\n 'Provided agents',\n 'their tools for this product stop until you connect again',\n ],\n ],\n }),\n );\n}\n\nfunction connectionSummary(\n ctx: CliContext,\n connection: SourceConnection,\n meta: { sourceSlug: string; callbackUrls: string[] },\n): string {\n const rows: ResultRow[] = [\n ['Source', meta.sourceSlug],\n ['Connected', connectionState(connection)],\n ...(connection.scope ? ([['Scope', connection.scope]] as ResultRow[]) : []),\n ...(connection.fields.length > 0\n ? ([\n [\n 'App fields',\n connection.fields.map(\n (field) =>\n `${field.label}: ${field.set ? (field.value ?? 'set') : 'missing'}`,\n ),\n ],\n ] as ResultRow[])\n : []),\n ['Redirect URL', meta.callbackUrls],\n [\n 'Used by',\n `provided agents whose template says connections.${connection.slug}.owner: \"source\", in every team`,\n ],\n ];\n return [\n ctx.ui.result({\n title: `${connection.name} — Source connection (one for every team's provided agents)`,\n rows,\n }),\n ...(connection.connected\n ? []\n : [\n ctx.ui.hint(\n `Run \"ekanos apps connect ${connection.slug}\" in your terminal to connect it.`,\n ),\n ]),\n ].join('\\n');\n}\n\nasync function openClient(ctx: CliContext, args: AppsArgs) {\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const resolved = await resolveSourceTarget(env, requireSession(env), args);\n return {\n env,\n client: new AppsClient(env, resolved.session),\n source: resolved.source,\n };\n}\n\nclass AppsClient {\n constructor(\n private readonly env: AuthEnvironment,\n private session: StoredSession,\n ) {}\n\n async call<T>(\n send: (accessToken: string) => Promise<AppsApiResult<T>>,\n ): Promise<T> {\n let result = await send(this.session.accessToken);\n if (result.status === 'unauthorized') {\n this.session = await refreshStoredSession(this.env, this.session);\n result = await send(this.session.accessToken);\n }\n if (result.status === 'ok') return result.data;\n throw authRequiredError(\n `The session for ${this.env.host} could not authorize the apps call.`,\n loginHint(this.env),\n );\n }\n\n /** As `call`, for the connections client, whose 409s are answers. */\n async connection<T>(\n send: (accessToken: string) => Promise<ConnectionsApiResult<T>>,\n ): Promise<Exclude<ConnectionsApiResult<T>, { status: 'unauthorized' }>> {\n let result = await send(this.session.accessToken);\n if (result.status === 'unauthorized') {\n this.session = await refreshStoredSession(this.env, this.session);\n result = await send(this.session.accessToken);\n }\n if (result.status !== 'unauthorized') return result;\n throw authRequiredError(\n `The session for ${this.env.host} could not authorize the connections call.`,\n loginHint(this.env),\n );\n }\n}\n\nfunction canPrompt(ctx: CliContext, args: AppsArgs): boolean {\n return !ctx.jsonMode && (args.stdinIsTTY ?? process.stdin.isTTY === true);\n}\n\nfunction parseSubcommand(value: string | undefined): AppsSubcommand {\n const match = APPS_SUBCOMMANDS.find((name) => name === value);\n if (match) return match;\n throw usageError(\n value ? `Unknown apps subcommand \"${value}\".` : 'apps needs a subcommand.',\n `Run one of: ${APPS_SUBCOMMANDS.map((name) => `ekanos apps ${name} <product>`).join(', ')}.`,\n );\n}\n\nfunction requireProduct(value: string | undefined, verb: string): string {\n const slug = value?.trim().toLowerCase();\n if (slug && /^[a-z0-9][a-z0-9-]*$/.test(slug)) return slug;\n throw usageError(\n value\n ? `\"${value}\" is not a product slug.`\n : `apps ${verb} needs a product.`,\n `Pass the product's slug, e.g. \"ekanos apps ${verb} linear\". \"ekanos catalog\" lists them.`,\n );\n}\n\nexport async function promptLine(question: string): Promise<string> {\n const readline = await import('node:readline/promises');\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n try {\n return await rl.question(question);\n } finally {\n rl.close();\n }\n}\n\n/**\n * Read a line without echoing it: the secret never appears on screen or in\n * scrollback. The question is always printed; only the typed characters are\n * hidden (each shows as `*`, so a paste visibly landed).\n *\n * Raw mode by hand rather than readline: a terminal readline redraws its\n * line on `question()` — cursor to column 0, clear to the end of the screen —\n * which erased the question written before it, so the terminal sat on an\n * empty line and a hidden field looked skipped.\n */\nexport async function promptHidden(question: string): Promise<string> {\n const stdin = process.stdin;\n const stderr = process.stderr;\n stderr.write(question);\n\n if (!stdin.isTTY) {\n // Piped stdin echoes nothing: read one line as is.\n const readline = await import('node:readline/promises');\n const rl = readline.createInterface({ input: stdin, terminal: false });\n try {\n return await rl.question('');\n } finally {\n rl.close();\n stderr.write('\\n');\n }\n }\n\n return new Promise<string>((resolve) => {\n let value = '';\n let inEscape = false;\n const wasRaw = stdin.isRaw;\n const finish = () => {\n stdin.off('data', onData);\n stdin.setRawMode(wasRaw);\n stdin.pause();\n stderr.write('\\n');\n };\n const onData = (chunk: Buffer | string) => {\n for (const char of typeof chunk === 'string'\n ? chunk\n : chunk.toString('utf8')) {\n if (inEscape) {\n // An escape sequence (an arrow key) ends at its final letter.\n if (/[A-Za-z~]/.test(char)) inEscape = false;\n continue;\n }\n if (char === '\\u001b') {\n inEscape = true;\n continue;\n }\n if (char === '\\r' || char === '\\n' || char === '\\u0004') {\n finish();\n resolve(value);\n return;\n }\n if (char === '\\u0003') {\n // Ctrl-C: raw mode swallowed the signal, so leave as SIGINT would.\n finish();\n process.exit(130);\n }\n if (char === '\\u007f' || char === '\\b') {\n if (value.length > 0) {\n value = value.slice(0, -1);\n stderr.write('\\b \\b');\n }\n continue;\n }\n if (char === '\\u0015') {\n // Ctrl-U: clear what was typed.\n stderr.write('\\b \\b'.repeat(value.length));\n value = '';\n continue;\n }\n if (char < ' ') continue;\n value += char;\n stderr.write('*');\n }\n };\n stdin.setRawMode(true);\n stdin.resume();\n stdin.on('data', onData);\n });\n}\n\n/** Each credential's state: the client id's value, the secret as saved or not. */\nfunction providerFieldRows(status: ProviderAppStatus): ResultRow[] {\n return (status.fields ?? []).map((field) => [\n field.label,\n !field.set\n ? 'not set'\n : field.sensitive\n ? 'saved'\n : (field.value ?? 'saved'),\n ]);\n}\n\n/** Every redirect URI to register; an older host sends only the one. */\nfunction callbackUrls(status: ProviderAppStatus): string[] {\n return status.callbackUrls?.length\n ? status.callbackUrls\n : [status.callbackUrl];\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { loginHint } from '../auth/host-trust.js';
1
2
  import { refreshStoredSession, requireSession, resolveAuthEnvironment, } from '../auth/session.js';
2
3
  import { fetchSourceCatalog, } from '../catalog-api.js';
3
4
  import { authRequiredError } from '../errors.js';
@@ -18,7 +19,7 @@ export async function runCatalog(ctx, args) {
18
19
  const env = resolveAuthEnvironment(ctx, args.host, args.env, {
19
20
  projectDir: args.dir,
20
21
  });
21
- let session = requireSession(env.store, env.host);
22
+ let session = requireSession(env);
22
23
  const resolved = await resolveSourceTarget(env, session, args);
23
24
  session = resolved.session;
24
25
  const query = { source: resolved.source, product: args.product };
@@ -27,20 +28,20 @@ export async function runCatalog(ctx, args) {
27
28
  session = await refreshStoredSession(env, session);
28
29
  result = await fetchSourceCatalog(env.host, session.accessToken, query);
29
30
  }
30
- const catalog = requireCatalog(result, env.host);
31
+ const catalog = requireCatalog(result, env);
31
32
  return ctx.succeed(Object.assign({ host: env.host }, catalog), withDocsHint(ctx.ui, args.dir, args.product
32
33
  ? productDetail(ctx.ui, catalog.products[0])
33
34
  : catalogSummary(ctx.ui, catalog)));
34
35
  }
35
- function requireCatalog(result, host) {
36
+ function requireCatalog(result, env) {
36
37
  if (result.status === 'ok')
37
38
  return result.catalog;
38
- throw authRequiredError(`The session for ${host} could not authorize the catalog read.`, `Run "ekanos login --host ${host}" and retry.`);
39
+ throw authRequiredError(`The session for ${env.host} could not authorize the catalog read.`, loginHint(env));
39
40
  }
40
41
  const AVAILABILITY_LABEL = {
41
42
  enabled: 'Enabled on this Source',
42
- 'turned-off': 'Granted but switched off',
43
- available: 'Available — ask Ekanos to enable',
43
+ 'turned-off': 'Not enabled — granted, but switched off',
44
+ available: 'Not enabled — only a super-admin enables it',
44
45
  };
45
46
  function catalogSummary(ui, catalog) {
46
47
  const blocks = ['enabled', 'turned-off', 'available']
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/commands/catalog.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CatalogProduct, SourceCatalog } from '@ekanos/integration-schema';\n\nimport {\n refreshStoredSession,\n requireSession,\n resolveAuthEnvironment,\n} from '../auth/session';\nimport {\n type FetchSourceCatalogResult,\n fetchSourceCatalog,\n} from '../catalog-api';\nimport type { CliContext } from '../context';\nimport { authRequiredError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { resolveSourceTarget } from '../source-target';\nimport { type Ui, pluralize } from '../ui';\nimport { withDocsHint } from './agents-init';\n\nexport interface CatalogArgs {\n host?: string;\n source?: string;\n /** One product's detail, when given. */\n product?: string;\n dir: string;\n env: Record<string, string | undefined>;\n}\n\n/**\n * `catalog` — what the Source can already do (plan 239.0). Lists every\n * product the Source can use, with its tools, agent events and the steps\n * left to set it up; `ekanos catalog <product>` shows one in full.\n *\n * Read before building: an agent migration asks it first, so a capability\n * the Source already has is set up rather than rebuilt. Works outside a\n * project — the Source comes from `--source`, else `ekanos.json`, else the\n * caller's only seat.\n */\nexport async function runCatalog(\n ctx: CliContext,\n args: CatalogArgs,\n): Promise<ExitCode> {\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n let session = requireSession(env.store, env.host);\n\n const resolved = await resolveSourceTarget(env, session, args);\n session = resolved.session;\n\n const query = { source: resolved.source, product: args.product };\n let result = await fetchSourceCatalog(env.host, session.accessToken, query);\n if (result.status === 'unauthorized') {\n session = await refreshStoredSession(env, session);\n result = await fetchSourceCatalog(env.host, session.accessToken, query);\n }\n const catalog = requireCatalog(result, env.host);\n\n return ctx.succeed(\n { host: env.host, ...catalog },\n withDocsHint(\n ctx.ui,\n args.dir,\n args.product\n ? productDetail(ctx.ui, catalog.products[0]!)\n : catalogSummary(ctx.ui, catalog),\n ),\n );\n}\n\nfunction requireCatalog(\n result: FetchSourceCatalogResult,\n host: string,\n): SourceCatalog {\n if (result.status === 'ok') return result.catalog;\n throw authRequiredError(\n `The session for ${host} could not authorize the catalog read.`,\n `Run \"ekanos login --host ${host}\" and retry.`,\n );\n}\n\nconst AVAILABILITY_LABEL = {\n enabled: 'Enabled on this Source',\n 'turned-off': 'Granted but switched off',\n available: 'Available — ask Ekanos to enable',\n} as const;\n\nfunction catalogSummary(ui: Ui, catalog: SourceCatalog): string {\n const blocks = (['enabled', 'turned-off', 'available'] as const)\n .map((availability) => {\n const products = catalog.products.filter(\n (product) => product.availability === availability,\n );\n if (products.length === 0) return null;\n return ui.result({\n title: `${AVAILABILITY_LABEL[availability]} (${products.length})`,\n tone: availability === 'enabled' ? 'ok' : 'warn',\n rows: products.map((product): [string, string] => [\n product.slug,\n [product.name, describeShape(product), openSteps(product)]\n .filter(Boolean)\n .join(' · '),\n ]),\n });\n })\n .filter((block): block is string => block !== null);\n\n return [\n ...blocks,\n ui.hint(\n `${pluralize(catalog.products.length, 'product')} on ${catalog.source.slug}. ` +\n `\"ekanos catalog <product>\" shows tools, agent events and setup steps.`,\n ),\n ].join('\\n\\n');\n}\n\nfunction productDetail(ui: Ui, product: CatalogProduct): string {\n const rows: [string, string | string[]][] = [\n ['What', product.summary ?? '—'],\n [\n 'Kind',\n product.kind === 'experience' ? 'Ekanos Experience' : 'Integration',\n ],\n ['Status', AVAILABILITY_LABEL[product.availability]],\n ];\n if (product.connectedTeams !== null) {\n rows.push(['Teams connected', String(product.connectedTeams)]);\n }\n if (product.tools.length > 0) {\n rows.push([\n 'Tools',\n product.tools.map(\n (tool) =>\n `${tool.name} (${tool.effect}${tool.sensitivity === 'undeclared' ? '' : `, ${tool.sensitivity}`})`,\n ),\n ]);\n }\n if (product.agentEvents.length > 0) {\n rows.push([\n 'Agent triggers',\n product.agentEvents.map((event) => `${event.id} — ${event.label}`),\n ]);\n }\n if (product.agentReplyTool) {\n rows.push(['Replies with', product.agentReplyTool]);\n }\n rows.push([\n 'Setup',\n product.setupSteps.flatMap((step, index) => [\n `${index + 1}. [${step.state}] ${step.title} (${step.actor}) — ${step.detail}` +\n (step.guideUrl ? ` ${step.guideUrl}` : ''),\n ...(step.consoleUrl ? [` Open ${step.consoleUrl}`] : []),\n ...(step.instructions ?? []).map(\n (line, lineIndex) =>\n ` ${String.fromCharCode(97 + lineIndex)}. ${line}`,\n ),\n ]),\n ]);\n\n return ui.result({ title: `${product.name} (${product.slug})`, rows });\n}\n\nfunction describeShape(product: CatalogProduct): string {\n const parts = [\n product.tools.length > 0 ? pluralize(product.tools.length, 'tool') : null,\n product.agentEvents.length > 0\n ? pluralize(product.agentEvents.length, 'agent trigger')\n : null,\n ].filter(Boolean);\n return parts.join(', ');\n}\n\nfunction openSteps(product: CatalogProduct): string {\n const open = product.setupSteps.filter((step) => step.state === 'todo');\n return open.length === 0 ? '' : `${pluralize(open.length, 'step')} left`;\n}\n"]}
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/commands/catalog.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CatalogProduct, SourceCatalog } from '@ekanos/integration-schema';\n\nimport { loginHint } from '../auth/host-trust';\nimport {\n type AuthEnvironment,\n refreshStoredSession,\n requireSession,\n resolveAuthEnvironment,\n} from '../auth/session';\nimport {\n type FetchSourceCatalogResult,\n fetchSourceCatalog,\n} from '../catalog-api';\nimport type { CliContext } from '../context';\nimport { authRequiredError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { resolveSourceTarget } from '../source-target';\nimport { type Ui, pluralize } from '../ui';\nimport { withDocsHint } from './agents-init';\n\nexport interface CatalogArgs {\n host?: string;\n source?: string;\n /** One product's detail, when given. */\n product?: string;\n dir: string;\n env: Record<string, string | undefined>;\n}\n\n/**\n * `catalog` — what the Source can already do (plan 239.0). Lists every\n * product the Source can use, with its tools, agent events and the steps\n * left to set it up; `ekanos catalog <product>` shows one in full.\n *\n * Read before building: an agent migration asks it first, so a capability\n * the Source already has is set up rather than rebuilt. Works outside a\n * project — the Source comes from `--source`, else `ekanos.json`, else the\n * caller's only seat.\n */\nexport async function runCatalog(\n ctx: CliContext,\n args: CatalogArgs,\n): Promise<ExitCode> {\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n let session = requireSession(env);\n\n const resolved = await resolveSourceTarget(env, session, args);\n session = resolved.session;\n\n const query = { source: resolved.source, product: args.product };\n let result = await fetchSourceCatalog(env.host, session.accessToken, query);\n if (result.status === 'unauthorized') {\n session = await refreshStoredSession(env, session);\n result = await fetchSourceCatalog(env.host, session.accessToken, query);\n }\n const catalog = requireCatalog(result, env);\n\n return ctx.succeed(\n { host: env.host, ...catalog },\n withDocsHint(\n ctx.ui,\n args.dir,\n args.product\n ? productDetail(ctx.ui, catalog.products[0]!)\n : catalogSummary(ctx.ui, catalog),\n ),\n );\n}\n\nfunction requireCatalog(\n result: FetchSourceCatalogResult,\n env: AuthEnvironment,\n): SourceCatalog {\n if (result.status === 'ok') return result.catalog;\n throw authRequiredError(\n `The session for ${env.host} could not authorize the catalog read.`,\n loginHint(env),\n );\n}\n\nconst AVAILABILITY_LABEL = {\n enabled: 'Enabled on this Source',\n 'turned-off': 'Not enabled — granted, but switched off',\n available: 'Not enabled — only a super-admin enables it',\n} as const;\n\nfunction catalogSummary(ui: Ui, catalog: SourceCatalog): string {\n const blocks = (['enabled', 'turned-off', 'available'] as const)\n .map((availability) => {\n const products = catalog.products.filter(\n (product) => product.availability === availability,\n );\n if (products.length === 0) return null;\n return ui.result({\n title: `${AVAILABILITY_LABEL[availability]} (${products.length})`,\n tone: availability === 'enabled' ? 'ok' : 'warn',\n rows: products.map((product): [string, string] => [\n product.slug,\n [product.name, describeShape(product), openSteps(product)]\n .filter(Boolean)\n .join(' · '),\n ]),\n });\n })\n .filter((block): block is string => block !== null);\n\n return [\n ...blocks,\n ui.hint(\n `${pluralize(catalog.products.length, 'product')} on ${catalog.source.slug}. ` +\n `\"ekanos catalog <product>\" shows tools, agent events and setup steps.`,\n ),\n ].join('\\n\\n');\n}\n\nfunction productDetail(ui: Ui, product: CatalogProduct): string {\n const rows: [string, string | string[]][] = [\n ['What', product.summary ?? '—'],\n [\n 'Kind',\n product.kind === 'experience' ? 'Ekanos Experience' : 'Integration',\n ],\n ['Status', AVAILABILITY_LABEL[product.availability]],\n ];\n if (product.connectedTeams !== null) {\n rows.push(['Teams connected', String(product.connectedTeams)]);\n }\n if (product.tools.length > 0) {\n rows.push([\n 'Tools',\n product.tools.map(\n (tool) =>\n `${tool.name} (${tool.effect}${tool.sensitivity === 'undeclared' ? '' : `, ${tool.sensitivity}`})`,\n ),\n ]);\n }\n if (product.agentEvents.length > 0) {\n rows.push([\n 'Agent triggers',\n product.agentEvents.map((event) => `${event.id} — ${event.label}`),\n ]);\n }\n if (product.agentReplyTool) {\n rows.push(['Replies with', product.agentReplyTool]);\n }\n rows.push([\n 'Setup',\n product.setupSteps.flatMap((step, index) => [\n `${index + 1}. [${step.state}] ${step.title} (${step.actor}) — ${step.detail}` +\n (step.guideUrl ? ` ${step.guideUrl}` : ''),\n ...(step.consoleUrl ? [` Open ${step.consoleUrl}`] : []),\n ...(step.instructions ?? []).map(\n (line, lineIndex) =>\n ` ${String.fromCharCode(97 + lineIndex)}. ${line}`,\n ),\n ]),\n ]);\n\n return ui.result({ title: `${product.name} (${product.slug})`, rows });\n}\n\nfunction describeShape(product: CatalogProduct): string {\n const parts = [\n product.tools.length > 0 ? pluralize(product.tools.length, 'tool') : null,\n product.agentEvents.length > 0\n ? pluralize(product.agentEvents.length, 'agent trigger')\n : null,\n ].filter(Boolean);\n return parts.join(', ');\n}\n\nfunction openSteps(product: CatalogProduct): string {\n const open = product.setupSteps.filter((step) => step.state === 'todo');\n return open.length === 0 ? '' : `${pluralize(open.length, 'step')} left`;\n}\n"]}