@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.
- 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.d.ts +2 -2
- package/dist/commands/agents.js +14 -20
- 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 +24 -6
- 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 +23 -17
- package/dist/commands/team-agent-readiness.js +57 -90
- package/dist/commands/team-agent-readiness.js.map +1 -1
- package/dist/commands/team-agents-agents.d.ts +8 -5
- package/dist/commands/team-agents-agents.js +173 -58
- 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 +7 -3
- 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 +367 -133
- 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 +90 -31
- 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 +56 -22
- 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 +40 -20
- package/templates/skills/build-agent/references/set-up-an-integration.md +46 -29
- package/templates/skills/build-agent/references/triggers.md +4 -3
- package/templates/skills/build-integration/references/widget-design.md +1 -1
- package/templates/skills/ekanos-platform/SKILL.md +77 -23
- 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
|
|
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,
|
|
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,
|
|
@@ -459,10 +537,10 @@ const COMMAND_SPECS = {
|
|
|
459
537
|
description: 'policy, triggers, links, overrides: publish the new version too (with --yes)',
|
|
460
538
|
},
|
|
461
539
|
// `publish | rollback` (and `--publish`): also confirm, as yourself, on
|
|
462
|
-
// every team
|
|
540
|
+
// every team running the version with no confirmation.
|
|
463
541
|
'confirm-access': {
|
|
464
542
|
type: 'boolean',
|
|
465
|
-
description: 'publish, rollback, --publish: also confirm, as yourself, on every team
|
|
543
|
+
description: 'publish, rollback, --publish: also confirm, as yourself, on every team on that version not yet confirmed',
|
|
466
544
|
},
|
|
467
545
|
},
|
|
468
546
|
skills: {
|
|
@@ -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,12 +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
|
-
' [--draft] [--confirm-access] (--confirm-access:
|
|
686
|
-
'
|
|
687
|
-
'
|
|
688
|
-
'
|
|
689
|
-
'
|
|
857
|
+
' [--draft] [--confirm-access] (--confirm-access: you also confirm',
|
|
858
|
+
' what it may use) | agents confirm <team> <key> (you confirm what',
|
|
859
|
+
' it may use, as yourself: whoever sets an agent up confirms it, never',
|
|
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',
|
|
690
863
|
' unpin <team> <key> | agents pin <team> <key> <version> | agents pin',
|
|
691
864
|
' <team> <key> --draft (this team only runs the unpublished draft, by',
|
|
692
865
|
' hand, every write waiting; the next publish puts it back to',
|
|
@@ -695,17 +868,29 @@ const USAGE = [
|
|
|
695
868
|
' [--reads auto|approve] [--writes auto|approve] [--confirm-access]',
|
|
696
869
|
' | agents skills <team> <key> [add|remove <skill>] (where the',
|
|
697
870
|
' template allows team skills; its own skills stay)',
|
|
698
|
-
'
|
|
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>",
|
|
699
877
|
" [--filter field=a,b]… or --filter '<json>'; remove <trigger-id|key> --yes;",
|
|
700
878
|
' add … slack --channel',
|
|
701
879
|
' <#name|id>… [--dms] --yes | add … linear [--label <name>]…',
|
|
702
880
|
' [--no-mention], once installed with teams connect) | triggers',
|
|
703
881
|
" rotate <team> <key> <trigger-key|id> [--yes] (a webhook trigger's",
|
|
704
|
-
' 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',
|
|
705
888
|
' <team> <from-key> [<to-key> --kind talk|delegate --mode await|handoff]',
|
|
706
889
|
' (remove <link-id|to-key> [--kind <kind>] --yes)',
|
|
707
|
-
' | mcp list|add|status|token|effect|remove <team> [<server-key> …]',
|
|
708
|
-
' (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)',
|
|
709
894
|
' Every area also takes the team as --team <slug>.',
|
|
710
895
|
' ("ekanos teams --help" spells out each area)',
|
|
711
896
|
' reviewers Who decides agent reply drafts, for the Source admin:',
|
|
@@ -727,10 +912,10 @@ const USAGE = [
|
|
|
727
912
|
' archive <key> --yes (refused while any team has it on; lists',
|
|
728
913
|
' each team and the command to turn it off) | unarchive <key>',
|
|
729
914
|
' publish <key> [--to <n>] [--confirm-access] --yes | rollback <key>',
|
|
730
|
-
' --to <n> [--confirm-access] --yes (
|
|
731
|
-
'
|
|
732
|
-
'
|
|
733
|
-
'
|
|
915
|
+
' --to <n> [--confirm-access] --yes (every following team moves; one',
|
|
916
|
+
' that had confirmed stays confirmed, in your name: your publish is the',
|
|
917
|
+
' confirmation; --confirm-access: you also confirm every team on that',
|
|
918
|
+
' version not yet confirmed; the output lists teams pinned elsewhere)',
|
|
734
919
|
' test <key> --team <slug> (--prompt "…" | --input <file.json>)',
|
|
735
920
|
' [--follow] (runs the latest, unpublished version on one team;',
|
|
736
921
|
' same grant, policy, approvals and audit; marked as a test; to',
|
|
@@ -783,6 +968,25 @@ const USAGE = [
|
|
|
783
968
|
" approvals What a team's agent runs wait on: list --team <slug> |",
|
|
784
969
|
' approve|reject <id> --team <slug> [--reason "…"] |',
|
|
785
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 "…"]',
|
|
786
990
|
' use Set this project\'s publish target ("ekanos use <source-slug>")',
|
|
787
991
|
' publish Validate, pack and submit the integration to an Ekanos host',
|
|
788
992
|
' upgrade Move this toolchain to a coherent target version, with',
|
|
@@ -797,7 +1001,7 @@ const USAGE = [
|
|
|
797
1001
|
' bare "ekanos upgrade" MUTATES the project (installs the target versions,',
|
|
798
1002
|
' verifies with validate + the test script, rolls back on any failure).',
|
|
799
1003
|
'',
|
|
800
|
-
'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):',
|
|
801
1005
|
' --host, else EKANOS_HOST, else the "host" field in ekanos.json, else the',
|
|
802
1006
|
' sole stored login. "ekanos publish" saves host and source to ekanos.json.',
|
|
803
1007
|
' "ekanos login" never reads ekanos.json for a host (--host, else',
|
|
@@ -826,16 +1030,17 @@ const USAGE = [
|
|
|
826
1030
|
* `process.exit`, so this stays fully testable.
|
|
827
1031
|
*/
|
|
828
1032
|
export async function run(argv, options = {}) {
|
|
829
|
-
var _a, _b, _c, _d;
|
|
1033
|
+
var _a, _b, _c, _d, _e, _f;
|
|
830
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);
|
|
831
1036
|
const ctx = new CliContext({
|
|
832
1037
|
jsonFlag,
|
|
833
1038
|
stdout: options.stdout,
|
|
834
1039
|
stderr: options.stderr,
|
|
835
1040
|
env: options.env,
|
|
836
1041
|
});
|
|
837
|
-
const cwd = (
|
|
838
|
-
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;
|
|
839
1044
|
try {
|
|
840
1045
|
// `--version` is global and verb-independent, so it is answered before the
|
|
841
1046
|
// command is even resolved: `ekanos --version` and `ekanos validate
|
|
@@ -854,26 +1059,21 @@ export async function run(argv, options = {}) {
|
|
|
854
1059
|
tool: 'ekanos',
|
|
855
1060
|
error: 'unknown-command',
|
|
856
1061
|
commands: COMMANDS,
|
|
857
|
-
|
|
1062
|
+
help: 'ekanos --help',
|
|
858
1063
|
});
|
|
859
1064
|
throw usageError(`Unknown command or flag "${argv[0]}".`, `Run one of: ${COMMANDS.join(', ')}. See "ekanos --help".`);
|
|
860
1065
|
}
|
|
861
1066
|
if (!COMMANDS.includes(command)) {
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
given: command,
|
|
866
|
-
commands: COMMANDS,
|
|
867
|
-
usage: USAGE,
|
|
868
|
-
});
|
|
869
|
-
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;
|
|
870
1070
|
}
|
|
871
1071
|
const specs = Object.assign(Object.assign({}, GLOBAL_SPECS), COMMAND_SPECS[command]);
|
|
872
1072
|
const parsed = parseArgv(rest, specs);
|
|
873
1073
|
if (parsed.flags.help === true) {
|
|
874
1074
|
return emitCommandHelp(ctx, command);
|
|
875
1075
|
}
|
|
876
|
-
const positionalNames = (
|
|
1076
|
+
const positionalNames = (_e = POSITIONAL_COMMANDS[command]) !== null && _e !== void 0 ? _e : [];
|
|
877
1077
|
if (positionalNames.length === 0 && parsed.positionals.length > 0) {
|
|
878
1078
|
throw usageError(`"${command}" takes no positional arguments (got "${parsed.positionals[0]}").`, `Pass options as flags, e.g. "--dir <path>". See "ekanos ${command} --help".`);
|
|
879
1079
|
}
|
|
@@ -883,7 +1083,7 @@ export async function run(argv, options = {}) {
|
|
|
883
1083
|
`argument${positionalNames.length === 1 ? '' : 's'} (${usage}), ` +
|
|
884
1084
|
`got ${parsed.positionals.length}.`, `e.g. "ekanos ${command} ${usage}". See "ekanos ${command} --help".`);
|
|
885
1085
|
}
|
|
886
|
-
const dir = (
|
|
1086
|
+
const dir = (_f = parsed.flags.dir) !== null && _f !== void 0 ? _f : cwd;
|
|
887
1087
|
switch (command) {
|
|
888
1088
|
case 'init':
|
|
889
1089
|
return await runInit(ctx, {
|
|
@@ -953,8 +1153,11 @@ export async function run(argv, options = {}) {
|
|
|
953
1153
|
positionals: parsed.positionals,
|
|
954
1154
|
source: parsed.flags.source,
|
|
955
1155
|
yes: parsed.flags.yes === true,
|
|
1156
|
+
flags: parsed.flags,
|
|
956
1157
|
dir,
|
|
957
1158
|
env,
|
|
1159
|
+
stdinIsTTY: options.stdinIsTTY,
|
|
1160
|
+
ask: options.ask,
|
|
958
1161
|
});
|
|
959
1162
|
case 'catalog':
|
|
960
1163
|
return await runCatalog(ctx, {
|
|
@@ -978,6 +1181,10 @@ export async function run(argv, options = {}) {
|
|
|
978
1181
|
confirm: options.confirm,
|
|
979
1182
|
noWait: parsed.flags['no-wait'] === true,
|
|
980
1183
|
yes: parsed.flags.yes === true,
|
|
1184
|
+
flags: parsed.flags,
|
|
1185
|
+
readStdin: options.readStdin,
|
|
1186
|
+
openUrl: options.openUrl,
|
|
1187
|
+
secretFormTimeoutMs: options.secretFormTimeoutMs,
|
|
981
1188
|
});
|
|
982
1189
|
case 'teams':
|
|
983
1190
|
return await runTeams(ctx, {
|
|
@@ -1001,6 +1208,8 @@ export async function run(argv, options = {}) {
|
|
|
1001
1208
|
askSecret: options.askSecret,
|
|
1002
1209
|
openUrl: options.openUrl,
|
|
1003
1210
|
pollDelayMs: options.pollDelayMs,
|
|
1211
|
+
readStdin: options.readStdin,
|
|
1212
|
+
secretFormTimeoutMs: options.secretFormTimeoutMs,
|
|
1004
1213
|
});
|
|
1005
1214
|
case 'reviewers':
|
|
1006
1215
|
return await runReviewers(ctx, {
|
|
@@ -1113,6 +1322,30 @@ export async function run(argv, options = {}) {
|
|
|
1113
1322
|
stdinIsTTY: options.stdinIsTTY,
|
|
1114
1323
|
confirm: options.confirm,
|
|
1115
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
|
+
});
|
|
1116
1349
|
case 'use':
|
|
1117
1350
|
return await runUse(ctx, {
|
|
1118
1351
|
host: parsed.flags.host,
|
|
@@ -1222,11 +1455,12 @@ function emitVersion(ctx) {
|
|
|
1222
1455
|
}
|
|
1223
1456
|
const DOCS_FOOTER = `\nDocs: ${SDK_DOCS_URL} (commands: ${docsPage('cli/commands')})`;
|
|
1224
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.
|
|
1225
1460
|
ctx.emitClaudeCodeHint({
|
|
1226
1461
|
tool: 'ekanos',
|
|
1227
1462
|
commands: COMMANDS,
|
|
1228
|
-
|
|
1229
|
-
exitCodes: EXIT_CODES,
|
|
1463
|
+
help: 'ekanos <command> --help',
|
|
1230
1464
|
});
|
|
1231
1465
|
return ctx.succeed({ usage: USAGE, commands: COMMANDS, docs: SDK_DOCS_URL }, `${USAGE}${DOCS_FOOTER}`);
|
|
1232
1466
|
}
|