@ekanos/cli 0.14.0 → 0.16.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 (115) hide show
  1. package/README.md +41 -4
  2. package/dist/auth/ekanos-api.d.ts +23 -0
  3. package/dist/auth/ekanos-api.js +33 -6
  4. package/dist/auth/ekanos-api.js.map +1 -1
  5. package/dist/commands/agents.d.ts +2 -2
  6. package/dist/commands/agents.js +14 -20
  7. package/dist/commands/agents.js.map +1 -1
  8. package/dist/commands/apps.d.ts +11 -3
  9. package/dist/commands/apps.js +86 -28
  10. package/dist/commands/apps.js.map +1 -1
  11. package/dist/commands/catalog.d.ts +4 -2
  12. package/dist/commands/catalog.js +166 -35
  13. package/dist/commands/catalog.js.map +1 -1
  14. package/dist/commands/login.d.ts +2 -0
  15. package/dist/commands/login.js +17 -0
  16. package/dist/commands/login.js.map +1 -1
  17. package/dist/commands/runs.d.ts +7 -3
  18. package/dist/commands/runs.js +24 -6
  19. package/dist/commands/runs.js.map +1 -1
  20. package/dist/commands/scope-notice.d.ts +7 -0
  21. package/dist/commands/scope-notice.js +4 -11
  22. package/dist/commands/scope-notice.js.map +1 -1
  23. package/dist/commands/sources-roles.d.ts +5 -0
  24. package/dist/commands/sources-roles.js +235 -0
  25. package/dist/commands/sources-roles.js.map +1 -0
  26. package/dist/commands/sources.d.ts +5 -0
  27. package/dist/commands/sources.js +6 -1
  28. package/dist/commands/sources.js.map +1 -1
  29. package/dist/commands/team-agent-readiness.d.ts +23 -17
  30. package/dist/commands/team-agent-readiness.js +57 -90
  31. package/dist/commands/team-agent-readiness.js.map +1 -1
  32. package/dist/commands/team-agents-agents.d.ts +8 -5
  33. package/dist/commands/team-agents-agents.js +173 -58
  34. package/dist/commands/team-agents-agents.js.map +1 -1
  35. package/dist/commands/team-agents-define.d.ts +31 -0
  36. package/dist/commands/team-agents-define.js +176 -0
  37. package/dist/commands/team-agents-define.js.map +1 -0
  38. package/dist/commands/team-agents-mcp.js +112 -10
  39. package/dist/commands/team-agents-mcp.js.map +1 -1
  40. package/dist/commands/team-agents-triggers.d.ts +1 -1
  41. package/dist/commands/team-agents-triggers.js +137 -5
  42. package/dist/commands/team-agents-triggers.js.map +1 -1
  43. package/dist/commands/team-agents.d.ts +4 -1
  44. package/dist/commands/team-agents.js +17 -4
  45. package/dist/commands/team-agents.js.map +1 -1
  46. package/dist/commands/team-llm-key.d.ts +14 -0
  47. package/dist/commands/team-llm-key.js +122 -0
  48. package/dist/commands/team-llm-key.js.map +1 -0
  49. package/dist/commands/teams-connect.js +123 -31
  50. package/dist/commands/teams-connect.js.map +1 -1
  51. package/dist/commands/teams-lifecycle.d.ts +90 -0
  52. package/dist/commands/teams-lifecycle.js +457 -0
  53. package/dist/commands/teams-lifecycle.js.map +1 -0
  54. package/dist/commands/teams-onboard.d.ts +14 -0
  55. package/dist/commands/teams-onboard.js +62 -13
  56. package/dist/commands/teams-onboard.js.map +1 -1
  57. package/dist/commands/teams-overview.js +7 -3
  58. package/dist/commands/teams-overview.js.map +1 -1
  59. package/dist/commands/teams.d.ts +25 -5
  60. package/dist/commands/teams.js +101 -39
  61. package/dist/commands/teams.js.map +1 -1
  62. package/dist/commands/workflows.d.ts +37 -0
  63. package/dist/commands/workflows.js +589 -0
  64. package/dist/commands/workflows.js.map +1 -0
  65. package/dist/connect-fields.d.ts +22 -0
  66. package/dist/connect-fields.js +115 -0
  67. package/dist/connect-fields.js.map +1 -0
  68. package/dist/context.d.ts +12 -0
  69. package/dist/context.js +32 -9
  70. package/dist/context.js.map +1 -1
  71. package/dist/index.d.ts +13 -0
  72. package/dist/index.js +367 -133
  73. package/dist/index.js.map +1 -1
  74. package/dist/invocation.d.ts +31 -0
  75. package/dist/invocation.js +58 -0
  76. package/dist/invocation.js.map +1 -0
  77. package/dist/runs-api.js +8 -3
  78. package/dist/runs-api.js.map +1 -1
  79. package/dist/safe-fs.d.ts +18 -0
  80. package/dist/safe-fs.js +57 -0
  81. package/dist/safe-fs.js.map +1 -1
  82. package/dist/secret-form.d.ts +48 -0
  83. package/dist/secret-form.js +212 -0
  84. package/dist/secret-form.js.map +1 -0
  85. package/dist/secret-input.d.ts +96 -0
  86. package/dist/secret-input.js +299 -0
  87. package/dist/secret-input.js.map +1 -0
  88. package/dist/team-connect-api.d.ts +78 -3
  89. package/dist/team-connect-api.js +17 -2
  90. package/dist/team-connect-api.js.map +1 -1
  91. package/dist/team-lifecycle-api.d.ts +435 -0
  92. package/dist/team-lifecycle-api.js +301 -0
  93. package/dist/team-lifecycle-api.js.map +1 -0
  94. package/dist/teams-api.d.ts +13 -1
  95. package/dist/teams-api.js +90 -31
  96. package/dist/teams-api.js.map +1 -1
  97. package/dist/unknown-command.d.ts +18 -0
  98. package/dist/unknown-command.js +50 -0
  99. package/dist/unknown-command.js.map +1 -0
  100. package/dist/workflows-api.d.ts +69 -0
  101. package/dist/workflows-api.js +182 -0
  102. package/dist/workflows-api.js.map +1 -0
  103. package/package.json +3 -3
  104. package/templates/AGENTS.md.tmpl +6 -4
  105. package/templates/claude-skill.md.tmpl +4 -1
  106. package/templates/package.json.tmpl +4 -4
  107. package/templates/skills/build-agent/SKILL.md +56 -22
  108. package/templates/skills/build-agent/references/agent-json.md +4 -1
  109. package/templates/skills/build-agent/references/app-setup.md +14 -7
  110. package/templates/skills/build-agent/references/rollout.md +40 -20
  111. package/templates/skills/build-agent/references/set-up-an-integration.md +46 -29
  112. package/templates/skills/build-agent/references/triggers.md +4 -3
  113. package/templates/skills/build-integration/references/widget-design.md +1 -1
  114. package/templates/skills/ekanos-platform/SKILL.md +77 -23
  115. package/templates/skills/polish-widgets/references/patterns.md +3 -3
@@ -69,6 +69,9 @@ export async function runLogin(ctx, args) {
69
69
  ctx.log(ctx.ui.dim('The stored session has expired. Starting a new login…'));
70
70
  }
71
71
  }
72
+ // Name the host before anything is sent to it, whichever source chose it —
73
+ // above all the sole stored host, which no flag on this command line named.
74
+ ctx.log(loggingInLine(ctx, env));
72
75
  const config = await fetchCliAuthConfig(env.host);
73
76
  await confirmNewHost(ctx, args, env, config.auth0Domain);
74
77
  const authorization = await startDeviceAuthorization(config);
@@ -78,6 +81,7 @@ export async function runLogin(ctx, args) {
78
81
  if (authorization.verificationUriComplete) {
79
82
  noteLines.push(`(without the pre-filled code: ${authorization.verificationUri})`);
80
83
  }
84
+ noteLines.push('', BROWSER_ERROR_LINE);
81
85
  wizard.note(noteLines.join('\n'), 'Device login');
82
86
  }
83
87
  else {
@@ -89,6 +93,7 @@ export async function runLogin(ctx, args) {
89
93
  }
90
94
  ctx.log('');
91
95
  ctx.log('Waiting for approval…');
96
+ ctx.log(BROWSER_ERROR_LINE);
92
97
  }
93
98
  const spinner = useWizard ? wizard.spinner() : null;
94
99
  spinner === null || spinner === void 0 ? void 0 : spinner.start('Waiting for approval…');
@@ -135,6 +140,18 @@ export async function runLogin(ctx, args) {
135
140
  ],
136
141
  }));
137
142
  }
143
+ /** Printed while the device flow waits: the way out of a dead browser page. */
144
+ export const BROWSER_ERROR_LINE = 'If the browser page shows an error, press Ctrl-C and run `ekanos login` again.';
145
+ /** "Logging in to <host>", with where the host came from when no flag named it. */
146
+ function loggingInLine(ctx, env) {
147
+ const origin = env.hostOrigin === 'stored'
148
+ ? ' — the only host you are logged in to. Pass --host to log in to another.'
149
+ : env.hostOrigin === 'env'
150
+ ? ' — from EKANOS_HOST.'
151
+ : '.';
152
+ const line = `Logging in to ${env.host}${origin}`;
153
+ return ctx.jsonMode ? `ekanos: ${line}` : ctx.ui.dim(line);
154
+ }
138
155
  /**
139
156
  * A login sends the Auth0 access token, and later the refresh token, to the
140
157
  * host. A hostile host can return Ekanos's real Auth0 domain and client id,
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StoredSession } from '../auth/credential-store';\nimport {\n pollForDeviceTokens,\n startDeviceAuthorization,\n} from '../auth/device-flow';\nimport { createEkanosSession, fetchCliAuthConfig } from '../auth/ekanos-api';\nimport { isKnownHost } from '../auth/host-trust';\nimport {\n type AuthEnvironment,\n resolveAuthEnvironment,\n resolveIdentity,\n} from '../auth/session';\nimport { printBanner } from '../banner';\nimport { claudeDocsRow, offerDocsToClaude } from '../claude-docs';\nimport type { CliContext } from '../context';\nimport { CliError, invalidStateError, validationError } from '../errors';\nimport { ERROR_CODES } from '../exit-codes';\nimport type { ExitCode } from '../exit-codes';\nimport { shortHost } from '../ui';\nimport { canWizard, wizard } from '../wizard';\nimport { promptYesNo } from './publish';\n\nexport interface LoginArgs {\n host?: string;\n /** Start a new browser login even if a working session is already stored. */\n force: boolean;\n /** Where a project's ekanos.json may sit — read-only here, never written. */\n cwd: string;\n env: Record<string, string | undefined>;\n /**\n * Test-only override for the clack wizard gate (`canWizard` in\n * `wizard.ts`) — never set from real CLI wiring. See `RunOptions` in\n * `index.ts`.\n */\n stdinIsTTY?: boolean;\n /** `--claude` adds the Ekanos docs to Claude Code without asking; `--no-claude` skips the offer. */\n claude?: boolean;\n /** Test seam for the Claude Code offer's question. */\n confirm?: (question: string) => Promise<boolean>;\n /** `--trust-host`: sign in to a host you have never used without the question. */\n trustHost?: boolean;\n /** Test seam for the new-host question. */\n confirmHost?: (question: string) => Promise<boolean>;\n}\n\n/**\n * `login` — authenticate this machine against an Ekanos deployment via the\n * Auth0 device authorization flow.\n *\n * Idempotent: with a stored session that still authenticates, it reports that\n * and exits 0 without opening a browser. `--force` skips the check.\n *\n * The user code and verification URL go to STDERR. They have to be visible\n * even when stdout is a pipe into an agent, and stdout in this CLI carries\n * exactly one JSON object.\n *\n * In human mode at a real TTY (`canWizard`), this runs behind a clack\n * `intro`/`outro` flow with a spinner over the approval wait — see\n * `wizard.ts`. The device code and URL themselves stay plain, copy-pasteable\n * text (a clack `note`, not a prompt) either way: a partner needs to select\n * and open them, not interact with them through clack. JSON mode and human\n * non-TTY mode are byte-for-byte what they were before this existed.\n */\nexport async function runLogin(\n ctx: CliContext,\n args: LoginArgs,\n): Promise<ExitCode> {\n // No `projectDir`: login is the one verb that CREATES credentials, so its\n // host must come from something the developer chose (--host, EKANOS_HOST)\n // or already trusts (the sole stored login) — never from a committed\n // ekanos.json, which an attacker can set in any cloned repo to point the\n // device flow at their own tenant. Every other verb may read the project\n // host because their bearer tokens are looked up per-host from the store:\n // an unfamiliar host simply has no session to present.\n const env = resolveAuthEnvironment(ctx, args.host, args.env);\n\n const useWizard = canWizard(ctx, { stdinIsTTY: args.stdinIsTTY });\n if (useWizard) wizard.intro('ekanos login');\n\n if (!args.force) {\n const existing = env.store.read(env.host);\n\n if (existing) {\n const reusable = await tryReuse(env, existing);\n\n if (reusable) {\n printBanner(ctx);\n\n const email = reusable.user.email ?? reusable.user.id;\n if (useWizard) {\n wizard.outro(\n `Already signed in as ${email} on ${shortHost(env.host)}.`,\n );\n }\n\n return ctx.succeed(\n {\n host: env.host,\n status: 'already-authenticated',\n user: reusable.user,\n expiresAt: reusable.expiresAt,\n credentialsPath: env.store.filePath,\n },\n useWizard\n ? ''\n : ctx.ui.result({\n title: 'Already signed in',\n rows: [\n ['Account', email],\n ['Host', shortHost(env.host)],\n ],\n }),\n );\n }\n\n ctx.log(\n ctx.ui.dim('The stored session has expired. Starting a new login…'),\n );\n }\n }\n\n const config = await fetchCliAuthConfig(env.host);\n await confirmNewHost(ctx, args, env, config.auth0Domain);\n const authorization = await startDeviceAuthorization(config);\n const openUrl =\n authorization.verificationUriComplete ?? authorization.verificationUri;\n\n if (useWizard) {\n const noteLines = [`Open: ${openUrl}`, `Code: ${authorization.userCode}`];\n if (authorization.verificationUriComplete) {\n noteLines.push(\n `(without the pre-filled code: ${authorization.verificationUri})`,\n );\n }\n wizard.note(noteLines.join('\\n'), 'Device login');\n } else {\n ctx.log('');\n ctx.log(` Open: ${openUrl}`);\n ctx.log(` Code: ${authorization.userCode}`);\n\n if (authorization.verificationUriComplete) {\n ctx.log(\n ` (without the pre-filled code: ${authorization.verificationUri})`,\n );\n }\n\n ctx.log('');\n ctx.log('Waiting for approval…');\n }\n\n const spinner = useWizard ? wizard.spinner() : null;\n spinner?.start('Waiting for approval…');\n\n const tokens = await pollForDeviceTokens(config, authorization);\n const session = await createEkanosSession(env.host, tokens.accessToken);\n\n spinner?.stop(`✓ authenticated as ${session.email ?? session.userId}`);\n\n const stored: StoredSession = {\n auth0RefreshToken: tokens.refreshToken,\n accessToken: session.accessToken,\n expiresAt: session.expiresAt,\n userId: session.userId,\n email: session.email,\n updatedAt: new Date().toISOString(),\n };\n\n env.store.write(env.host, stored);\n\n // A first sign-in is when a developer is setting up: offer the docs to\n // Claude Code once, so it can look Ekanos up instead of guessing.\n const claudeDocs = await offerDocsToClaude({\n choice: args.claude,\n canPrompt:\n !ctx.jsonMode && (args.stdinIsTTY ?? process.stdin.isTTY === true),\n confirm: args.confirm ?? promptYesNo,\n env: args.env,\n });\n const claudeRow = claudeDocsRow(claudeDocs);\n\n printBanner(ctx);\n\n if (useWizard) {\n wizard.outro(\n `Signed in as ${session.email ?? session.userId} on ${shortHost(env.host)}.`,\n );\n }\n\n return ctx.succeed(\n {\n host: env.host,\n status: 'authenticated',\n user: { id: session.userId, email: session.email },\n expiresAt: session.expiresAt,\n credentialsPath: env.store.filePath,\n claudeDocs,\n },\n useWizard\n ? ''\n : ctx.ui.result({\n title: 'Signed in',\n rows: [\n ['Account', session.email ?? session.userId],\n ['Host', shortHost(env.host)],\n ...(claudeRow ? [claudeRow] : []),\n ],\n }),\n );\n}\n\n/**\n * A login sends the Auth0 access token, and later the refresh token, to the\n * host. A hostile host can return Ekanos's real Auth0 domain and client id,\n * so the browser step looks genuine and proves nothing about the host. So a\n * host that is neither stored nor a known Ekanos host is shown, with the\n * Auth0 domain it named, and asked about; with nobody to ask (JSON mode, an\n * agent, no TTY) it needs `--trust-host`.\n */\nasync function confirmNewHost(\n ctx: CliContext,\n args: LoginArgs,\n env: AuthEnvironment,\n auth0Domain: string,\n): Promise<void> {\n if (args.trustHost || isKnownHost(env.store, env.host)) return;\n\n const canPrompt =\n !ctx.jsonMode && (args.stdinIsTTY ?? process.stdin.isTTY === true);\n\n if (!canPrompt) {\n throw invalidStateError(\n `${env.host} is not a host you have logged in to before, and it ` +\n `signs in through ${auth0Domain}. A login sends your credentials there.`,\n `Check with the person you work for that ${env.host} is their Ekanos ` +\n `deployment. If it is, re-run: ekanos login --host ${env.host} --trust-host`,\n );\n }\n\n ctx.log(` Host: ${env.host}`);\n ctx.log(` Sign-in: ${auth0Domain}`);\n\n const sure = await (args.confirmHost ?? promptYesNo)(\n `You have never logged in to ${env.host}. Send your credentials there? [y/N]`,\n );\n\n if (!sure) {\n throw validationError(\n 'Nothing was changed.',\n `Check the host is the Ekanos deployment you meant, then run ` +\n `\"ekanos login --host <url>\" again.`,\n );\n }\n}\n\n/**\n * Probe a stored session. Returns null when it cannot be revived, so `login`\n * falls through to a fresh device flow rather than failing — \"log in again\"\n * is the whole point of the command being run.\n *\n * Only auth failures are absorbed. A network or configuration error still\n * propagates: silently starting a browser login because the host was\n * unreachable would be the wrong recovery, and would hide the real fault.\n */\nasync function tryReuse(\n env: ReturnType<typeof resolveAuthEnvironment>,\n existing: StoredSession,\n): Promise<{\n user: { id: string; email: string | null };\n expiresAt: string;\n} | null> {\n try {\n const { identity, session } = await resolveIdentity(env, existing);\n\n return {\n user: { id: identity.id, email: identity.email },\n expiresAt: session.expiresAt,\n };\n } catch (error) {\n if (isAuthFailure(error)) {\n return null;\n }\n\n throw error;\n }\n}\n\nfunction isAuthFailure(error: unknown): boolean {\n return error instanceof CliError && error.code === ERROR_CODES.AUTH_REQUIRED;\n}\n"]}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StoredSession } from '../auth/credential-store';\nimport {\n pollForDeviceTokens,\n startDeviceAuthorization,\n} from '../auth/device-flow';\nimport { createEkanosSession, fetchCliAuthConfig } from '../auth/ekanos-api';\nimport { isKnownHost } from '../auth/host-trust';\nimport {\n type AuthEnvironment,\n resolveAuthEnvironment,\n resolveIdentity,\n} from '../auth/session';\nimport { printBanner } from '../banner';\nimport { claudeDocsRow, offerDocsToClaude } from '../claude-docs';\nimport type { CliContext } from '../context';\nimport { CliError, invalidStateError, validationError } from '../errors';\nimport { ERROR_CODES } from '../exit-codes';\nimport type { ExitCode } from '../exit-codes';\nimport { shortHost } from '../ui';\nimport { canWizard, wizard } from '../wizard';\nimport { promptYesNo } from './publish';\n\nexport interface LoginArgs {\n host?: string;\n /** Start a new browser login even if a working session is already stored. */\n force: boolean;\n /** Where a project's ekanos.json may sit — read-only here, never written. */\n cwd: string;\n env: Record<string, string | undefined>;\n /**\n * Test-only override for the clack wizard gate (`canWizard` in\n * `wizard.ts`) — never set from real CLI wiring. See `RunOptions` in\n * `index.ts`.\n */\n stdinIsTTY?: boolean;\n /** `--claude` adds the Ekanos docs to Claude Code without asking; `--no-claude` skips the offer. */\n claude?: boolean;\n /** Test seam for the Claude Code offer's question. */\n confirm?: (question: string) => Promise<boolean>;\n /** `--trust-host`: sign in to a host you have never used without the question. */\n trustHost?: boolean;\n /** Test seam for the new-host question. */\n confirmHost?: (question: string) => Promise<boolean>;\n}\n\n/**\n * `login` — authenticate this machine against an Ekanos deployment via the\n * Auth0 device authorization flow.\n *\n * Idempotent: with a stored session that still authenticates, it reports that\n * and exits 0 without opening a browser. `--force` skips the check.\n *\n * The user code and verification URL go to STDERR. They have to be visible\n * even when stdout is a pipe into an agent, and stdout in this CLI carries\n * exactly one JSON object.\n *\n * In human mode at a real TTY (`canWizard`), this runs behind a clack\n * `intro`/`outro` flow with a spinner over the approval wait — see\n * `wizard.ts`. The device code and URL themselves stay plain, copy-pasteable\n * text (a clack `note`, not a prompt) either way: a partner needs to select\n * and open them, not interact with them through clack. JSON mode and human\n * non-TTY mode are byte-for-byte what they were before this existed.\n */\nexport async function runLogin(\n ctx: CliContext,\n args: LoginArgs,\n): Promise<ExitCode> {\n // No `projectDir`: login is the one verb that CREATES credentials, so its\n // host must come from something the developer chose (--host, EKANOS_HOST)\n // or already trusts (the sole stored login) — never from a committed\n // ekanos.json, which an attacker can set in any cloned repo to point the\n // device flow at their own tenant. Every other verb may read the project\n // host because their bearer tokens are looked up per-host from the store:\n // an unfamiliar host simply has no session to present.\n const env = resolveAuthEnvironment(ctx, args.host, args.env);\n\n const useWizard = canWizard(ctx, { stdinIsTTY: args.stdinIsTTY });\n if (useWizard) wizard.intro('ekanos login');\n\n if (!args.force) {\n const existing = env.store.read(env.host);\n\n if (existing) {\n const reusable = await tryReuse(env, existing);\n\n if (reusable) {\n printBanner(ctx);\n\n const email = reusable.user.email ?? reusable.user.id;\n if (useWizard) {\n wizard.outro(\n `Already signed in as ${email} on ${shortHost(env.host)}.`,\n );\n }\n\n return ctx.succeed(\n {\n host: env.host,\n status: 'already-authenticated',\n user: reusable.user,\n expiresAt: reusable.expiresAt,\n credentialsPath: env.store.filePath,\n },\n useWizard\n ? ''\n : ctx.ui.result({\n title: 'Already signed in',\n rows: [\n ['Account', email],\n ['Host', shortHost(env.host)],\n ],\n }),\n );\n }\n\n ctx.log(\n ctx.ui.dim('The stored session has expired. Starting a new login…'),\n );\n }\n }\n\n // Name the host before anything is sent to it, whichever source chose it —\n // above all the sole stored host, which no flag on this command line named.\n ctx.log(loggingInLine(ctx, env));\n\n const config = await fetchCliAuthConfig(env.host);\n await confirmNewHost(ctx, args, env, config.auth0Domain);\n const authorization = await startDeviceAuthorization(config);\n const openUrl =\n authorization.verificationUriComplete ?? authorization.verificationUri;\n\n if (useWizard) {\n const noteLines = [`Open: ${openUrl}`, `Code: ${authorization.userCode}`];\n if (authorization.verificationUriComplete) {\n noteLines.push(\n `(without the pre-filled code: ${authorization.verificationUri})`,\n );\n }\n noteLines.push('', BROWSER_ERROR_LINE);\n wizard.note(noteLines.join('\\n'), 'Device login');\n } else {\n ctx.log('');\n ctx.log(` Open: ${openUrl}`);\n ctx.log(` Code: ${authorization.userCode}`);\n\n if (authorization.verificationUriComplete) {\n ctx.log(\n ` (without the pre-filled code: ${authorization.verificationUri})`,\n );\n }\n\n ctx.log('');\n ctx.log('Waiting for approval…');\n ctx.log(BROWSER_ERROR_LINE);\n }\n\n const spinner = useWizard ? wizard.spinner() : null;\n spinner?.start('Waiting for approval…');\n\n const tokens = await pollForDeviceTokens(config, authorization);\n const session = await createEkanosSession(env.host, tokens.accessToken);\n\n spinner?.stop(`✓ authenticated as ${session.email ?? session.userId}`);\n\n const stored: StoredSession = {\n auth0RefreshToken: tokens.refreshToken,\n accessToken: session.accessToken,\n expiresAt: session.expiresAt,\n userId: session.userId,\n email: session.email,\n updatedAt: new Date().toISOString(),\n };\n\n env.store.write(env.host, stored);\n\n // A first sign-in is when a developer is setting up: offer the docs to\n // Claude Code once, so it can look Ekanos up instead of guessing.\n const claudeDocs = await offerDocsToClaude({\n choice: args.claude,\n canPrompt:\n !ctx.jsonMode && (args.stdinIsTTY ?? process.stdin.isTTY === true),\n confirm: args.confirm ?? promptYesNo,\n env: args.env,\n });\n const claudeRow = claudeDocsRow(claudeDocs);\n\n printBanner(ctx);\n\n if (useWizard) {\n wizard.outro(\n `Signed in as ${session.email ?? session.userId} on ${shortHost(env.host)}.`,\n );\n }\n\n return ctx.succeed(\n {\n host: env.host,\n status: 'authenticated',\n user: { id: session.userId, email: session.email },\n expiresAt: session.expiresAt,\n credentialsPath: env.store.filePath,\n claudeDocs,\n },\n useWizard\n ? ''\n : ctx.ui.result({\n title: 'Signed in',\n rows: [\n ['Account', session.email ?? session.userId],\n ['Host', shortHost(env.host)],\n ...(claudeRow ? [claudeRow] : []),\n ],\n }),\n );\n}\n\n/** Printed while the device flow waits: the way out of a dead browser page. */\nexport const BROWSER_ERROR_LINE =\n 'If the browser page shows an error, press Ctrl-C and run `ekanos login` again.';\n\n/** \"Logging in to <host>\", with where the host came from when no flag named it. */\nfunction loggingInLine(ctx: CliContext, env: AuthEnvironment): string {\n const origin =\n env.hostOrigin === 'stored'\n ? ' — the only host you are logged in to. Pass --host to log in to another.'\n : env.hostOrigin === 'env'\n ? ' — from EKANOS_HOST.'\n : '.';\n const line = `Logging in to ${env.host}${origin}`;\n\n return ctx.jsonMode ? `ekanos: ${line}` : ctx.ui.dim(line);\n}\n\n/**\n * A login sends the Auth0 access token, and later the refresh token, to the\n * host. A hostile host can return Ekanos's real Auth0 domain and client id,\n * so the browser step looks genuine and proves nothing about the host. So a\n * host that is neither stored nor a known Ekanos host is shown, with the\n * Auth0 domain it named, and asked about; with nobody to ask (JSON mode, an\n * agent, no TTY) it needs `--trust-host`.\n */\nasync function confirmNewHost(\n ctx: CliContext,\n args: LoginArgs,\n env: AuthEnvironment,\n auth0Domain: string,\n): Promise<void> {\n if (args.trustHost || isKnownHost(env.store, env.host)) return;\n\n const canPrompt =\n !ctx.jsonMode && (args.stdinIsTTY ?? process.stdin.isTTY === true);\n\n if (!canPrompt) {\n throw invalidStateError(\n `${env.host} is not a host you have logged in to before, and it ` +\n `signs in through ${auth0Domain}. A login sends your credentials there.`,\n `Check with the person you work for that ${env.host} is their Ekanos ` +\n `deployment. If it is, re-run: ekanos login --host ${env.host} --trust-host`,\n );\n }\n\n ctx.log(` Host: ${env.host}`);\n ctx.log(` Sign-in: ${auth0Domain}`);\n\n const sure = await (args.confirmHost ?? promptYesNo)(\n `You have never logged in to ${env.host}. Send your credentials there? [y/N]`,\n );\n\n if (!sure) {\n throw validationError(\n 'Nothing was changed.',\n `Check the host is the Ekanos deployment you meant, then run ` +\n `\"ekanos login --host <url>\" again.`,\n );\n }\n}\n\n/**\n * Probe a stored session. Returns null when it cannot be revived, so `login`\n * falls through to a fresh device flow rather than failing — \"log in again\"\n * is the whole point of the command being run.\n *\n * Only auth failures are absorbed. A network or configuration error still\n * propagates: silently starting a browser login because the host was\n * unreachable would be the wrong recovery, and would hide the real fault.\n */\nasync function tryReuse(\n env: ReturnType<typeof resolveAuthEnvironment>,\n existing: StoredSession,\n): Promise<{\n user: { id: string; email: string | null };\n expiresAt: string;\n} | null> {\n try {\n const { identity, session } = await resolveIdentity(env, existing);\n\n return {\n user: { id: identity.id, email: identity.email },\n expiresAt: session.expiresAt,\n };\n } catch (error) {\n if (isAuthFailure(error)) {\n return null;\n }\n\n throw error;\n }\n}\n\nfunction isAuthFailure(error: unknown): boolean {\n return error instanceof CliError && error.code === ERROR_CODES.AUTH_REQUIRED;\n}\n"]}
@@ -46,8 +46,12 @@ export declare function runAgentTest(ctx: CliContext, args: RunsArgs & {
46
46
  key: string | undefined;
47
47
  }): Promise<ExitCode>;
48
48
  /**
49
- * `approvals` — what a team's agent runs are waiting on, and deciding it.
50
- * Decided with the authority a team's agent manager has in the app, and
51
- * recorded as your decision.
49
+ * `approvals` — what a team's agent runs are waiting on, and deciding it,
50
+ * recorded as your decision. A Source admin sees and decides every one
51
+ * (a provided agent's with an agent manager's authority); any other seat
52
+ * holder sees and decides only those they may in the app — as a member who
53
+ * manages the team's agents, or reply drafts as one who reviews them or a
54
+ * reviewer the Source admin named, and a personal agent's as its creator.
55
+ * The first decision wins.
52
56
  */
53
57
  export declare function runApprovals(ctx: CliContext, args: RunsArgs): Promise<ExitCode>;
@@ -106,9 +106,13 @@ export async function runAgentTest(ctx, args) {
106
106
  return startAndReport(ctx, args, { team, agent, draft: true });
107
107
  }
108
108
  /**
109
- * `approvals` — what a team's agent runs are waiting on, and deciding it.
110
- * Decided with the authority a team's agent manager has in the app, and
111
- * recorded as your decision.
109
+ * `approvals` — what a team's agent runs are waiting on, and deciding it,
110
+ * recorded as your decision. A Source admin sees and decides every one
111
+ * (a provided agent's with an agent manager's authority); any other seat
112
+ * holder sees and decides only those they may in the app — as a member who
113
+ * manages the team's agents, or reply drafts as one who reviews them or a
114
+ * reviewer the Source admin named, and a personal agent's as its creator.
115
+ * The first decision wins.
112
116
  */
113
117
  export async function runApprovals(ctx, args) {
114
118
  const [rawSubcommand, operand, ...extra] = args.positionals;
@@ -125,10 +129,22 @@ export async function runApprovals(ctx, args) {
125
129
  rejectExtra([operand], 'approvals list');
126
130
  const { env, client, source } = await connect(ctx, args);
127
131
  const list = await client.call((token) => listApprovals(env.host, token, { source, team }));
132
+ // Not the Source's admin: only what you may decide yourself.
133
+ const yours = list.scope === 'yours';
128
134
  return ctx.succeed(Object.assign({ host: env.host }, list), list.approvals.length === 0
129
- ? ctx.ui.result({ title: `Nothing waiting on ${list.team.slug}` })
135
+ ? ctx.ui.result(Object.assign({ title: yours
136
+ ? `Nothing waiting on ${list.team.slug} that you can decide`
137
+ : `Nothing waiting on ${list.team.slug}` }, (yours
138
+ ? {
139
+ notes: [
140
+ "You see the approvals you may decide: as a member who manages the team's agents, or — reply drafts — one who reviews them or a reviewer the Source admin named; a personal agent's, as its creator.",
141
+ ],
142
+ }
143
+ : {})))
130
144
  : ctx.ui.result({
131
- title: `${list.approvals.length} waiting on ${list.team.slug}`,
145
+ title: yours
146
+ ? `${list.approvals.length} waiting on ${list.team.slug} for you to decide`
147
+ : `${list.approvals.length} waiting on ${list.team.slug}`,
132
148
  tone: 'warn',
133
149
  rows: list.approvals.map((approval) => [
134
150
  approval.id,
@@ -353,7 +369,9 @@ function approvalLines(approval) {
353
369
  return [
354
370
  `${approval.toolName} · ${agentLabel(approval.agent)}${approval.replyDraft ? ' · reply draft (editable)' : ''}`,
355
371
  `run ${approval.runId}${approval.expiresAt ? ` · expires ${approval.expiresAt}` : ''}`,
356
- clip(JSON.stringify((_a = approval.args) !== null && _a !== void 0 ? _a : null)),
372
+ approval.argsWithheld
373
+ ? "arguments withheld: the team's own agent, so only a member of the team who could decide it sees what it would do"
374
+ : clip(JSON.stringify((_a = approval.args) !== null && _a !== void 0 ? _a : null)),
357
375
  ];
358
376
  }
359
377
  function agentLabel(agent) {
@@ -1 +1 @@
1
- {"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/commands/runs.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AgentRunApproval,\n type AgentRunDetail,\n type AgentRunStartRequest,\n AgentRunStatusSchema,\n type AgentRunSummary,\n type AgentRunToolCall,\n} from '@ekanos/integration-schema';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\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 type { CliContext } from '../context';\nimport { authRequiredError, usageError, validationError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport {\n type RunsApiResult,\n cancelRun,\n decideApproval,\n listApprovals,\n listRuns,\n showRun,\n startRun,\n} from '../runs-api';\nimport { resolveSourceTarget } from '../source-target';\nimport type { ResultRow, Ui } from '../ui';\nimport { promptYesNo } from './publish';\nimport { parseSince } from './teams-events';\n\nexport const RUNS_SUBCOMMANDS = ['start', 'list', 'show', 'cancel'] as const;\nexport const APPROVALS_SUBCOMMANDS = [\n 'list',\n 'approve',\n 'reject',\n 'edit',\n] as const;\n\nconst FOLLOW_INTERVAL_MS = 2000;\nconst FOLLOW_TIMEOUT_MS = 15 * 60 * 1000;\n\nexport interface RunsArgs {\n host?: string;\n source?: string;\n positionals: readonly string[];\n team?: string;\n agent?: string;\n /** `list --status <status>` and `--since 24h|7d|<date>`. */\n status?: string;\n since?: string;\n prompt?: string;\n input?: string;\n follow: boolean;\n reason?: string;\n body?: string;\n /** `runs cancel`: confirmed up front, for a script or an agent run. */\n yes?: boolean;\n dir: string;\n env: Record<string, string | undefined>;\n /** Test seam for the `--follow` poll delay. */\n sleep?: (ms: number) => Promise<void>;\n /** Test seams for `runs cancel`'s question. */\n stdinIsTTY?: boolean;\n confirm?: (question: string) => Promise<boolean>;\n}\n\n/**\n * `runs` — run, list and inspect a team's agents as its Source admin. A run\n * started here is the app's \"Run now\": it runs as the agent's creator under\n * the agent's own grant, policy and approvals (writes still wait for one),\n * and is attributed to you.\n */\nexport async function runRuns(\n ctx: CliContext,\n args: RunsArgs,\n): Promise<ExitCode> {\n const [rawSubcommand, operand, ...extra] = args.positionals;\n const subcommand = RUNS_SUBCOMMANDS.find((name) => name === rawSubcommand);\n if (!subcommand) {\n throw usageError(\n rawSubcommand\n ? `Unknown runs subcommand \"${rawSubcommand}\".`\n : 'runs needs a subcommand.',\n 'Run one of: ekanos runs start <agent> --team <slug> --prompt \"…\", ekanos runs list --team <slug>, ekanos runs show <run-id> --team <slug>, ekanos runs cancel <run-id> --team <slug> [--yes].',\n );\n }\n rejectExtra(extra, 'runs');\n const team = requireTeam(args.team);\n\n if (subcommand === 'start') {\n const agent = requireOperand(operand, 'agent key', 'runs start');\n return startAndReport(ctx, args, { team, agent, draft: false });\n }\n\n const { env, client, source } = await connect(ctx, args);\n\n if (subcommand === 'list') {\n if (operand) rejectExtra([operand], 'runs list');\n const status = parseStatus(args.status);\n const since = parseSince(args.since, Date.now());\n const list = await client.call((token) =>\n listRuns(env.host, token, {\n source,\n team,\n agent: args.agent,\n status,\n since,\n }),\n );\n const scope = [\n args.agent ? `for ${args.agent}` : '',\n status ? `${status}` : '',\n since ? `since ${since.slice(0, 16).replace('T', ' ')}` : '',\n ]\n .filter(Boolean)\n .join(', ');\n return ctx.succeed(\n { host: env.host, ...list },\n list.runs.length === 0\n ? ctx.ui.result({\n title: `No runs on ${list.team.slug}${scope ? ` (${scope})` : ''}`,\n tone: 'warn',\n })\n : ctx.ui.table(\n ['RUN', 'AGENT', 'STATUS', 'TRIGGER', 'VERSION', 'STARTED'],\n list.runs.map((run) => [\n run.id,\n agentLabel(run.agent),\n run.status,\n run.trigger,\n versionLabel(run),\n run.startedAt.slice(0, 19).replace('T', ' '),\n ]),\n ),\n );\n }\n\n if (subcommand === 'cancel') {\n const runId = requireOperand(operand, 'run id', 'runs cancel');\n await confirmCancel(ctx, args, { runId, team });\n const cancelled = await client.call((token) =>\n cancelRun(env.host, token, { source, team, runId }),\n );\n return ctx.succeed(\n { host: env.host, ...cancelled },\n ctx.ui.result({\n title: `Cancelled run ${cancelled.run.id} on ${cancelled.team.slug}`,\n tone: 'warn',\n rows: [\n ['Agent', agentLabel(cancelled.run.agent)],\n ['Status', cancelled.run.status],\n ],\n notes: [\n 'Its pending approvals expired, and runs it was waiting on were stopped too.',\n ],\n }),\n );\n }\n\n const runId = requireOperand(operand, 'run id', 'runs show');\n const detail = await client.call((token) =>\n showRun(env.host, token, { source, team, runId }),\n );\n return ctx.succeed({ host: env.host, ...detail }, runDetail(ctx.ui, detail));\n}\n\n/**\n * `agents test <key> --team <slug>`: run the template's latest version — its\n * draft, published or not — on one team, without publishing it. Marked as a\n * draft test run in the ledger; the team's stored agent still bounds every\n * tool call, so a draft can narrow what runs but never widen it. To test what\n * a draft adds — or a template never published — pin the team to the draft\n * first (`teams agents enable|pin <team> <key> --draft`); the host warns when\n * the team holds another version.\n */\nexport async function runAgentTest(\n ctx: CliContext,\n args: RunsArgs & { key: string | undefined },\n): Promise<ExitCode> {\n const agent = requireOperand(args.key, 'agent key', 'agents test');\n const team = requireTeam(args.team);\n return startAndReport(ctx, args, { team, agent, draft: true });\n}\n\n/**\n * `approvals` — what a team's agent runs are waiting on, and deciding it.\n * Decided with the authority a team's agent manager has in the app, and\n * recorded as your decision.\n */\nexport async function runApprovals(\n ctx: CliContext,\n args: RunsArgs,\n): Promise<ExitCode> {\n const [rawSubcommand, operand, ...extra] = args.positionals;\n const subcommand = APPROVALS_SUBCOMMANDS.find(\n (name) => name === rawSubcommand,\n );\n if (!subcommand) {\n throw usageError(\n rawSubcommand\n ? `Unknown approvals subcommand \"${rawSubcommand}\".`\n : 'approvals needs a subcommand.',\n 'Run one of: ekanos approvals list --team <slug>, ekanos approvals approve|reject <id> --team <slug> [--reason \"…\"], ekanos approvals edit <id> --team <slug> --body <file>.',\n );\n }\n rejectExtra(extra, 'approvals');\n const team = requireTeam(args.team);\n\n if (subcommand === 'list') {\n if (operand) rejectExtra([operand], 'approvals list');\n const { env, client, source } = await connect(ctx, args);\n const list = await client.call((token) =>\n listApprovals(env.host, token, { source, team }),\n );\n return ctx.succeed(\n { host: env.host, ...list },\n list.approvals.length === 0\n ? ctx.ui.result({ title: `Nothing waiting on ${list.team.slug}` })\n : ctx.ui.result({\n title: `${list.approvals.length} waiting on ${list.team.slug}`,\n tone: 'warn',\n rows: list.approvals.map((approval): ResultRow => [\n approval.id,\n approvalLines(approval),\n ]),\n notes: [\n '\"ekanos approvals approve|reject <id> --team <slug>\" decides one; \"approvals edit <id> --body <file>\" edits a reply draft and sends it.',\n ],\n }),\n );\n }\n\n const approvalId = requireOperand(\n operand,\n 'approval id',\n `approvals ${subcommand}`,\n );\n const editedBody =\n subcommand === 'edit' ? readBodyFile(args.body, args.dir) : undefined;\n if (subcommand !== 'edit' && args.body) {\n throw usageError(\n '--body is for \"approvals edit\".',\n `Run \"ekanos approvals edit ${approvalId} --team ${team} --body <file>\".`,\n );\n }\n\n const { env, client, source } = await connect(ctx, args);\n const decided = await client.call((token) =>\n decideApproval(\n env.host,\n token,\n { source, team, approvalId },\n {\n decision: subcommand === 'reject' ? 'rejected' : 'approved',\n ...(args.reason ? { reason: args.reason } : {}),\n ...(editedBody ? { body: editedBody } : {}),\n },\n ),\n );\n const approval = decided.approval;\n return ctx.succeed(\n { host: env.host, ...decided },\n ctx.ui.result({\n title: `${approval.status === 'rejected' ? 'Rejected' : editedBody ? 'Edited and approved' : 'Approved'} ${approval.toolName}`,\n tone: approval.status === 'rejected' ? 'warn' : 'ok',\n rows: [\n ['Agent', agentLabel(approval.agent)],\n ['Run', approval.runId],\n ],\n notes: [\n `The run picks it up now: \"ekanos runs show ${approval.runId} --team ${team}\".`,\n ],\n }),\n );\n}\n\n/**\n * Stopping a run can't be undone: a human run asks first; a scripted or JSON\n * run needs `--yes`. Asked before any request.\n */\nasync function confirmCancel(\n ctx: CliContext,\n args: RunsArgs,\n target: { runId: string; team: string },\n) {\n if (args.yes) return;\n if (ctx.jsonMode || !(args.stdinIsTTY ?? process.stdin.isTTY === true)) {\n throw validationError(\n `Cancelling run ${target.runId} on ${target.team} needs confirmation.`,\n `It stops the run for good and expires its pending approvals. Pass --yes to confirm: ekanos runs cancel ${target.runId} --team ${target.team} --yes`,\n );\n }\n const confirmed = await (args.confirm ?? promptYesNo)(\n `Stop run ${target.runId} on ${target.team} for good? [y/N]`,\n );\n if (!confirmed) {\n throw validationError(\n `Cancelling run ${target.runId} was not confirmed.`,\n 'Nothing was changed.',\n );\n }\n}\n\nasync function startAndReport(\n ctx: CliContext,\n args: RunsArgs,\n target: { team: string; agent: string; draft: boolean },\n): Promise<ExitCode> {\n const body = startBody(args, target);\n const { env, client, source } = await connect(ctx, args);\n const started = await client.call((token) =>\n startRun(env.host, token, { source, team: target.team }, body),\n );\n\n const startedNote = `${target.draft ? 'Testing' : 'Started'} ${agentLabel(started.agent)} on ${started.team.slug}${started.draftTemplateVersion ? ` (draft v${started.draftTemplateVersion}, unpublished)` : ''}: run ${started.runId}`;\n // A run started here needs no channel, so it ran; the agent's real trigger\n // may still never fire. Said up front, so a passing test is not read as\n // \"the agent answers in Linear\".\n const warnings = (started.warnings ?? []).map(\n (warning) => `Warning: ${warning}`,\n );\n\n if (!args.follow) {\n return ctx.succeed(\n { host: env.host, ...started },\n ctx.ui.result({\n title: startedNote,\n ...(warnings.length > 0 ? { tone: 'warn' as const } : {}),\n notes: [\n ...warnings,\n `Watch it: \"ekanos runs show ${started.runId} --team ${target.team}\".`,\n ],\n }),\n );\n }\n\n ctx.log(startedNote);\n for (const warning of warnings) ctx.log(warning);\n const detail = await follow(ctx, args, async (after) =>\n client.call((token) =>\n showRun(env.host, token, {\n source,\n team: target.team,\n runId: started.runId,\n after,\n }),\n ),\n );\n return ctx.succeed(\n { host: env.host, started, ...detail },\n runDetail(ctx.ui, detail),\n );\n}\n\n/**\n * Poll the run, printing its status changes, its messages and each tool\n * call as it lands, until it ends or parks on an approval.\n */\nasync function follow(\n ctx: CliContext,\n args: RunsArgs,\n read: (after: number | undefined) => Promise<AgentRunDetail>,\n): Promise<AgentRunDetail> {\n const sleep =\n args.sleep ??\n ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));\n const seenCalls = new Set<string>();\n const events: AgentRunDetail['events'] = [];\n let lastEvent: number | undefined;\n let lastStatus = '';\n const deadline = Date.now() + FOLLOW_TIMEOUT_MS;\n\n for (;;) {\n const detail = await read(lastEvent);\n for (const event of detail.events) {\n events.push(event);\n lastEvent = event.id;\n for (const line of eventLines(event.message)) ctx.log(` ${line}`);\n }\n for (const call of detail.toolCalls) {\n if (seenCalls.has(call.toolCallId)) continue;\n seenCalls.add(call.toolCallId);\n ctx.log(\n ` ${call.ok === false ? '✗' : '✓'} ${call.toolName} (${callFacts(call)})${call.error ? ` — ${call.error}` : ''}`,\n );\n }\n if (detail.run.status !== lastStatus) {\n lastStatus = detail.run.status;\n ctx.log(` status: ${lastStatus}`);\n }\n\n const waiting = detail.approvals.some(\n (approval) => approval.status === 'pending',\n );\n const ended = ['completed', 'failed', 'cancelled'].includes(\n detail.run.status,\n );\n if (ended || waiting || Date.now() > deadline) {\n return { ...detail, events };\n }\n await sleep(FOLLOW_INTERVAL_MS);\n }\n}\n\n/** Assistant text and tool calls from one live transcript message. */\nfunction eventLines(message: unknown): string[] {\n if (!isRecord(message)) return [];\n const content = message.content;\n if (message.role === 'assistant' && typeof content === 'string') {\n return content.trim() ? [`agent: ${clip(content)}`] : [];\n }\n if (!Array.isArray(content)) return [];\n return content.flatMap((part): string[] => {\n if (!isRecord(part)) return [];\n if (part.type === 'text' && message.role === 'assistant') {\n return typeof part.text === 'string' && part.text.trim()\n ? [`agent: ${clip(part.text)}`]\n : [];\n }\n if (part.type === 'tool-call' && typeof part.toolName === 'string') {\n return [`→ ${part.toolName}`];\n }\n return [];\n });\n}\n\nfunction startBody(\n args: RunsArgs,\n target: { agent: string; draft: boolean },\n): AgentRunStartRequest {\n if (!args.prompt && !args.input) {\n throw usageError(\n 'Give the run a prompt or an input.',\n `Pass --prompt \"…\" or --input <file.json>.`,\n );\n }\n let input: unknown;\n if (args.input) {\n const file = path.resolve(args.dir, args.input);\n let raw: string;\n try {\n raw = fs.readFileSync(file, 'utf8');\n } catch {\n throw usageError(`Cannot read ${file}.`, 'Pass --input <file.json>.');\n }\n try {\n input = JSON.parse(raw);\n } catch {\n throw validationError(\n `${file} is not valid JSON.`,\n 'Fix the file, or pass the text with --prompt instead.',\n );\n }\n }\n return {\n agent: target.agent,\n ...(args.prompt ? { prompt: args.prompt } : {}),\n ...(input !== undefined ? { input } : {}),\n draft: target.draft,\n };\n}\n\nfunction readBodyFile(file: string | undefined, dir: string): string {\n if (!file) {\n throw usageError(\n 'approvals edit needs the reply to send.',\n 'Pass --body <file> with the edited reply text.',\n );\n }\n const resolved = path.resolve(dir, file);\n let text: string;\n try {\n text = fs.readFileSync(resolved, 'utf8');\n } catch {\n throw usageError(`Cannot read ${resolved}.`, 'Pass --body <file>.');\n }\n if (!text.trim()) {\n throw validationError(`${resolved} is empty.`, 'Write the reply to send.');\n }\n return text;\n}\n\nfunction runDetail(ui: Ui, detail: AgentRunDetail): string {\n const { run } = detail;\n const pending = detail.approvals.filter(\n (approval) => approval.status === 'pending',\n );\n const rows: ResultRow[] = [\n ['Agent', agentLabel(run.agent)],\n ['Status', run.status],\n ['Trigger', run.trigger],\n ['Version', versionLabel(run)],\n ['Started', run.startedAt],\n ...(run.finishedAt ? [['Finished', run.finishedAt] as ResultRow] : []),\n ...(run.error ? [['Error', run.error] as ResultRow] : []),\n [\n 'Tool calls',\n detail.toolCalls.length === 0\n ? 'none'\n : detail.toolCalls.map(\n (call) =>\n `${call.ok === false ? '✗' : '✓'} ${call.toolName} (${callFacts(call)})`,\n ),\n ],\n ...(pending.length > 0\n ? [\n [\n 'Waiting on',\n pending.flatMap((approval) => [\n `${approval.id} ${approval.toolName}${approval.replyDraft ? ' (reply draft)' : ''}`,\n ]),\n ] as ResultRow,\n ]\n : []),\n ...(run.output ? [['Output', run.output.split('\\n')] as ResultRow] : []),\n ];\n return ui.result({\n title: `Run ${run.id}`,\n tone:\n run.status === 'failed'\n ? 'err'\n : run.status === 'completed'\n ? 'ok'\n : 'warn',\n rows,\n notes:\n pending.length > 0\n ? [\n `Decide: \"ekanos approvals approve|reject <id> --team ${detail.team.slug}\". Full record: --json.`,\n ]\n : ['The full transcript and every tool call: --json.'],\n });\n}\n\nfunction approvalLines(approval: AgentRunApproval): string[] {\n return [\n `${approval.toolName} · ${agentLabel(approval.agent)}${approval.replyDraft ? ' · reply draft (editable)' : ''}`,\n `run ${approval.runId}${approval.expiresAt ? ` · expires ${approval.expiresAt}` : ''}`,\n clip(JSON.stringify(approval.args ?? null)),\n ];\n}\n\nfunction agentLabel(agent: AgentRunSummary['agent']): string {\n return agent.templateKey ?? agent.slug;\n}\n\nfunction versionLabel(run: AgentRunSummary): string {\n return run.draftTemplateVersion\n ? `v${run.agentVersion} · draft test of template v${run.draftTemplateVersion}`\n : `v${run.agentVersion}`;\n}\n\nfunction clip(text: string, max = 200): string {\n const flat = text.replace(/\\s+/g, ' ').trim();\n return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction requireTeam(value: string | undefined): 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 team slug.`\n : 'Name the team with --team <slug>.',\n '\"ekanos teams list\" lists the teams on this Source.',\n );\n}\n\nfunction requireOperand(\n value: string | undefined,\n what: string,\n command: string,\n): string {\n const trimmed = value?.trim();\n if (trimmed) return trimmed;\n throw usageError(`Name the ${what}.`, `See \"ekanos ${command} --help\".`);\n}\n\n/** `--status`, one of the run statuses. */\nfunction parseStatus(raw: string | undefined): string | undefined {\n if (raw === undefined) return undefined;\n const parsed = AgentRunStatusSchema.safeParse(raw.trim());\n if (parsed.success) return parsed.data;\n throw usageError(\n `--status \"${raw}\" is not a run status.`,\n `Use one of: ${AgentRunStatusSchema.options.join(', ')}.`,\n );\n}\n\nfunction rejectExtra(extra: readonly string[], command: string) {\n if (extra.length > 0) {\n throw usageError(\n `Unexpected argument \"${extra[0]}\".`,\n `See \"ekanos ${command.split(' ')[0]} --help\".`,\n );\n }\n}\n\nasync function connect(ctx: CliContext, args: RunsArgs) {\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 RunsClient(env, resolved.session),\n source: resolved.source,\n };\n}\n\nclass RunsClient {\n constructor(\n private readonly env: AuthEnvironment,\n private session: StoredSession,\n ) {}\n\n async call<T>(\n send: (accessToken: string) => Promise<RunsApiResult<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 call.`,\n loginHint(this.env),\n );\n }\n}\n\nconst CONNECTION_WORDS = {\n source: 'via Source connection',\n team: 'via team connection',\n person: 'via personal connection',\n} as const;\n\n/** Effect, how it was authorized, and whose connection it ran on. */\nfunction callFacts(call: AgentRunToolCall): string {\n return [\n call.effect,\n call.authorizedVia,\n ...(call.connection ? [CONNECTION_WORDS[call.connection]] : []),\n ].join(', ');\n}\n"]}
1
+ {"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/commands/runs.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AgentRunApproval,\n type AgentRunDetail,\n type AgentRunStartRequest,\n AgentRunStatusSchema,\n type AgentRunSummary,\n type AgentRunToolCall,\n} from '@ekanos/integration-schema';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\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 type { CliContext } from '../context';\nimport { authRequiredError, usageError, validationError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport {\n type RunsApiResult,\n cancelRun,\n decideApproval,\n listApprovals,\n listRuns,\n showRun,\n startRun,\n} from '../runs-api';\nimport { resolveSourceTarget } from '../source-target';\nimport type { ResultRow, Ui } from '../ui';\nimport { promptYesNo } from './publish';\nimport { parseSince } from './teams-events';\n\nexport const RUNS_SUBCOMMANDS = ['start', 'list', 'show', 'cancel'] as const;\nexport const APPROVALS_SUBCOMMANDS = [\n 'list',\n 'approve',\n 'reject',\n 'edit',\n] as const;\n\nconst FOLLOW_INTERVAL_MS = 2000;\nconst FOLLOW_TIMEOUT_MS = 15 * 60 * 1000;\n\nexport interface RunsArgs {\n host?: string;\n source?: string;\n positionals: readonly string[];\n team?: string;\n agent?: string;\n /** `list --status <status>` and `--since 24h|7d|<date>`. */\n status?: string;\n since?: string;\n prompt?: string;\n input?: string;\n follow: boolean;\n reason?: string;\n body?: string;\n /** `runs cancel`: confirmed up front, for a script or an agent run. */\n yes?: boolean;\n dir: string;\n env: Record<string, string | undefined>;\n /** Test seam for the `--follow` poll delay. */\n sleep?: (ms: number) => Promise<void>;\n /** Test seams for `runs cancel`'s question. */\n stdinIsTTY?: boolean;\n confirm?: (question: string) => Promise<boolean>;\n}\n\n/**\n * `runs` — run, list and inspect a team's agents as its Source admin. A run\n * started here is the app's \"Run now\": it runs as the agent's creator under\n * the agent's own grant, policy and approvals (writes still wait for one),\n * and is attributed to you.\n */\nexport async function runRuns(\n ctx: CliContext,\n args: RunsArgs,\n): Promise<ExitCode> {\n const [rawSubcommand, operand, ...extra] = args.positionals;\n const subcommand = RUNS_SUBCOMMANDS.find((name) => name === rawSubcommand);\n if (!subcommand) {\n throw usageError(\n rawSubcommand\n ? `Unknown runs subcommand \"${rawSubcommand}\".`\n : 'runs needs a subcommand.',\n 'Run one of: ekanos runs start <agent> --team <slug> --prompt \"…\", ekanos runs list --team <slug>, ekanos runs show <run-id> --team <slug>, ekanos runs cancel <run-id> --team <slug> [--yes].',\n );\n }\n rejectExtra(extra, 'runs');\n const team = requireTeam(args.team);\n\n if (subcommand === 'start') {\n const agent = requireOperand(operand, 'agent key', 'runs start');\n return startAndReport(ctx, args, { team, agent, draft: false });\n }\n\n const { env, client, source } = await connect(ctx, args);\n\n if (subcommand === 'list') {\n if (operand) rejectExtra([operand], 'runs list');\n const status = parseStatus(args.status);\n const since = parseSince(args.since, Date.now());\n const list = await client.call((token) =>\n listRuns(env.host, token, {\n source,\n team,\n agent: args.agent,\n status,\n since,\n }),\n );\n const scope = [\n args.agent ? `for ${args.agent}` : '',\n status ? `${status}` : '',\n since ? `since ${since.slice(0, 16).replace('T', ' ')}` : '',\n ]\n .filter(Boolean)\n .join(', ');\n return ctx.succeed(\n { host: env.host, ...list },\n list.runs.length === 0\n ? ctx.ui.result({\n title: `No runs on ${list.team.slug}${scope ? ` (${scope})` : ''}`,\n tone: 'warn',\n })\n : ctx.ui.table(\n ['RUN', 'AGENT', 'STATUS', 'TRIGGER', 'VERSION', 'STARTED'],\n list.runs.map((run) => [\n run.id,\n agentLabel(run.agent),\n run.status,\n run.trigger,\n versionLabel(run),\n run.startedAt.slice(0, 19).replace('T', ' '),\n ]),\n ),\n );\n }\n\n if (subcommand === 'cancel') {\n const runId = requireOperand(operand, 'run id', 'runs cancel');\n await confirmCancel(ctx, args, { runId, team });\n const cancelled = await client.call((token) =>\n cancelRun(env.host, token, { source, team, runId }),\n );\n return ctx.succeed(\n { host: env.host, ...cancelled },\n ctx.ui.result({\n title: `Cancelled run ${cancelled.run.id} on ${cancelled.team.slug}`,\n tone: 'warn',\n rows: [\n ['Agent', agentLabel(cancelled.run.agent)],\n ['Status', cancelled.run.status],\n ],\n notes: [\n 'Its pending approvals expired, and runs it was waiting on were stopped too.',\n ],\n }),\n );\n }\n\n const runId = requireOperand(operand, 'run id', 'runs show');\n const detail = await client.call((token) =>\n showRun(env.host, token, { source, team, runId }),\n );\n return ctx.succeed({ host: env.host, ...detail }, runDetail(ctx.ui, detail));\n}\n\n/**\n * `agents test <key> --team <slug>`: run the template's latest version — its\n * draft, published or not — on one team, without publishing it. Marked as a\n * draft test run in the ledger; the team's stored agent still bounds every\n * tool call, so a draft can narrow what runs but never widen it. To test what\n * a draft adds — or a template never published — pin the team to the draft\n * first (`teams agents enable|pin <team> <key> --draft`); the host warns when\n * the team holds another version.\n */\nexport async function runAgentTest(\n ctx: CliContext,\n args: RunsArgs & { key: string | undefined },\n): Promise<ExitCode> {\n const agent = requireOperand(args.key, 'agent key', 'agents test');\n const team = requireTeam(args.team);\n return startAndReport(ctx, args, { team, agent, draft: true });\n}\n\n/**\n * `approvals` — what a team's agent runs are waiting on, and deciding it,\n * recorded as your decision. A Source admin sees and decides every one\n * (a provided agent's with an agent manager's authority); any other seat\n * holder sees and decides only those they may in the app — as a member who\n * manages the team's agents, or reply drafts as one who reviews them or a\n * reviewer the Source admin named, and a personal agent's as its creator.\n * The first decision wins.\n */\nexport async function runApprovals(\n ctx: CliContext,\n args: RunsArgs,\n): Promise<ExitCode> {\n const [rawSubcommand, operand, ...extra] = args.positionals;\n const subcommand = APPROVALS_SUBCOMMANDS.find(\n (name) => name === rawSubcommand,\n );\n if (!subcommand) {\n throw usageError(\n rawSubcommand\n ? `Unknown approvals subcommand \"${rawSubcommand}\".`\n : 'approvals needs a subcommand.',\n 'Run one of: ekanos approvals list --team <slug>, ekanos approvals approve|reject <id> --team <slug> [--reason \"…\"], ekanos approvals edit <id> --team <slug> --body <file>.',\n );\n }\n rejectExtra(extra, 'approvals');\n const team = requireTeam(args.team);\n\n if (subcommand === 'list') {\n if (operand) rejectExtra([operand], 'approvals list');\n const { env, client, source } = await connect(ctx, args);\n const list = await client.call((token) =>\n listApprovals(env.host, token, { source, team }),\n );\n // Not the Source's admin: only what you may decide yourself.\n const yours = list.scope === 'yours';\n return ctx.succeed(\n { host: env.host, ...list },\n list.approvals.length === 0\n ? ctx.ui.result({\n title: yours\n ? `Nothing waiting on ${list.team.slug} that you can decide`\n : `Nothing waiting on ${list.team.slug}`,\n ...(yours\n ? {\n notes: [\n \"You see the approvals you may decide: as a member who manages the team's agents, or — reply drafts — one who reviews them or a reviewer the Source admin named; a personal agent's, as its creator.\",\n ],\n }\n : {}),\n })\n : ctx.ui.result({\n title: yours\n ? `${list.approvals.length} waiting on ${list.team.slug} for you to decide`\n : `${list.approvals.length} waiting on ${list.team.slug}`,\n tone: 'warn',\n rows: list.approvals.map((approval): ResultRow => [\n approval.id,\n approvalLines(approval),\n ]),\n notes: [\n '\"ekanos approvals approve|reject <id> --team <slug>\" decides one; \"approvals edit <id> --body <file>\" edits a reply draft and sends it.',\n ],\n }),\n );\n }\n\n const approvalId = requireOperand(\n operand,\n 'approval id',\n `approvals ${subcommand}`,\n );\n const editedBody =\n subcommand === 'edit' ? readBodyFile(args.body, args.dir) : undefined;\n if (subcommand !== 'edit' && args.body) {\n throw usageError(\n '--body is for \"approvals edit\".',\n `Run \"ekanos approvals edit ${approvalId} --team ${team} --body <file>\".`,\n );\n }\n\n const { env, client, source } = await connect(ctx, args);\n const decided = await client.call((token) =>\n decideApproval(\n env.host,\n token,\n { source, team, approvalId },\n {\n decision: subcommand === 'reject' ? 'rejected' : 'approved',\n ...(args.reason ? { reason: args.reason } : {}),\n ...(editedBody ? { body: editedBody } : {}),\n },\n ),\n );\n const approval = decided.approval;\n return ctx.succeed(\n { host: env.host, ...decided },\n ctx.ui.result({\n title: `${approval.status === 'rejected' ? 'Rejected' : editedBody ? 'Edited and approved' : 'Approved'} ${approval.toolName}`,\n tone: approval.status === 'rejected' ? 'warn' : 'ok',\n rows: [\n ['Agent', agentLabel(approval.agent)],\n ['Run', approval.runId],\n ],\n notes: [\n `The run picks it up now: \"ekanos runs show ${approval.runId} --team ${team}\".`,\n ],\n }),\n );\n}\n\n/**\n * Stopping a run can't be undone: a human run asks first; a scripted or JSON\n * run needs `--yes`. Asked before any request.\n */\nasync function confirmCancel(\n ctx: CliContext,\n args: RunsArgs,\n target: { runId: string; team: string },\n) {\n if (args.yes) return;\n if (ctx.jsonMode || !(args.stdinIsTTY ?? process.stdin.isTTY === true)) {\n throw validationError(\n `Cancelling run ${target.runId} on ${target.team} needs confirmation.`,\n `It stops the run for good and expires its pending approvals. Pass --yes to confirm: ekanos runs cancel ${target.runId} --team ${target.team} --yes`,\n );\n }\n const confirmed = await (args.confirm ?? promptYesNo)(\n `Stop run ${target.runId} on ${target.team} for good? [y/N]`,\n );\n if (!confirmed) {\n throw validationError(\n `Cancelling run ${target.runId} was not confirmed.`,\n 'Nothing was changed.',\n );\n }\n}\n\nasync function startAndReport(\n ctx: CliContext,\n args: RunsArgs,\n target: { team: string; agent: string; draft: boolean },\n): Promise<ExitCode> {\n const body = startBody(args, target);\n const { env, client, source } = await connect(ctx, args);\n const started = await client.call((token) =>\n startRun(env.host, token, { source, team: target.team }, body),\n );\n\n const startedNote = `${target.draft ? 'Testing' : 'Started'} ${agentLabel(started.agent)} on ${started.team.slug}${started.draftTemplateVersion ? ` (draft v${started.draftTemplateVersion}, unpublished)` : ''}: run ${started.runId}`;\n // A run started here needs no channel, so it ran; the agent's real trigger\n // may still never fire. Said up front, so a passing test is not read as\n // \"the agent answers in Linear\".\n const warnings = (started.warnings ?? []).map(\n (warning) => `Warning: ${warning}`,\n );\n\n if (!args.follow) {\n return ctx.succeed(\n { host: env.host, ...started },\n ctx.ui.result({\n title: startedNote,\n ...(warnings.length > 0 ? { tone: 'warn' as const } : {}),\n notes: [\n ...warnings,\n `Watch it: \"ekanos runs show ${started.runId} --team ${target.team}\".`,\n ],\n }),\n );\n }\n\n ctx.log(startedNote);\n for (const warning of warnings) ctx.log(warning);\n const detail = await follow(ctx, args, async (after) =>\n client.call((token) =>\n showRun(env.host, token, {\n source,\n team: target.team,\n runId: started.runId,\n after,\n }),\n ),\n );\n return ctx.succeed(\n { host: env.host, started, ...detail },\n runDetail(ctx.ui, detail),\n );\n}\n\n/**\n * Poll the run, printing its status changes, its messages and each tool\n * call as it lands, until it ends or parks on an approval.\n */\nasync function follow(\n ctx: CliContext,\n args: RunsArgs,\n read: (after: number | undefined) => Promise<AgentRunDetail>,\n): Promise<AgentRunDetail> {\n const sleep =\n args.sleep ??\n ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));\n const seenCalls = new Set<string>();\n const events: AgentRunDetail['events'] = [];\n let lastEvent: number | undefined;\n let lastStatus = '';\n const deadline = Date.now() + FOLLOW_TIMEOUT_MS;\n\n for (;;) {\n const detail = await read(lastEvent);\n for (const event of detail.events) {\n events.push(event);\n lastEvent = event.id;\n for (const line of eventLines(event.message)) ctx.log(` ${line}`);\n }\n for (const call of detail.toolCalls) {\n if (seenCalls.has(call.toolCallId)) continue;\n seenCalls.add(call.toolCallId);\n ctx.log(\n ` ${call.ok === false ? '✗' : '✓'} ${call.toolName} (${callFacts(call)})${call.error ? ` — ${call.error}` : ''}`,\n );\n }\n if (detail.run.status !== lastStatus) {\n lastStatus = detail.run.status;\n ctx.log(` status: ${lastStatus}`);\n }\n\n const waiting = detail.approvals.some(\n (approval) => approval.status === 'pending',\n );\n const ended = ['completed', 'failed', 'cancelled'].includes(\n detail.run.status,\n );\n if (ended || waiting || Date.now() > deadline) {\n return { ...detail, events };\n }\n await sleep(FOLLOW_INTERVAL_MS);\n }\n}\n\n/** Assistant text and tool calls from one live transcript message. */\nfunction eventLines(message: unknown): string[] {\n if (!isRecord(message)) return [];\n const content = message.content;\n if (message.role === 'assistant' && typeof content === 'string') {\n return content.trim() ? [`agent: ${clip(content)}`] : [];\n }\n if (!Array.isArray(content)) return [];\n return content.flatMap((part): string[] => {\n if (!isRecord(part)) return [];\n if (part.type === 'text' && message.role === 'assistant') {\n return typeof part.text === 'string' && part.text.trim()\n ? [`agent: ${clip(part.text)}`]\n : [];\n }\n if (part.type === 'tool-call' && typeof part.toolName === 'string') {\n return [`→ ${part.toolName}`];\n }\n return [];\n });\n}\n\nfunction startBody(\n args: RunsArgs,\n target: { agent: string; draft: boolean },\n): AgentRunStartRequest {\n if (!args.prompt && !args.input) {\n throw usageError(\n 'Give the run a prompt or an input.',\n `Pass --prompt \"…\" or --input <file.json>.`,\n );\n }\n let input: unknown;\n if (args.input) {\n const file = path.resolve(args.dir, args.input);\n let raw: string;\n try {\n raw = fs.readFileSync(file, 'utf8');\n } catch {\n throw usageError(`Cannot read ${file}.`, 'Pass --input <file.json>.');\n }\n try {\n input = JSON.parse(raw);\n } catch {\n throw validationError(\n `${file} is not valid JSON.`,\n 'Fix the file, or pass the text with --prompt instead.',\n );\n }\n }\n return {\n agent: target.agent,\n ...(args.prompt ? { prompt: args.prompt } : {}),\n ...(input !== undefined ? { input } : {}),\n draft: target.draft,\n };\n}\n\nfunction readBodyFile(file: string | undefined, dir: string): string {\n if (!file) {\n throw usageError(\n 'approvals edit needs the reply to send.',\n 'Pass --body <file> with the edited reply text.',\n );\n }\n const resolved = path.resolve(dir, file);\n let text: string;\n try {\n text = fs.readFileSync(resolved, 'utf8');\n } catch {\n throw usageError(`Cannot read ${resolved}.`, 'Pass --body <file>.');\n }\n if (!text.trim()) {\n throw validationError(`${resolved} is empty.`, 'Write the reply to send.');\n }\n return text;\n}\n\nfunction runDetail(ui: Ui, detail: AgentRunDetail): string {\n const { run } = detail;\n const pending = detail.approvals.filter(\n (approval) => approval.status === 'pending',\n );\n const rows: ResultRow[] = [\n ['Agent', agentLabel(run.agent)],\n ['Status', run.status],\n ['Trigger', run.trigger],\n ['Version', versionLabel(run)],\n ['Started', run.startedAt],\n ...(run.finishedAt ? [['Finished', run.finishedAt] as ResultRow] : []),\n ...(run.error ? [['Error', run.error] as ResultRow] : []),\n [\n 'Tool calls',\n detail.toolCalls.length === 0\n ? 'none'\n : detail.toolCalls.map(\n (call) =>\n `${call.ok === false ? '✗' : '✓'} ${call.toolName} (${callFacts(call)})`,\n ),\n ],\n ...(pending.length > 0\n ? [\n [\n 'Waiting on',\n pending.flatMap((approval) => [\n `${approval.id} ${approval.toolName}${approval.replyDraft ? ' (reply draft)' : ''}`,\n ]),\n ] as ResultRow,\n ]\n : []),\n ...(run.output ? [['Output', run.output.split('\\n')] as ResultRow] : []),\n ];\n return ui.result({\n title: `Run ${run.id}`,\n tone:\n run.status === 'failed'\n ? 'err'\n : run.status === 'completed'\n ? 'ok'\n : 'warn',\n rows,\n notes:\n pending.length > 0\n ? [\n `Decide: \"ekanos approvals approve|reject <id> --team ${detail.team.slug}\". Full record: --json.`,\n ]\n : ['The full transcript and every tool call: --json.'],\n });\n}\n\nfunction approvalLines(approval: AgentRunApproval): string[] {\n return [\n `${approval.toolName} · ${agentLabel(approval.agent)}${approval.replyDraft ? ' · reply draft (editable)' : ''}`,\n `run ${approval.runId}${approval.expiresAt ? ` · expires ${approval.expiresAt}` : ''}`,\n approval.argsWithheld\n ? \"arguments withheld: the team's own agent, so only a member of the team who could decide it sees what it would do\"\n : clip(JSON.stringify(approval.args ?? null)),\n ];\n}\n\nfunction agentLabel(agent: AgentRunSummary['agent']): string {\n return agent.templateKey ?? agent.slug;\n}\n\nfunction versionLabel(run: AgentRunSummary): string {\n return run.draftTemplateVersion\n ? `v${run.agentVersion} · draft test of template v${run.draftTemplateVersion}`\n : `v${run.agentVersion}`;\n}\n\nfunction clip(text: string, max = 200): string {\n const flat = text.replace(/\\s+/g, ' ').trim();\n return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction requireTeam(value: string | undefined): 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 team slug.`\n : 'Name the team with --team <slug>.',\n '\"ekanos teams list\" lists the teams on this Source.',\n );\n}\n\nfunction requireOperand(\n value: string | undefined,\n what: string,\n command: string,\n): string {\n const trimmed = value?.trim();\n if (trimmed) return trimmed;\n throw usageError(`Name the ${what}.`, `See \"ekanos ${command} --help\".`);\n}\n\n/** `--status`, one of the run statuses. */\nfunction parseStatus(raw: string | undefined): string | undefined {\n if (raw === undefined) return undefined;\n const parsed = AgentRunStatusSchema.safeParse(raw.trim());\n if (parsed.success) return parsed.data;\n throw usageError(\n `--status \"${raw}\" is not a run status.`,\n `Use one of: ${AgentRunStatusSchema.options.join(', ')}.`,\n );\n}\n\nfunction rejectExtra(extra: readonly string[], command: string) {\n if (extra.length > 0) {\n throw usageError(\n `Unexpected argument \"${extra[0]}\".`,\n `See \"ekanos ${command.split(' ')[0]} --help\".`,\n );\n }\n}\n\nasync function connect(ctx: CliContext, args: RunsArgs) {\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 RunsClient(env, resolved.session),\n source: resolved.source,\n };\n}\n\nclass RunsClient {\n constructor(\n private readonly env: AuthEnvironment,\n private session: StoredSession,\n ) {}\n\n async call<T>(\n send: (accessToken: string) => Promise<RunsApiResult<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 call.`,\n loginHint(this.env),\n );\n }\n}\n\nconst CONNECTION_WORDS = {\n source: 'via Source connection',\n team: 'via team connection',\n person: 'via personal connection',\n} as const;\n\n/** Effect, how it was authorized, and whose connection it ran on. */\nfunction callFacts(call: AgentRunToolCall): string {\n return [\n call.effect,\n call.authorizedVia,\n ...(call.connection ? [CONNECTION_WORDS[call.connection]] : []),\n ].join(', ');\n}\n"]}
@@ -1,4 +1,11 @@
1
1
  import type { TeamScopeState } from '@ekanos/integration-schema';
2
+ /**
3
+ * A product the CLI reports as ready for a team can still be hidden from the
4
+ * team in the app by the team's product scopes — the "Bronze" scope that
5
+ * hid Linear and Zendesk on a team whose setup read as done. Wherever the
6
+ * CLI says a product is ready, it says this too, with the command that
7
+ * changes it.
8
+ */
2
9
  export interface ScopeFacts {
3
10
  state: TeamScopeState;
4
11
  scopes: string[];
@@ -1,11 +1,4 @@
1
- /**
2
- * A product the CLI reports as ready for a team can still be hidden from the
3
- * team in the app by the team's product scopes — the "Bronze" scope that
4
- * hid Linear and Zendesk on a team whose setup read as done. Wherever the
5
- * CLI says a product is ready, it says this too, with the command that
6
- * changes it.
7
- */
8
- const CLI = 'npx @ekanos/cli';
1
+ import { cli } from '../invocation.js';
9
2
  /** "hidden by its product scope Bronze" — the problem, in words. */
10
3
  export function scopeHiddenWords(scope) {
11
4
  return scope.state === 'locked_out' || scope.scopes.length === 0
@@ -14,11 +7,11 @@ export function scopeHiddenWords(scope) {
14
7
  }
15
8
  /** The command that shows the product to the team. */
16
9
  export function scopeFix(scope, target) {
17
- const set = `${CLI} teams scope set ${target.team} <scope> --source ${target.source}`;
10
+ const set = `${cli()} teams scope set ${target.team} <scope> --source ${target.source}`;
18
11
  if (scope.state === 'locked_out' || scope.scopes.length === 0) {
19
- return `${set} (scopes and their products: ${CLI} sources scopes --source ${target.source})`;
12
+ return `${set} (scopes and their products: ${cli()} sources scopes --source ${target.source})`;
20
13
  }
21
- return `${CLI} sources scopes add ${quote(scope.scopes[0])} ${target.product} --source ${target.source} (every team on ${scope.scopes[0]} then sees it; or move the team to a scope that has it: ${set})`;
14
+ return `${cli()} sources scopes add ${quote(scope.scopes[0])} ${target.product} --source ${target.source} (every team on ${scope.scopes[0]} then sees it; or move the team to a scope that has it: ${set})`;
22
15
  }
23
16
  /** The two lines `teams show` / `teams connect` print for a hidden product. */
24
17
  export function scopeHiddenLines(scope, target) {
@@ -1 +1 @@
1
- {"version":3,"file":"scope-notice.js","sourceRoot":"","sources":["../../src/commands/scope-notice.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH,MAAM,GAAG,GAAG,iBAAiB,CAAC;AAO9B,oEAAoE;AACpE,MAAM,UAAU,gBAAgB,CAAC,KAAiB;IAChD,OAAO,KAAK,CAAC,KAAK,KAAK,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAC9D,CAAC,CAAC,+EAA+E;QACjF,CAAC,CAAC,uDAAuD,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC/H,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,QAAQ,CACtB,KAAiB,EACjB,MAAyD;IAEzD,MAAM,GAAG,GAAG,GAAG,GAAG,oBAAoB,MAAM,CAAC,IAAI,qBAAqB,MAAM,CAAC,MAAM,EAAE,CAAC;IACtF,IAAI,KAAK,CAAC,KAAK,KAAK,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9D,OAAO,GAAG,GAAG,iCAAiC,GAAG,4BAA4B,MAAM,CAAC,MAAM,GAAG,CAAC;IAChG,CAAC;IACD,OAAO,GAAG,GAAG,uBAAuB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,IAAI,MAAM,CAAC,OAAO,aAAa,MAAM,CAAC,MAAM,oBAAoB,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,2DAA2D,GAAG,GAAG,CAAC;AAC9M,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAC9B,KAAqD,EACrD,MAAyD;IAEzD,IAAI,EAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,MAAM,CAAA;QAAE,OAAO,EAAE,CAAC;IAC9B,OAAO;QACL,KAAK,MAAM,CAAC,OAAO,OAAO,gBAAgB,CAAC,KAAK,CAAC,GAAG;QACpD,UAAU,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE;KACpC,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,IAAY;IACzB,OAAO,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC;AAC7D,CAAC","sourcesContent":["import type { TeamScopeState } from '@ekanos/integration-schema';\n\n/**\n * A product the CLI reports as ready for a team can still be hidden from the\n * team in the app by the team's product scopes — the \"Bronze\" scope that\n * hid Linear and Zendesk on a team whose setup read as done. Wherever the\n * CLI says a product is ready, it says this too, with the command that\n * changes it.\n */\n\nconst CLI = 'npx @ekanos/cli';\n\nexport interface ScopeFacts {\n state: TeamScopeState;\n scopes: string[];\n}\n\n/** \"hidden by its product scope Bronze\" — the problem, in words. */\nexport function scopeHiddenWords(scope: ScopeFacts): string {\n return scope.state === 'locked_out' || scope.scopes.length === 0\n ? 'hidden from the team in the app: it holds none of the Source’s product scopes'\n : `hidden from the team in the app by its product scope${scope.scopes.length === 1 ? '' : 's'} ${scope.scopes.join(', ')}`;\n}\n\n/** The command that shows the product to the team. */\nexport function scopeFix(\n scope: ScopeFacts,\n target: { team: string; product: string; source: string },\n): string {\n const set = `${CLI} teams scope set ${target.team} <scope> --source ${target.source}`;\n if (scope.state === 'locked_out' || scope.scopes.length === 0) {\n return `${set} (scopes and their products: ${CLI} sources scopes --source ${target.source})`;\n }\n return `${CLI} sources scopes add ${quote(scope.scopes[0]!)} ${target.product} --source ${target.source} (every team on ${scope.scopes[0]} then sees it; or move the team to a scope that has it: ${set})`;\n}\n\n/** The two lines `teams show` / `teams connect` print for a hidden product. */\nexport function scopeHiddenLines(\n scope: (ScopeFacts & { hidden: boolean }) | undefined,\n target: { team: string; product: string; source: string },\n): string[] {\n if (!scope?.hidden) return [];\n return [\n `! ${target.product} is ${scopeHiddenWords(scope)}.`,\n ` Fix: ${scopeFix(scope, target)}`,\n ];\n}\n\nfunction quote(name: string): string {\n return /^[A-Za-z0-9._-]+$/.test(name) ? name : `\"${name}\"`;\n}\n"]}
1
+ {"version":3,"file":"scope-notice.js","sourceRoot":"","sources":["../../src/commands/scope-notice.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAepC,oEAAoE;AACpE,MAAM,UAAU,gBAAgB,CAAC,KAAiB;IAChD,OAAO,KAAK,CAAC,KAAK,KAAK,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAC9D,CAAC,CAAC,+EAA+E;QACjF,CAAC,CAAC,uDAAuD,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC/H,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,QAAQ,CACtB,KAAiB,EACjB,MAAyD;IAEzD,MAAM,GAAG,GAAG,GAAG,GAAG,EAAE,oBAAoB,MAAM,CAAC,IAAI,qBAAqB,MAAM,CAAC,MAAM,EAAE,CAAC;IACxF,IAAI,KAAK,CAAC,KAAK,KAAK,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9D,OAAO,GAAG,GAAG,iCAAiC,GAAG,EAAE,4BAA4B,MAAM,CAAC,MAAM,GAAG,CAAC;IAClG,CAAC;IACD,OAAO,GAAG,GAAG,EAAE,uBAAuB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,IAAI,MAAM,CAAC,OAAO,aAAa,MAAM,CAAC,MAAM,oBAAoB,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,2DAA2D,GAAG,GAAG,CAAC;AAChN,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAC9B,KAAqD,EACrD,MAAyD;IAEzD,IAAI,EAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,MAAM,CAAA;QAAE,OAAO,EAAE,CAAC;IAC9B,OAAO;QACL,KAAK,MAAM,CAAC,OAAO,OAAO,gBAAgB,CAAC,KAAK,CAAC,GAAG;QACpD,UAAU,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE;KACpC,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,IAAY;IACzB,OAAO,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC;AAC7D,CAAC","sourcesContent":["import type { TeamScopeState } from '@ekanos/integration-schema';\n\nimport { cli } from '../invocation';\n\n/**\n * A product the CLI reports as ready for a team can still be hidden from the\n * team in the app by the team's product scopes — the \"Bronze\" scope that\n * hid Linear and Zendesk on a team whose setup read as done. Wherever the\n * CLI says a product is ready, it says this too, with the command that\n * changes it.\n */\n\nexport interface ScopeFacts {\n state: TeamScopeState;\n scopes: string[];\n}\n\n/** \"hidden by its product scope Bronze\" — the problem, in words. */\nexport function scopeHiddenWords(scope: ScopeFacts): string {\n return scope.state === 'locked_out' || scope.scopes.length === 0\n ? 'hidden from the team in the app: it holds none of the Source’s product scopes'\n : `hidden from the team in the app by its product scope${scope.scopes.length === 1 ? '' : 's'} ${scope.scopes.join(', ')}`;\n}\n\n/** The command that shows the product to the team. */\nexport function scopeFix(\n scope: ScopeFacts,\n target: { team: string; product: string; source: string },\n): string {\n const set = `${cli()} teams scope set ${target.team} <scope> --source ${target.source}`;\n if (scope.state === 'locked_out' || scope.scopes.length === 0) {\n return `${set} (scopes and their products: ${cli()} sources scopes --source ${target.source})`;\n }\n return `${cli()} sources scopes add ${quote(scope.scopes[0]!)} ${target.product} --source ${target.source} (every team on ${scope.scopes[0]} then sees it; or move the team to a scope that has it: ${set})`;\n}\n\n/** The two lines `teams show` / `teams connect` print for a hidden product. */\nexport function scopeHiddenLines(\n scope: (ScopeFacts & { hidden: boolean }) | undefined,\n target: { team: string; product: string; source: string },\n): string[] {\n if (!scope?.hidden) return [];\n return [\n `! ${target.product} is ${scopeHiddenWords(scope)}.`,\n ` Fix: ${scopeFix(scope, target)}`,\n ];\n}\n\nfunction quote(name: string): string {\n return /^[A-Za-z0-9._-]+$/.test(name) ? name : `\"${name}\"`;\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import type { CliContext } from '../context.js';
2
+ import type { ExitCode } from '../exit-codes.js';
3
+ import type { SourcesArgs } from './sources.js';
4
+ export declare function runSourceRoles(ctx: CliContext, args: SourcesArgs, rest: readonly string[]): Promise<ExitCode>;
5
+ export declare function runSourcePeople(ctx: CliContext, args: SourcesArgs, rest: readonly string[]): Promise<ExitCode>;