@ekanos/cli 0.15.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.
- package/README.md +41 -4
- package/dist/auth/ekanos-api.d.ts +23 -0
- package/dist/auth/ekanos-api.js +33 -6
- package/dist/auth/ekanos-api.js.map +1 -1
- package/dist/commands/agents.js +3 -2
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/apps.d.ts +11 -3
- package/dist/commands/apps.js +86 -28
- package/dist/commands/apps.js.map +1 -1
- package/dist/commands/catalog.d.ts +4 -2
- package/dist/commands/catalog.js +166 -35
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +17 -0
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/runs.d.ts +7 -3
- package/dist/commands/runs.js +21 -5
- package/dist/commands/runs.js.map +1 -1
- package/dist/commands/scope-notice.d.ts +7 -0
- package/dist/commands/scope-notice.js +4 -11
- package/dist/commands/scope-notice.js.map +1 -1
- package/dist/commands/sources-roles.d.ts +5 -0
- package/dist/commands/sources-roles.js +235 -0
- package/dist/commands/sources-roles.js.map +1 -0
- package/dist/commands/sources.d.ts +5 -0
- package/dist/commands/sources.js +6 -1
- package/dist/commands/sources.js.map +1 -1
- package/dist/commands/team-agent-readiness.d.ts +18 -2
- package/dist/commands/team-agent-readiness.js +39 -39
- package/dist/commands/team-agent-readiness.js.map +1 -1
- package/dist/commands/team-agents-agents.d.ts +5 -2
- package/dist/commands/team-agents-agents.js +152 -15
- package/dist/commands/team-agents-agents.js.map +1 -1
- package/dist/commands/team-agents-define.d.ts +31 -0
- package/dist/commands/team-agents-define.js +176 -0
- package/dist/commands/team-agents-define.js.map +1 -0
- package/dist/commands/team-agents-mcp.js +112 -10
- package/dist/commands/team-agents-mcp.js.map +1 -1
- package/dist/commands/team-agents-triggers.d.ts +1 -1
- package/dist/commands/team-agents-triggers.js +137 -5
- package/dist/commands/team-agents-triggers.js.map +1 -1
- package/dist/commands/team-agents.d.ts +4 -1
- package/dist/commands/team-agents.js +17 -4
- package/dist/commands/team-agents.js.map +1 -1
- package/dist/commands/team-llm-key.d.ts +14 -0
- package/dist/commands/team-llm-key.js +122 -0
- package/dist/commands/team-llm-key.js.map +1 -0
- package/dist/commands/teams-connect.js +123 -31
- package/dist/commands/teams-connect.js.map +1 -1
- package/dist/commands/teams-lifecycle.d.ts +90 -0
- package/dist/commands/teams-lifecycle.js +457 -0
- package/dist/commands/teams-lifecycle.js.map +1 -0
- package/dist/commands/teams-onboard.d.ts +14 -0
- package/dist/commands/teams-onboard.js +62 -13
- package/dist/commands/teams-onboard.js.map +1 -1
- package/dist/commands/teams-overview.js +6 -2
- package/dist/commands/teams-overview.js.map +1 -1
- package/dist/commands/teams.d.ts +25 -5
- package/dist/commands/teams.js +101 -39
- package/dist/commands/teams.js.map +1 -1
- package/dist/commands/workflows.d.ts +37 -0
- package/dist/commands/workflows.js +589 -0
- package/dist/commands/workflows.js.map +1 -0
- package/dist/connect-fields.d.ts +22 -0
- package/dist/connect-fields.js +115 -0
- package/dist/connect-fields.js.map +1 -0
- package/dist/context.d.ts +12 -0
- package/dist/context.js +32 -9
- package/dist/context.js.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.js +357 -122
- package/dist/index.js.map +1 -1
- package/dist/invocation.d.ts +31 -0
- package/dist/invocation.js +58 -0
- package/dist/invocation.js.map +1 -0
- package/dist/runs-api.js +8 -3
- package/dist/runs-api.js.map +1 -1
- package/dist/safe-fs.d.ts +18 -0
- package/dist/safe-fs.js +57 -0
- package/dist/safe-fs.js.map +1 -1
- package/dist/secret-form.d.ts +48 -0
- package/dist/secret-form.js +212 -0
- package/dist/secret-form.js.map +1 -0
- package/dist/secret-input.d.ts +96 -0
- package/dist/secret-input.js +299 -0
- package/dist/secret-input.js.map +1 -0
- package/dist/team-connect-api.d.ts +78 -3
- package/dist/team-connect-api.js +17 -2
- package/dist/team-connect-api.js.map +1 -1
- package/dist/team-lifecycle-api.d.ts +435 -0
- package/dist/team-lifecycle-api.js +301 -0
- package/dist/team-lifecycle-api.js.map +1 -0
- package/dist/teams-api.d.ts +13 -1
- package/dist/teams-api.js +88 -27
- package/dist/teams-api.js.map +1 -1
- package/dist/unknown-command.d.ts +18 -0
- package/dist/unknown-command.js +50 -0
- package/dist/unknown-command.js.map +1 -0
- package/dist/workflows-api.d.ts +69 -0
- package/dist/workflows-api.js +182 -0
- package/dist/workflows-api.js.map +1 -0
- package/package.json +3 -3
- package/templates/AGENTS.md.tmpl +6 -4
- package/templates/claude-skill.md.tmpl +4 -1
- package/templates/package.json.tmpl +4 -4
- package/templates/skills/build-agent/SKILL.md +43 -10
- package/templates/skills/build-agent/references/agent-json.md +4 -1
- package/templates/skills/build-agent/references/app-setup.md +14 -7
- package/templates/skills/build-agent/references/rollout.md +26 -2
- package/templates/skills/build-agent/references/set-up-an-integration.md +46 -29
- package/templates/skills/build-integration/references/widget-design.md +1 -1
- package/templates/skills/ekanos-platform/SKILL.md +66 -14
- package/templates/skills/polish-widgets/references/patterns.md +3 -3
package/dist/index.js
CHANGED
|
@@ -33,11 +33,13 @@ import { runUpgrade } from './commands/upgrade.js';
|
|
|
33
33
|
import { runUse } from './commands/use.js';
|
|
34
34
|
import { runValidate } from './commands/validate.js';
|
|
35
35
|
import { runWhoami } from './commands/whoami.js';
|
|
36
|
+
import { runWorkflows } from './commands/workflows.js';
|
|
36
37
|
import { CliContext } from './context.js';
|
|
37
38
|
import { SDK_DOCS_URL, docsPage } from './docs-links.js';
|
|
38
39
|
import { toCliError, usageError } from './errors.js';
|
|
39
|
-
import {
|
|
40
|
+
import { detectInvocation, setInvocation } from './invocation.js';
|
|
40
41
|
import { parseArgv } from './parse-argv.js';
|
|
42
|
+
import { unknownCommand } from './unknown-command.js';
|
|
41
43
|
export { CliContext } from './context.js';
|
|
42
44
|
export { EXIT_CODES, ERROR_CODES } from './exit-codes.js';
|
|
43
45
|
const GLOBAL_SPECS = {
|
|
@@ -61,6 +63,34 @@ const DIR = {
|
|
|
61
63
|
type: 'string',
|
|
62
64
|
description: 'Project directory, where ekanos.json and relative paths are read (default: the current one)',
|
|
63
65
|
};
|
|
66
|
+
/**
|
|
67
|
+
* Where a secret comes from without a terminal (`secret-input.ts`), for every
|
|
68
|
+
* command that takes one. Never a value: a secret in argv lands in shell
|
|
69
|
+
* history and the process list.
|
|
70
|
+
*/
|
|
71
|
+
const SECRET_INPUT = {
|
|
72
|
+
'secret-env': {
|
|
73
|
+
type: 'string',
|
|
74
|
+
description: 'The secret, from this environment variable (its NAME, never the value)',
|
|
75
|
+
},
|
|
76
|
+
'secret-file': {
|
|
77
|
+
type: 'string',
|
|
78
|
+
description: 'The secret, from this file: yours, mode 600, not a symlink',
|
|
79
|
+
},
|
|
80
|
+
'secret-stdin': {
|
|
81
|
+
type: 'boolean',
|
|
82
|
+
description: 'The secret, piped in on stdin',
|
|
83
|
+
},
|
|
84
|
+
'set-secret': {
|
|
85
|
+
type: 'string',
|
|
86
|
+
repeatable: true,
|
|
87
|
+
description: 'One field of a form: <field>=env:<NAME> | file:<path> | stdin',
|
|
88
|
+
},
|
|
89
|
+
browser: {
|
|
90
|
+
type: 'boolean',
|
|
91
|
+
description: 'Type the secret into a one-time form in your browser on this computer (never shown to the run that asked)',
|
|
92
|
+
},
|
|
93
|
+
};
|
|
64
94
|
const COMMAND_SPECS = {
|
|
65
95
|
init: {
|
|
66
96
|
slug: {
|
|
@@ -165,179 +195,227 @@ const COMMAND_SPECS = {
|
|
|
165
195
|
source: SOURCE,
|
|
166
196
|
yes: {
|
|
167
197
|
type: 'boolean',
|
|
168
|
-
description: 'Confirm products disable, scopes remove',
|
|
198
|
+
description: 'Confirm products disable, scopes remove, roles delete',
|
|
199
|
+
},
|
|
200
|
+
// `sources roles create|update`.
|
|
201
|
+
'display-name': {
|
|
202
|
+
type: 'string',
|
|
203
|
+
description: "roles create|update: the role's display name",
|
|
204
|
+
},
|
|
205
|
+
description: {
|
|
206
|
+
type: 'string',
|
|
207
|
+
description: "roles create|update: the role's description",
|
|
208
|
+
},
|
|
209
|
+
level: {
|
|
210
|
+
type: 'string',
|
|
211
|
+
description: 'roles create|update: its level, 1 to 1000; lower ranks higher (default 100)',
|
|
212
|
+
},
|
|
213
|
+
permission: {
|
|
214
|
+
type: 'string',
|
|
215
|
+
repeatable: true,
|
|
216
|
+
description: 'roles create|update: a permission it holds (update: replaces them all)',
|
|
169
217
|
},
|
|
218
|
+
grant: {
|
|
219
|
+
type: 'string',
|
|
220
|
+
repeatable: true,
|
|
221
|
+
description: 'roles update: add this permission',
|
|
222
|
+
},
|
|
223
|
+
revoke: {
|
|
224
|
+
type: 'string',
|
|
225
|
+
repeatable: true,
|
|
226
|
+
description: 'roles update: take this permission away',
|
|
227
|
+
},
|
|
228
|
+
// `sources people`.
|
|
229
|
+
search: {
|
|
230
|
+
type: 'string',
|
|
231
|
+
description: 'people: only those whose name or email matches',
|
|
232
|
+
},
|
|
233
|
+
page: { type: 'string', description: 'people: which page, from 1' },
|
|
170
234
|
},
|
|
171
235
|
catalog: {
|
|
172
236
|
host: HOST,
|
|
173
237
|
source: SOURCE,
|
|
174
238
|
dir: DIR,
|
|
175
239
|
},
|
|
176
|
-
apps: {
|
|
177
|
-
host: HOST,
|
|
178
|
-
source: SOURCE,
|
|
179
|
-
dir: DIR,
|
|
180
|
-
'no-wait': {
|
|
240
|
+
apps: Object.assign({ host: HOST, source: SOURCE, dir: DIR, 'no-wait': {
|
|
181
241
|
type: 'boolean',
|
|
182
242
|
description: 'connect: print the links and return without waiting',
|
|
183
|
-
},
|
|
184
|
-
yes: {
|
|
243
|
+
}, yes: {
|
|
185
244
|
type: 'boolean',
|
|
186
245
|
description: 'disconnect: confirm without the question (needed in a script or agent run)',
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
connection: {
|
|
246
|
+
}, set: {
|
|
247
|
+
type: 'string',
|
|
248
|
+
repeatable: true,
|
|
249
|
+
description: 'set, connect: <name>=<value> for a field that is not a secret (set: clientId)',
|
|
250
|
+
} }, SECRET_INPUT),
|
|
251
|
+
teams: Object.assign(Object.assign({ host: HOST, source: SOURCE, dir: DIR, connection: {
|
|
194
252
|
type: 'string',
|
|
195
253
|
description: 'connect, app set: which of the integration\'s connections (e.g. "agent" for Linear\'s agent)',
|
|
196
|
-
},
|
|
254
|
+
},
|
|
197
255
|
// `teams app set`: which fields to enter, non-secret values, removals.
|
|
198
256
|
field: {
|
|
199
257
|
type: 'string',
|
|
200
258
|
repeatable: true,
|
|
201
259
|
description: 'app set: enter just this field at your terminal',
|
|
202
|
-
},
|
|
203
|
-
set: {
|
|
260
|
+
}, set: {
|
|
204
261
|
type: 'string',
|
|
205
262
|
repeatable: true,
|
|
206
|
-
description: 'app set: <name>=<value> for a
|
|
207
|
-
},
|
|
208
|
-
|
|
263
|
+
description: 'app set, connect: <name>=<value> for a field that is not a secret (a list as a,b)',
|
|
264
|
+
}, self: {
|
|
265
|
+
type: 'boolean',
|
|
266
|
+
description: 'members add: you join the team now, with no invitation email',
|
|
267
|
+
} }, SECRET_INPUT), { clear: {
|
|
209
268
|
type: 'string',
|
|
210
269
|
repeatable: true,
|
|
211
270
|
description: "app set: remove this field's saved value",
|
|
212
|
-
},
|
|
213
|
-
slug: {
|
|
271
|
+
}, slug: {
|
|
214
272
|
type: 'string',
|
|
215
273
|
description: "create: the team's slug (default: from its name)",
|
|
216
|
-
},
|
|
217
|
-
owner: {
|
|
274
|
+
}, owner: {
|
|
218
275
|
type: 'string',
|
|
219
276
|
description: 'create: invite this email as the owner instead of you',
|
|
220
|
-
},
|
|
221
|
-
role: {
|
|
277
|
+
}, role: {
|
|
222
278
|
type: 'string',
|
|
223
|
-
description: 'members invite: the role to
|
|
224
|
-
},
|
|
225
|
-
yes: {
|
|
279
|
+
description: 'members add, members invite: the role to give (default member)',
|
|
280
|
+
}, yes: {
|
|
226
281
|
type: 'boolean',
|
|
227
|
-
description: 'Confirm a change that removes, pauses, revokes or opens something up (members remove, webhook, disconnect, agents disable, triggers add slack, triggers remove|rotate, links remove, mcp remove, scope set that drops a scope)',
|
|
228
|
-
},
|
|
282
|
+
description: 'Confirm a change that removes, pauses, revokes or opens something up (members remove, leave, groups delete, groups members remove, webhook, disconnect, agents disable|archive, mcp detach, triggers add slack|disable, triggers edit of a slack audience, triggers remove|rotate, links remove, mcp remove, scope set that drops a scope)',
|
|
283
|
+
},
|
|
229
284
|
// `teams agents|triggers|links|mcp` (team-agents.ts).
|
|
230
285
|
as: {
|
|
231
286
|
type: 'string',
|
|
232
|
-
description: 'connect: the member who signs in; agents enable: the member the agent runs as',
|
|
233
|
-
},
|
|
287
|
+
description: 'connect: the member who signs in; agents enable: the member the agent runs as (chosen once, when it is turned on)',
|
|
288
|
+
},
|
|
234
289
|
// `teams agents enable|pin … --draft`: test the unpublished draft there.
|
|
235
290
|
draft: {
|
|
236
291
|
type: 'boolean',
|
|
237
292
|
description: "agents enable|pin: put this team alone on the template's unpublished draft",
|
|
238
|
-
},
|
|
239
|
-
// `teams agents enable|policy`: also confirm, as yourself,
|
|
240
|
-
// agent may use (whoever sets it up confirms it, plan 247.2).
|
|
293
|
+
},
|
|
294
|
+
// `teams agents enable|policy|create|apply`: also confirm, as yourself,
|
|
295
|
+
// what the agent may use (whoever sets it up confirms it, plan 247.2).
|
|
241
296
|
'confirm-access': {
|
|
242
297
|
type: 'boolean',
|
|
243
|
-
description: 'agents enable|policy: also confirm, as yourself, what it may use',
|
|
244
|
-
},
|
|
245
|
-
|
|
298
|
+
description: 'agents enable|policy|create|apply: also confirm, as yourself, what it may use',
|
|
299
|
+
},
|
|
300
|
+
// `teams agents create|apply`: the agent.json, read as `agents apply`
|
|
301
|
+
// reads it (team-agents-define.ts).
|
|
302
|
+
from: {
|
|
303
|
+
type: 'string',
|
|
304
|
+
description: 'agents create: the agent directory or agent.json',
|
|
305
|
+
}, personal: {
|
|
306
|
+
type: 'boolean',
|
|
307
|
+
description: 'agents create|apply: your own agent, which acts for you and only you change',
|
|
308
|
+
}, 'base-version': {
|
|
309
|
+
type: 'string',
|
|
310
|
+
description: 'agents apply: the agent version your edit starts from ("teams agents show")',
|
|
311
|
+
}, overwrite: {
|
|
312
|
+
type: 'boolean',
|
|
313
|
+
description: 'agents apply: replace a newer version on the host anyway',
|
|
314
|
+
}, skills: {
|
|
315
|
+
type: 'boolean',
|
|
316
|
+
description: 'agents create|apply: --no-skills skips pushing <dir>/skills/<slug>/ as team skills',
|
|
317
|
+
}, reads: {
|
|
246
318
|
type: 'string',
|
|
247
319
|
description: 'agents policy: auto|approve for every read tool',
|
|
248
|
-
},
|
|
249
|
-
writes: {
|
|
320
|
+
}, writes: {
|
|
250
321
|
type: 'string',
|
|
251
322
|
description: 'agents policy: auto|approve for every write tool',
|
|
252
|
-
},
|
|
253
|
-
effect: {
|
|
323
|
+
}, effect: {
|
|
254
324
|
type: 'string',
|
|
255
325
|
description: 'Not read: "teams mcp effect" takes the effect as an argument',
|
|
256
|
-
},
|
|
257
|
-
|
|
258
|
-
|
|
326
|
+
}, agent: {
|
|
327
|
+
type: 'string',
|
|
328
|
+
description: 'mcp refresh: list again the tools of every server this agent has',
|
|
329
|
+
}, kind: { type: 'string', description: 'links add: talk|delegate' }, mode: {
|
|
259
330
|
type: 'string',
|
|
260
331
|
description: 'links add: await|handoff, for a delegate link',
|
|
261
|
-
},
|
|
262
|
-
url: { type: 'string', description: "mcp add: the server's URL" },
|
|
263
|
-
auth: {
|
|
332
|
+
}, url: { type: 'string', description: "mcp add: the server's URL" }, auth: {
|
|
264
333
|
type: 'string',
|
|
265
334
|
description: 'mcp add: none|token|oauth (default oauth)',
|
|
266
|
-
},
|
|
267
|
-
name: { type: 'string', description: "mcp add: the server's display name" },
|
|
268
|
-
cron: {
|
|
335
|
+
}, name: {
|
|
269
336
|
type: 'string',
|
|
270
|
-
description:
|
|
271
|
-
},
|
|
272
|
-
|
|
337
|
+
description: "mcp add: the server's display name; groups update: the group's new name",
|
|
338
|
+
},
|
|
339
|
+
// `teams groups create|update`.
|
|
340
|
+
description: {
|
|
273
341
|
type: 'string',
|
|
274
|
-
description:
|
|
275
|
-
},
|
|
276
|
-
prompt: {
|
|
342
|
+
description: "groups create|update: the group's description",
|
|
343
|
+
}, products: {
|
|
277
344
|
type: 'string',
|
|
278
|
-
description: '
|
|
279
|
-
},
|
|
345
|
+
description: 'groups create|update: the products it narrows to, comma-separated (none: no narrowing)',
|
|
346
|
+
},
|
|
347
|
+
// `teams disconnect|health <team> <product> --mine`: the caller's own.
|
|
348
|
+
mine: {
|
|
349
|
+
type: 'boolean',
|
|
350
|
+
description: "disconnect, health <product>: your own personal connection, never another member's",
|
|
351
|
+
},
|
|
352
|
+
// `teams health <team> <product> --run`.
|
|
353
|
+
run: {
|
|
354
|
+
type: 'boolean',
|
|
355
|
+
description: "health: run the integration's health check now",
|
|
356
|
+
}, cron: {
|
|
357
|
+
type: 'string',
|
|
358
|
+
description: 'triggers add|edit schedule: a cron expression',
|
|
359
|
+
}, timezone: {
|
|
360
|
+
type: 'string',
|
|
361
|
+
description: 'triggers add|edit schedule: an IANA time zone (default UTC)',
|
|
362
|
+
}, prompt: {
|
|
363
|
+
type: 'string',
|
|
364
|
+
description: 'triggers add|edit: what the agent is told when it fires',
|
|
365
|
+
},
|
|
280
366
|
// Repeatable `field=value`, or one JSON object — as at the template level.
|
|
281
367
|
filter: {
|
|
282
368
|
type: 'string',
|
|
283
369
|
repeatable: true,
|
|
284
|
-
description: 'triggers add event: field=a,b (repeatable) or one JSON object',
|
|
285
|
-
},
|
|
370
|
+
description: 'triggers add|edit event: field=a,b (repeatable) or one JSON object',
|
|
371
|
+
},
|
|
286
372
|
// `teams <area> … --team <slug>`: the team, in place of the positional.
|
|
287
373
|
team: {
|
|
288
374
|
type: 'string',
|
|
289
375
|
description: 'The team, in place of the <team> argument (teams <area> … --team <slug>)',
|
|
290
|
-
},
|
|
376
|
+
},
|
|
291
377
|
// `teams triggers add … slack|linear`: where it answers. `--no-mention`
|
|
292
378
|
// is the negation of `mention`.
|
|
293
379
|
channel: {
|
|
294
380
|
type: 'string',
|
|
295
381
|
repeatable: true,
|
|
296
|
-
description: 'triggers add slack: a channel it answers in (#name or id)',
|
|
297
|
-
},
|
|
298
|
-
dms: {
|
|
382
|
+
description: 'triggers add|edit slack: a channel it answers in (#name or id); edit replaces the list',
|
|
383
|
+
}, dms: {
|
|
299
384
|
type: 'boolean',
|
|
300
|
-
description: 'triggers add slack: also answer direct messages',
|
|
301
|
-
},
|
|
302
|
-
label: {
|
|
385
|
+
description: 'triggers add|edit slack: also answer direct messages (edit: --no-dms stops)',
|
|
386
|
+
}, label: {
|
|
303
387
|
type: 'string',
|
|
304
388
|
repeatable: true,
|
|
305
|
-
description: 'triggers add linear: a label that hands an issue to it',
|
|
306
|
-
},
|
|
307
|
-
mention: {
|
|
389
|
+
description: 'triggers add|edit linear: a label that hands an issue to it; edit replaces the list',
|
|
390
|
+
}, mention: {
|
|
308
391
|
type: 'boolean',
|
|
309
|
-
description: 'triggers add linear: --no-mention ignores @mentions',
|
|
310
|
-
},
|
|
392
|
+
description: 'triggers add|edit linear: --no-mention ignores @mentions (edit: --mention answers them)',
|
|
393
|
+
},
|
|
311
394
|
// `teams connect`: `--no-wait`, `--no-open` (the negation of `open`),
|
|
312
395
|
// `--link-only`.
|
|
313
396
|
'no-wait': {
|
|
314
397
|
type: 'boolean',
|
|
315
398
|
description: 'connect: print the sign-in link and return at once',
|
|
316
|
-
},
|
|
317
|
-
open: {
|
|
399
|
+
}, open: {
|
|
318
400
|
type: 'boolean',
|
|
319
401
|
description: 'connect: --no-open prints the link without opening a browser',
|
|
320
|
-
},
|
|
321
|
-
'link-only': {
|
|
402
|
+
}, 'link-only': {
|
|
322
403
|
type: 'boolean',
|
|
323
404
|
description: "connect: print the team's page instead of connecting",
|
|
324
|
-
},
|
|
405
|
+
},
|
|
325
406
|
// `teams events <team> [--product] [--since] [--limit]`.
|
|
326
407
|
product: {
|
|
327
408
|
type: 'string',
|
|
328
409
|
description: 'events: only this product (or name it after the team)',
|
|
329
|
-
},
|
|
330
|
-
since: {
|
|
410
|
+
}, since: {
|
|
331
411
|
type: 'string',
|
|
332
412
|
description: 'events: since 30m, 24h, 7d or a date',
|
|
333
|
-
},
|
|
334
|
-
limit: { type: 'string', description: 'events: how many, 1 to 100' },
|
|
413
|
+
}, limit: { type: 'string', description: 'events: how many, 1 to 100' },
|
|
335
414
|
// `teams connect --reconnect`.
|
|
336
415
|
reconnect: {
|
|
337
416
|
type: 'boolean',
|
|
338
417
|
description: 'connect: connect again though it reads as connected (revoked or expired)',
|
|
339
|
-
},
|
|
340
|
-
},
|
|
418
|
+
} }),
|
|
341
419
|
reviewers: {
|
|
342
420
|
host: HOST,
|
|
343
421
|
source: SOURCE,
|
|
@@ -542,6 +620,51 @@ const COMMAND_SPECS = {
|
|
|
542
620
|
description: 'edit: a file with the reply to send instead',
|
|
543
621
|
},
|
|
544
622
|
},
|
|
623
|
+
workflows: {
|
|
624
|
+
host: HOST,
|
|
625
|
+
source: SOURCE,
|
|
626
|
+
dir: DIR,
|
|
627
|
+
team: { type: 'string', description: 'The team whose workflows these are' },
|
|
628
|
+
all: { type: 'boolean', description: 'list: include archived workflows' },
|
|
629
|
+
out: {
|
|
630
|
+
type: 'string',
|
|
631
|
+
description: 'pull: where to write workflow.json (default workflows/<name>)',
|
|
632
|
+
},
|
|
633
|
+
force: {
|
|
634
|
+
type: 'boolean',
|
|
635
|
+
description: 'pull: overwrite a local workflow.json that differs',
|
|
636
|
+
},
|
|
637
|
+
update: {
|
|
638
|
+
type: 'string',
|
|
639
|
+
description: 'apply: the workflow (id or name) to replace; without it apply creates a draft',
|
|
640
|
+
},
|
|
641
|
+
'confirm-access': {
|
|
642
|
+
type: 'boolean',
|
|
643
|
+
description: 'enable: approve, as yourself, what its Custom Code reaches (hosts, writes)',
|
|
644
|
+
},
|
|
645
|
+
'dry-run': {
|
|
646
|
+
type: 'boolean',
|
|
647
|
+
description: 'run: rehearse it (writes recorded, not sent; gates pass); a draft may run so',
|
|
648
|
+
},
|
|
649
|
+
input: {
|
|
650
|
+
type: 'string',
|
|
651
|
+
description: 'run --dry-run: a JSON file read as the sample trigger.*',
|
|
652
|
+
},
|
|
653
|
+
follow: {
|
|
654
|
+
type: 'boolean',
|
|
655
|
+
description: 'run: wait, printing each step, until it ends or waits on a gate',
|
|
656
|
+
},
|
|
657
|
+
workflow: {
|
|
658
|
+
type: 'string',
|
|
659
|
+
description: "runs list: only this workflow's runs (id or name)",
|
|
660
|
+
},
|
|
661
|
+
status: {
|
|
662
|
+
type: 'string',
|
|
663
|
+
description: 'runs list: only runs in this status (running, waiting_approval, completed, rejected, failed, canceled)',
|
|
664
|
+
},
|
|
665
|
+
reason: { type: 'string', description: 'approvals reject: why' },
|
|
666
|
+
yes: { type: 'boolean', description: 'runs cancel: confirm' },
|
|
667
|
+
},
|
|
545
668
|
use: {
|
|
546
669
|
host: HOST,
|
|
547
670
|
dir: DIR,
|
|
@@ -597,6 +720,8 @@ const POSITIONAL_COMMANDS = {
|
|
|
597
720
|
knowledge: ['subcommand', 'path-or-query'],
|
|
598
721
|
runs: ['subcommand', 'agent-key-or-run-id'],
|
|
599
722
|
approvals: ['subcommand', 'approval-id'],
|
|
723
|
+
// `workflows runs show <run-id>` is the longest form.
|
|
724
|
+
workflows: ['subcommand', 'workflow-or-verb', 'id'],
|
|
600
725
|
// `triggers <key> add event <trigger-key>` is the longest form: five tokens.
|
|
601
726
|
agents: ['subcommand', 'key-or-path', 'action', 'arg', 'value'],
|
|
602
727
|
};
|
|
@@ -630,13 +755,27 @@ const USAGE = [
|
|
|
630
755
|
' and pointed at /admin) | scopes (each product scope: its',
|
|
631
756
|
' products and how many teams hold it; a team sees in the app',
|
|
632
757
|
" only its scopes' products) | scopes add <scope> <product> |",
|
|
633
|
-
' scopes remove <scope> <product> --yes',
|
|
634
|
-
'
|
|
758
|
+
' scopes remove <scope> <product> --yes | roles [list] (the roles',
|
|
759
|
+
' every team of the Source hands out, each with its level and',
|
|
760
|
+
' permissions) | roles create <name> [--display-name <text>]',
|
|
761
|
+
' [--description <text>] [--level <n>] [--permission <p>]… |',
|
|
762
|
+
' roles update <role> [--display-name] [--description] [--level]',
|
|
763
|
+
' [--permission <p>]… (replaces) [--grant <p>]… [--revoke <p>]… |',
|
|
764
|
+
' roles delete <role> [--yes] (owner, admin and member are system',
|
|
765
|
+
" roles: never changed or deleted; a held role isn't deleted) |",
|
|
766
|
+
' people [--search <text>] [--page <n>] (everyone with access, one',
|
|
767
|
+
' row per person, with their teams and role on each)',
|
|
768
|
+
' catalog What a source can already use, and how to set it up:',
|
|
769
|
+
' Experiences, then Integrations; one product shows its tools',
|
|
770
|
+
' with their inputs and whose connection agent runs use',
|
|
635
771
|
' ("ekanos catalog [<product-slug>] --source <slug>", --json)',
|
|
636
772
|
" apps The Source's app for an integration teams sign in through:",
|
|
637
773
|
' show <product> | set <product> (Source admin; takes the secret',
|
|
638
|
-
' at your terminal, Enter keeps a saved value
|
|
639
|
-
' <
|
|
774
|
+
' at your terminal, Enter keeps a saved value; without one,',
|
|
775
|
+
' --set clientId=<id> and --secret-env <NAME> | --secret-file',
|
|
776
|
+
' <path> | --secret-stdin | --browser) | connect',
|
|
777
|
+
' <product> [--no-wait] [--set <field>=<value>]… [--set-secret',
|
|
778
|
+
' <field>=env:<NAME>|file:<path>|stdin]… [--browser] (one',
|
|
640
779
|
" connection for the whole Source, used by the Source's provided",
|
|
641
780
|
' agents in every team) | disconnect <product> [--yes] (a',
|
|
642
781
|
' script or agent run needs --yes) | list',
|
|
@@ -644,15 +783,32 @@ const USAGE = [
|
|
|
644
783
|
' create <name> [--slug <slug>] [--owner <email>] (you own it',
|
|
645
784
|
' unless --owner, who is invited as owner) |',
|
|
646
785
|
' rename <team> <name> (the slug follows the name, as in the app) |',
|
|
647
|
-
' members list <team> | members
|
|
648
|
-
' <role>] (
|
|
786
|
+
' members list <team> | members add <team> --self | <email>',
|
|
787
|
+
' [--role <role>] (a member now, no email: you, or someone with',
|
|
788
|
+
' an Ekanos account on the Source) | members invite <team> <email>',
|
|
789
|
+
' [--role <role>] (default member; sends the invitation email) |',
|
|
649
790
|
' members role <team> <email> <role> | members remove <team>',
|
|
650
|
-
|
|
791
|
+
' <email> --yes | members resend <team> <email> (a live',
|
|
792
|
+
' invitation is resent, an expired one renewed) |',
|
|
793
|
+
" roles list <team> (each role's permissions) |",
|
|
794
|
+
' leave <team> [--yes] (you leave it; never the primary owner) |',
|
|
795
|
+
' groups list <team> | groups create <team> <name> [--description',
|
|
796
|
+
' <text>] [--products <slug,slug>] | groups update <team> <group>',
|
|
797
|
+
' [--name <name>] [--description <text>] [--products <slug,…>|none]',
|
|
798
|
+
' | groups delete <team> <group> [--yes] | groups members',
|
|
799
|
+
' add|remove <team> <group> <email> (leave, groups delete and',
|
|
800
|
+
' remove ask first; a script or agent run needs --yes) |',
|
|
801
|
+
' health <team> [<product>] [--run] (each connected integration',
|
|
802
|
+
' and its health; --run checks one now; <product> --mine: your own',
|
|
803
|
+
' personal connection, any seat, as a member) | workspace list <team> |',
|
|
804
|
+
' workspace default <team> <workspace> (where the team lands) |',
|
|
651
805
|
' connect <team> <product> [--connection <id>] [--as',
|
|
652
|
-
' <member-email>] [--
|
|
653
|
-
' [--reconnect] (connects',
|
|
654
|
-
" it: asks the form's fields at your terminal
|
|
655
|
-
'
|
|
806
|
+
' <member-email>] [--set <field>=<value>]… [--no-wait] [--no-open]',
|
|
807
|
+
' [--link-only] [--reconnect] (connects',
|
|
808
|
+
" it: asks the form's fields at your terminal or takes them from",
|
|
809
|
+
' --set (a list as a,b; secrets and JSON only at a prompt; an optional',
|
|
810
|
+
' one can be skipped), then opens the sign-in for you — your own',
|
|
811
|
+
' connection, for a personal product — or the member --as names, and waits;',
|
|
656
812
|
" --connection agent installs the team's Linear agent (its own",
|
|
657
813
|
' Linear app, as a member), which @mention and assign triggers',
|
|
658
814
|
" need; --link-only prints the team's page; --reconnect connects",
|
|
@@ -662,14 +818,22 @@ const USAGE = [
|
|
|
662
818
|
' Slack, or the Ekanos Agents app for Linear, which slack and',
|
|
663
819
|
' linear triggers answer through; same link-and-wait) |',
|
|
664
820
|
" disconnect <team> <product> --yes (takes the team's connection",
|
|
665
|
-
" and its tokens down; its own app's saved fields stay
|
|
821
|
+
" and its tokens down; its own app's saved fields stay; --mine:",
|
|
822
|
+
" your own personal connection, never another member's) |",
|
|
666
823
|
' list | show <team> (one screen: members, each integration and',
|
|
667
824
|
' whose connection it is, each agent live or the next step) |',
|
|
668
825
|
' show <team> <product> (a checklist: fields, callback',
|
|
669
826
|
' URLs, webhooks, connect link) | app set <team> <product>',
|
|
670
827
|
' [--connection <id>] [--field <name>]… [--set <name>=<value>]…',
|
|
671
|
-
' [--clear <name>]…
|
|
672
|
-
'
|
|
828
|
+
' [--clear <name>]… [--set-secret <name>=env:<NAME>|file:<path>|stdin]…',
|
|
829
|
+
' [--browser] (any one field at a time; a field you skip keeps',
|
|
830
|
+
' its saved value; a secret at your terminal, from the',
|
|
831
|
+
' environment, a private file, stdin or a browser form, never',
|
|
832
|
+
' as an argument) |',
|
|
833
|
+
' llm-key show <team> | llm-key set <team> [--secret-env <NAME> |',
|
|
834
|
+
' --secret-file <path> | --secret-stdin | --browser] | llm-key',
|
|
835
|
+
" remove <team> --yes (the team's own Anthropic key, as its",
|
|
836
|
+
' settings page sets it; show gives only its last four characters) |',
|
|
673
837
|
' webhook <team> <product> [<webhook-id>] [--yes] (URL saved to a 0600 file under ~/.ekanos/secrets, never printed) |',
|
|
674
838
|
' events <team> [<product>] [--product <slug>] [--since 24h|7d|<date>]',
|
|
675
839
|
' [--limit <n>] (the integration events recorded for the team, each',
|
|
@@ -681,11 +845,21 @@ const USAGE = [
|
|
|
681
845
|
' agents list <team> | agents show <team> <key> (is it live, and if',
|
|
682
846
|
' not, why: each connection and whose it is, each trigger and how its',
|
|
683
847
|
' events arrive, last event and run, one Next command)',
|
|
848
|
+
' | agents create <team> --from <dir|agent.json> [--personal]',
|
|
849
|
+
" [--confirm-access] [--no-skills] (the team's own agent, or with",
|
|
850
|
+
' --personal your own, from the agent.json "agents apply" reads;',
|
|
851
|
+
' you become its creator, so you must be an active member of the',
|
|
852
|
+
' team; it starts as a draft) | agents apply <team> <dir|agent.json>',
|
|
853
|
+
' [--personal] [--base-version <n>] [--overwrite] [--confirm-access]',
|
|
854
|
+
' (creates it, or changes it from the same file; a personal agent',
|
|
855
|
+
" is its creator's alone to change)",
|
|
684
856
|
' | agents enable <team> <key> [--as <member-email>]',
|
|
685
857
|
' [--draft] [--confirm-access] (--confirm-access: you also confirm',
|
|
686
858
|
' what it may use) | agents confirm <team> <key> (you confirm what',
|
|
687
859
|
' it may use, as yourself: whoever sets an agent up confirms it, never',
|
|
688
860
|
' a team member) | agents disable <team> <key> --yes | agents',
|
|
861
|
+
' archive <team> <key> [--yes] (off the list; runs and setup kept) |',
|
|
862
|
+
' agents unarchive <team> <key> (back, paused) | agents',
|
|
689
863
|
' unpin <team> <key> | agents pin <team> <key> <version> | agents pin',
|
|
690
864
|
' <team> <key> --draft (this team only runs the unpublished draft, by',
|
|
691
865
|
' hand, every write waiting; the next publish puts it back to',
|
|
@@ -694,17 +868,29 @@ const USAGE = [
|
|
|
694
868
|
' [--reads auto|approve] [--writes auto|approve] [--confirm-access]',
|
|
695
869
|
' | agents skills <team> <key> [add|remove <skill>] (where the',
|
|
696
870
|
' template allows team skills; its own skills stay)',
|
|
697
|
-
'
|
|
871
|
+
' | agents tags <team> <key> [add|remove <tag>] (labels that grant',
|
|
872
|
+
' nothing; a tag the team lacks is made)',
|
|
873
|
+
' triggers list|add|remove <team> <key> … (add … schedule --cron',
|
|
874
|
+
' <expr> [--timezone <zone>] --prompt <text> | add … webhook --prompt',
|
|
875
|
+
' <text> (its token saved to a 0600 file, never printed; a personal',
|
|
876
|
+
" agent's webhook acts as its creator) | add … event <id>",
|
|
698
877
|
" [--filter field=a,b]… or --filter '<json>'; remove <trigger-id|key> --yes;",
|
|
699
878
|
' add … slack --channel',
|
|
700
879
|
' <#name|id>… [--dms] --yes | add … linear [--label <name>]…',
|
|
701
880
|
' [--no-mention], once installed with teams connect) | triggers',
|
|
702
881
|
" rotate <team> <key> <trigger-key|id> [--yes] (a webhook trigger's",
|
|
703
|
-
' new token, the old one revoked; saved to a 0600 file, never printed)
|
|
882
|
+
' new token, the old one revoked; saved to a 0600 file, never printed)',
|
|
883
|
+
' | triggers enable|disable <team> <key> <trigger-id|key> (disable',
|
|
884
|
+
' asks first, --yes in a script) | triggers edit <team> <key>',
|
|
885
|
+
' <trigger-id|key> [--prompt …] [--cron … --timezone …] [--filter …]',
|
|
886
|
+
' [--channel …] [--dms|--no-dms] [--label …] [--mention|--no-mention]',
|
|
887
|
+
' (in place: a webhook keeps its URL and token) | links list|add|remove',
|
|
704
888
|
' <team> <from-key> [<to-key> --kind talk|delegate --mode await|handoff]',
|
|
705
889
|
' (remove <link-id|to-key> [--kind <kind>] --yes)',
|
|
706
|
-
' | mcp list|add|status|token|effect|remove <team> [<server-key> …]',
|
|
707
|
-
' (remove needs --yes
|
|
890
|
+
' | mcp list|add|status|token|effect|refresh|remove <team> [<server-key> …]',
|
|
891
|
+
' (remove needs --yes; refresh <team> --agent <key>: every server it',
|
|
892
|
+
' has) | mcp attach|detach <team> <server-key> <agent-key> (detach',
|
|
893
|
+
' asks first, --yes in a script; where the template allows)',
|
|
708
894
|
' Every area also takes the team as --team <slug>.',
|
|
709
895
|
' ("ekanos teams --help" spells out each area)',
|
|
710
896
|
' reviewers Who decides agent reply drafts, for the Source admin:',
|
|
@@ -782,6 +968,25 @@ const USAGE = [
|
|
|
782
968
|
" approvals What a team's agent runs wait on: list --team <slug> |",
|
|
783
969
|
' approve|reject <id> --team <slug> [--reason "…"] |',
|
|
784
970
|
' edit <id> --team <slug> --body <file> (edit & send a reply draft)',
|
|
971
|
+
' The Source admin sees all; any other seat holder only what they',
|
|
972
|
+
" may decide (managing or reviewing the team's agents, a named",
|
|
973
|
+
" reviewer, a personal agent's creator). The first decision wins.",
|
|
974
|
+
" workflows A team's workflows, for the Source admin (each takes --team <slug>;",
|
|
975
|
+
' a workflow is named by its id or its name):',
|
|
976
|
+
' list [--all] | show <workflow> (status, trigger, Custom Code review',
|
|
977
|
+
' state, recent runs; --json: the definition) | pull <workflow>',
|
|
978
|
+
' [--out <dir>] [--force] (writes workflow.json, the JSON the editor',
|
|
979
|
+
' saves) | apply <file|dir> [--update <workflow>] (a new draft, or',
|
|
980
|
+
" that workflow's definition replaced; the editor's checks: shape,",
|
|
981
|
+
' tool effects, Custom Code security review, approval gates before',
|
|
982
|
+
' writes) | enable <workflow> [--confirm-access] (activation re-checks',
|
|
983
|
+
' it; Custom Code that writes or reaches a host needs your approval,',
|
|
984
|
+
' asked at a terminal) | disable <workflow> | run <workflow>',
|
|
985
|
+
' [--dry-run [--input <file.json>]] [--follow] (a live run needs it',
|
|
986
|
+
' on; --dry-run records writes instead of sending them) |',
|
|
987
|
+
' runs list [--workflow <workflow>] [--status <status>] | runs show',
|
|
988
|
+
' <run-id> | runs cancel <run-id> [--yes] | approvals list |',
|
|
989
|
+
' approvals approve|reject <id> [--reason "…"]',
|
|
785
990
|
' use Set this project\'s publish target ("ekanos use <source-slug>")',
|
|
786
991
|
' publish Validate, pack and submit the integration to an Ekanos host',
|
|
787
992
|
' upgrade Move this toolchain to a coherent target version, with',
|
|
@@ -796,7 +1001,7 @@ const USAGE = [
|
|
|
796
1001
|
' bare "ekanos upgrade" MUTATES the project (installs the target versions,',
|
|
797
1002
|
' verifies with validate + the test script, rolls back on any failure).',
|
|
798
1003
|
'',
|
|
799
|
-
'Host resolution (logout, whoami, status, sources, catalog, apps, teams, reviewers, routes, agents, skills, knowledge, runs, approvals, use, publish, upgrade):',
|
|
1004
|
+
'Host resolution (logout, whoami, status, sources, catalog, apps, teams, reviewers, routes, agents, skills, knowledge, runs, approvals, workflows, use, publish, upgrade):',
|
|
800
1005
|
' --host, else EKANOS_HOST, else the "host" field in ekanos.json, else the',
|
|
801
1006
|
' sole stored login. "ekanos publish" saves host and source to ekanos.json.',
|
|
802
1007
|
' "ekanos login" never reads ekanos.json for a host (--host, else',
|
|
@@ -825,16 +1030,17 @@ const USAGE = [
|
|
|
825
1030
|
* `process.exit`, so this stays fully testable.
|
|
826
1031
|
*/
|
|
827
1032
|
export async function run(argv, options = {}) {
|
|
828
|
-
var _a, _b, _c, _d;
|
|
1033
|
+
var _a, _b, _c, _d, _e, _f;
|
|
829
1034
|
const jsonFlag = scanJsonFlag(argv);
|
|
1035
|
+
setInvocation((_a = options.invocation) !== null && _a !== void 0 ? _a : detectInvocation((_b = options.env) !== null && _b !== void 0 ? _b : process.env), COMMANDS);
|
|
830
1036
|
const ctx = new CliContext({
|
|
831
1037
|
jsonFlag,
|
|
832
1038
|
stdout: options.stdout,
|
|
833
1039
|
stderr: options.stderr,
|
|
834
1040
|
env: options.env,
|
|
835
1041
|
});
|
|
836
|
-
const cwd = (
|
|
837
|
-
const env = (
|
|
1042
|
+
const cwd = (_c = options.cwd) !== null && _c !== void 0 ? _c : process.cwd();
|
|
1043
|
+
const env = (_d = options.env) !== null && _d !== void 0 ? _d : process.env;
|
|
838
1044
|
try {
|
|
839
1045
|
// `--version` is global and verb-independent, so it is answered before the
|
|
840
1046
|
// command is even resolved: `ekanos --version` and `ekanos validate
|
|
@@ -853,26 +1059,21 @@ export async function run(argv, options = {}) {
|
|
|
853
1059
|
tool: 'ekanos',
|
|
854
1060
|
error: 'unknown-command',
|
|
855
1061
|
commands: COMMANDS,
|
|
856
|
-
|
|
1062
|
+
help: 'ekanos --help',
|
|
857
1063
|
});
|
|
858
1064
|
throw usageError(`Unknown command or flag "${argv[0]}".`, `Run one of: ${COMMANDS.join(', ')}. See "ekanos --help".`);
|
|
859
1065
|
}
|
|
860
1066
|
if (!COMMANDS.includes(command)) {
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
given: command,
|
|
865
|
-
commands: COMMANDS,
|
|
866
|
-
usage: USAGE,
|
|
867
|
-
});
|
|
868
|
-
throw usageError(`Unknown command "${command}".`, `Run one of: ${COMMANDS.join(', ')}. See "ekanos --help".`);
|
|
1067
|
+
const unknown = unknownCommand(command, rest, COMMANDS);
|
|
1068
|
+
ctx.emitClaudeCodeHint(Object.assign(Object.assign({ tool: 'ekanos', error: 'unknown-command', given: command }, (unknown.suggestion ? { suggestion: unknown.suggestion } : {})), { commands: COMMANDS, help: 'ekanos --help' }));
|
|
1069
|
+
throw unknown.error;
|
|
869
1070
|
}
|
|
870
1071
|
const specs = Object.assign(Object.assign({}, GLOBAL_SPECS), COMMAND_SPECS[command]);
|
|
871
1072
|
const parsed = parseArgv(rest, specs);
|
|
872
1073
|
if (parsed.flags.help === true) {
|
|
873
1074
|
return emitCommandHelp(ctx, command);
|
|
874
1075
|
}
|
|
875
|
-
const positionalNames = (
|
|
1076
|
+
const positionalNames = (_e = POSITIONAL_COMMANDS[command]) !== null && _e !== void 0 ? _e : [];
|
|
876
1077
|
if (positionalNames.length === 0 && parsed.positionals.length > 0) {
|
|
877
1078
|
throw usageError(`"${command}" takes no positional arguments (got "${parsed.positionals[0]}").`, `Pass options as flags, e.g. "--dir <path>". See "ekanos ${command} --help".`);
|
|
878
1079
|
}
|
|
@@ -882,7 +1083,7 @@ export async function run(argv, options = {}) {
|
|
|
882
1083
|
`argument${positionalNames.length === 1 ? '' : 's'} (${usage}), ` +
|
|
883
1084
|
`got ${parsed.positionals.length}.`, `e.g. "ekanos ${command} ${usage}". See "ekanos ${command} --help".`);
|
|
884
1085
|
}
|
|
885
|
-
const dir = (
|
|
1086
|
+
const dir = (_f = parsed.flags.dir) !== null && _f !== void 0 ? _f : cwd;
|
|
886
1087
|
switch (command) {
|
|
887
1088
|
case 'init':
|
|
888
1089
|
return await runInit(ctx, {
|
|
@@ -952,8 +1153,11 @@ export async function run(argv, options = {}) {
|
|
|
952
1153
|
positionals: parsed.positionals,
|
|
953
1154
|
source: parsed.flags.source,
|
|
954
1155
|
yes: parsed.flags.yes === true,
|
|
1156
|
+
flags: parsed.flags,
|
|
955
1157
|
dir,
|
|
956
1158
|
env,
|
|
1159
|
+
stdinIsTTY: options.stdinIsTTY,
|
|
1160
|
+
ask: options.ask,
|
|
957
1161
|
});
|
|
958
1162
|
case 'catalog':
|
|
959
1163
|
return await runCatalog(ctx, {
|
|
@@ -977,6 +1181,10 @@ export async function run(argv, options = {}) {
|
|
|
977
1181
|
confirm: options.confirm,
|
|
978
1182
|
noWait: parsed.flags['no-wait'] === true,
|
|
979
1183
|
yes: parsed.flags.yes === true,
|
|
1184
|
+
flags: parsed.flags,
|
|
1185
|
+
readStdin: options.readStdin,
|
|
1186
|
+
openUrl: options.openUrl,
|
|
1187
|
+
secretFormTimeoutMs: options.secretFormTimeoutMs,
|
|
980
1188
|
});
|
|
981
1189
|
case 'teams':
|
|
982
1190
|
return await runTeams(ctx, {
|
|
@@ -1000,6 +1208,8 @@ export async function run(argv, options = {}) {
|
|
|
1000
1208
|
askSecret: options.askSecret,
|
|
1001
1209
|
openUrl: options.openUrl,
|
|
1002
1210
|
pollDelayMs: options.pollDelayMs,
|
|
1211
|
+
readStdin: options.readStdin,
|
|
1212
|
+
secretFormTimeoutMs: options.secretFormTimeoutMs,
|
|
1003
1213
|
});
|
|
1004
1214
|
case 'reviewers':
|
|
1005
1215
|
return await runReviewers(ctx, {
|
|
@@ -1112,6 +1322,30 @@ export async function run(argv, options = {}) {
|
|
|
1112
1322
|
stdinIsTTY: options.stdinIsTTY,
|
|
1113
1323
|
confirm: options.confirm,
|
|
1114
1324
|
});
|
|
1325
|
+
case 'workflows':
|
|
1326
|
+
return await runWorkflows(ctx, {
|
|
1327
|
+
host: parsed.flags.host,
|
|
1328
|
+
source: parsed.flags.source,
|
|
1329
|
+
positionals: parsed.positionals,
|
|
1330
|
+
team: parsed.flags.team,
|
|
1331
|
+
all: parsed.flags.all === true,
|
|
1332
|
+
out: parsed.flags.out,
|
|
1333
|
+
force: parsed.flags.force === true,
|
|
1334
|
+
update: parsed.flags.update,
|
|
1335
|
+
confirmAccess: parsed.flags['confirm-access'] === true,
|
|
1336
|
+
dryRun: parsed.flags['dry-run'] === true,
|
|
1337
|
+
input: parsed.flags.input,
|
|
1338
|
+
follow: parsed.flags.follow === true,
|
|
1339
|
+
workflow: parsed.flags.workflow,
|
|
1340
|
+
status: parsed.flags.status,
|
|
1341
|
+
reason: parsed.flags.reason,
|
|
1342
|
+
yes: parsed.flags.yes === true,
|
|
1343
|
+
dir,
|
|
1344
|
+
env,
|
|
1345
|
+
sleep: options.sleep,
|
|
1346
|
+
stdinIsTTY: options.stdinIsTTY,
|
|
1347
|
+
confirm: options.confirm,
|
|
1348
|
+
});
|
|
1115
1349
|
case 'use':
|
|
1116
1350
|
return await runUse(ctx, {
|
|
1117
1351
|
host: parsed.flags.host,
|
|
@@ -1221,11 +1455,12 @@ function emitVersion(ctx) {
|
|
|
1221
1455
|
}
|
|
1222
1456
|
const DOCS_FOOTER = `\nDocs: ${SDK_DOCS_URL} (commands: ${docsPage('cli/commands')})`;
|
|
1223
1457
|
function emitHelp(ctx) {
|
|
1458
|
+
// Short on purpose: the command list and where each command's usage is.
|
|
1459
|
+
// The full usage is already the result, and a hint line is not a manual.
|
|
1224
1460
|
ctx.emitClaudeCodeHint({
|
|
1225
1461
|
tool: 'ekanos',
|
|
1226
1462
|
commands: COMMANDS,
|
|
1227
|
-
|
|
1228
|
-
exitCodes: EXIT_CODES,
|
|
1463
|
+
help: 'ekanos <command> --help',
|
|
1229
1464
|
});
|
|
1230
1465
|
return ctx.succeed({ usage: USAGE, commands: COMMANDS, docs: SDK_DOCS_URL }, `${USAGE}${DOCS_FOOTER}`);
|
|
1231
1466
|
}
|