@ekanos/cli 0.15.0 → 0.17.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 +103 -8
- 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/add.d.ts +2 -0
- package/dist/commands/add.js +118 -0
- package/dist/commands/add.js.map +1 -0
- 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/audiences.d.ts +31 -0
- package/dist/commands/audiences.js +239 -0
- package/dist/commands/audiences.js.map +1 -0
- package/dist/commands/build.d.ts +2 -0
- package/dist/commands/build.js +41 -0
- package/dist/commands/build.js.map +1 -0
- 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/check.d.ts +2 -0
- package/dist/commands/check.js +43 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/codegen.d.ts +2 -0
- package/dist/commands/codegen.js +49 -0
- package/dist/commands/codegen.js.map +1 -0
- package/dist/commands/contract.d.ts +52 -0
- package/dist/commands/contract.js +300 -0
- package/dist/commands/contract.js.map +1 -0
- package/dist/commands/dev.d.ts +7 -0
- package/dist/commands/dev.js +186 -12
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/index-experience.d.ts +31 -0
- package/dist/commands/index-experience.js +21 -0
- package/dist/commands/index-experience.js.map +1 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.js +12 -0
- package/dist/commands/init.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/new.d.ts +2 -0
- package/dist/commands/new.js +39 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/publish.d.ts +59 -0
- package/dist/commands/publish.js +118 -65
- package/dist/commands/publish.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 +13 -0
- package/dist/commands/scope-notice.js +12 -4
- 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 +8 -1
- package/dist/commands/sources.js.map +1 -1
- package/dist/commands/sync.d.ts +2 -0
- package/dist/commands/sync.js +150 -0
- package/dist/commands/sync.js.map +1 -0
- 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-audience.d.ts +12 -0
- package/dist/commands/teams-audience.js +144 -0
- package/dist/commands/teams-audience.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-scope.js +4 -0
- package/dist/commands/teams-scope.js.map +1 -1
- package/dist/commands/teams.d.ts +25 -5
- package/dist/commands/teams.js +106 -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/compatibility.d.ts +10 -1
- package/dist/compatibility.js +10 -1
- package/dist/compatibility.js.map +1 -1
- 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/dev-experience.d.ts +125 -0
- package/dist/dev-experience.js +128 -0
- package/dist/dev-experience.js.map +1 -0
- package/dist/experience/boundary.d.ts +12 -0
- package/dist/experience/boundary.js +260 -0
- package/dist/experience/boundary.js.map +1 -0
- package/dist/experience/build.d.ts +16 -0
- package/dist/experience/build.js +90 -0
- package/dist/experience/build.js.map +1 -0
- package/dist/experience/checks.d.ts +29 -0
- package/dist/experience/checks.js +133 -0
- package/dist/experience/checks.js.map +1 -0
- package/dist/experience/contract-sources.d.ts +36 -0
- package/dist/experience/contract-sources.js +111 -0
- package/dist/experience/contract-sources.js.map +1 -0
- package/dist/experience/definition-checks.d.ts +26 -0
- package/dist/experience/definition-checks.js +201 -0
- package/dist/experience/definition-checks.js.map +1 -0
- package/dist/experience/definition-shape.d.ts +60 -0
- package/dist/experience/definition-shape.js +2 -0
- package/dist/experience/definition-shape.js.map +1 -0
- package/dist/experience/init.d.ts +10 -0
- package/dist/experience/init.js +64 -0
- package/dist/experience/init.js.map +1 -0
- package/dist/experience/integrations-codegen.d.ts +17 -0
- package/dist/experience/integrations-codegen.js +51 -0
- package/dist/experience/integrations-codegen.js.map +1 -0
- package/dist/experience/json-schema-to-ts.d.ts +1 -0
- package/dist/experience/json-schema-to-ts.js +90 -0
- package/dist/experience/json-schema-to-ts.js.map +1 -0
- package/dist/experience/load-experience.d.ts +23 -0
- package/dist/experience/load-experience.js +115 -0
- package/dist/experience/load-experience.js.map +1 -0
- package/dist/experience/overrides.d.ts +8 -0
- package/dist/experience/overrides.js +21 -0
- package/dist/experience/overrides.js.map +1 -0
- package/dist/experience/pin-integration.d.ts +8 -0
- package/dist/experience/pin-integration.js +17 -0
- package/dist/experience/pin-integration.js.map +1 -0
- package/dist/experience/pin-ops.d.ts +12 -0
- package/dist/experience/pin-ops.js +36 -0
- package/dist/experience/pin-ops.js.map +1 -0
- package/dist/experience/pins.d.ts +35 -0
- package/dist/experience/pins.js +91 -0
- package/dist/experience/pins.js.map +1 -0
- package/dist/experience/project.d.ts +52 -0
- package/dist/experience/project.js +149 -0
- package/dist/experience/project.js.map +1 -0
- package/dist/experience/publish.d.ts +51 -0
- package/dist/experience/publish.js +144 -0
- package/dist/experience/publish.js.map +1 -0
- package/dist/experience/regenerate.d.ts +10 -0
- package/dist/experience/regenerate.js +33 -0
- package/dist/experience/regenerate.js.map +1 -0
- package/dist/experience/report.d.ts +9 -0
- package/dist/experience/report.js +23 -0
- package/dist/experience/report.js.map +1 -0
- package/dist/harness-scaffold.d.ts +52 -18
- package/dist/harness-scaffold.js +189 -9
- package/dist/harness-scaffold.js.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.js +494 -127
- 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/project-checks.d.ts +12 -0
- package/dist/project-checks.js +46 -0
- package/dist/project-checks.js.map +1 -1
- package/dist/project.d.ts +14 -0
- package/dist/project.js +10 -0
- package/dist/project.js.map +1 -1
- package/dist/repo/publish.d.ts +42 -0
- package/dist/repo/publish.js +225 -0
- package/dist/repo/publish.js.map +1 -0
- package/dist/repo/scaffold.d.ts +30 -0
- package/dist/repo/scaffold.js +165 -0
- package/dist/repo/scaffold.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 +49 -1
- package/dist/teams-api.js +149 -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/validate-findings.js +2 -1
- package/dist/validate-findings.js.map +1 -1
- 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/ekanos.json.tmpl +1 -0
- package/templates/experience/AGENTS.md.tmpl +22 -0
- package/templates/experience/ekanos.json.tmpl +7 -0
- package/templates/experience/ekanos.lock.json.tmpl +4 -0
- package/templates/experience/eslint.config.mjs.tmpl +25 -0
- package/templates/experience/gitignore.tmpl +17 -0
- package/templates/experience/package.json.tmpl +41 -0
- package/templates/experience/src/.ekanos/integrations.d.ts.tmpl +3 -0
- package/templates/experience/src/experience.ts.tmpl +30 -0
- package/templates/experience/src/widgets/hello-widget.tsx.tmpl +40 -0
- package/templates/experience/tsconfig.json.tmpl +20 -0
- package/templates/harness/app/%5F%5Fekanos/api/[...path]/route.ts.tmpl +9 -0
- package/templates/harness/app/[slug]/activation/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/tile/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/triggers/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/widgets/[widgetId]/page.tsx.tmpl +1 -1
- package/templates/harness/app/[slug]/widgets/page.tsx.tmpl +1 -1
- package/templates/harness/app/experience/layout.tsx.tmpl +17 -0
- package/templates/harness/app/experience/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/pages/[id]/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/review-queue/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/runs/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/widgets/[id]/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/widgets/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/workflows/[id]/page.tsx.tmpl +1 -0
- package/templates/harness/app/experience/workflows/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/connect/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/events/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/health/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/operations/[kind]/[name]/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/operations/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/activation/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/layout.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/tile/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/triggers/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/widgets/[widgetId]/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/preview/widgets/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/[slug]/runs/page.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/layout.tsx.tmpl +1 -0
- package/templates/harness/app/integrations/page.tsx.tmpl +1 -0
- package/templates/harness/app/page.experience.tsx.tmpl +5 -0
- package/templates/harness/repo/app/%5F%5Fekanos/api/[...path]/route.ts.tmpl +11 -0
- package/templates/harness/repo/app/(repo)/connections/page.tsx.tmpl +1 -0
- package/templates/harness/repo/app/(repo)/layout.tsx.tmpl +1 -0
- package/templates/harness/repo/app/(repo)/page.tsx.tmpl +1 -0
- package/templates/harness/repo/app/experiences/[name]/connect/page.tsx.tmpl +1 -0
- package/templates/harness/repo/app/experiences/[name]/layout.tsx.tmpl +9 -0
- package/templates/harness/repo/app/experiences/page.tsx.tmpl +5 -0
- package/templates/harness/repo/app/harness-shell.tsx.tmpl +9 -0
- package/templates/harness/repo/app/integrations/[slug]/layout.tsx.tmpl +1 -0
- package/templates/harness/repo/app/integrations/page.tsx.tmpl +5 -0
- package/templates/harness/repo/app/repo-experiences.ts.tmpl +5 -0
- package/templates/harness/styles/globals.css.tmpl +15 -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
|
@@ -9,12 +9,16 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
+
import { isRepoRoot } from '@ekanos/integration-schema/repo';
|
|
12
13
|
import * as fs from 'node:fs';
|
|
14
|
+
import * as path from 'node:path';
|
|
13
15
|
import { runAgents } from './commands/agents.js';
|
|
14
16
|
import { TEMPLATE_EDIT_HELP } from './commands/agents-edit.js';
|
|
15
17
|
import { runApps } from './commands/apps.js';
|
|
18
|
+
import { runAudiences } from './commands/audiences.js';
|
|
16
19
|
import { runCatalog } from './commands/catalog.js';
|
|
17
20
|
import { runDev } from './commands/dev.js';
|
|
21
|
+
import { EXPERIENCE_COMMANDS } from './commands/index-experience.js';
|
|
18
22
|
import { runInit } from './commands/init.js';
|
|
19
23
|
import { runKnowledge } from './commands/knowledge.js';
|
|
20
24
|
import { runLogin } from './commands/login.js';
|
|
@@ -33,11 +37,13 @@ import { runUpgrade } from './commands/upgrade.js';
|
|
|
33
37
|
import { runUse } from './commands/use.js';
|
|
34
38
|
import { runValidate } from './commands/validate.js';
|
|
35
39
|
import { runWhoami } from './commands/whoami.js';
|
|
40
|
+
import { runWorkflows } from './commands/workflows.js';
|
|
36
41
|
import { CliContext } from './context.js';
|
|
37
42
|
import { SDK_DOCS_URL, docsPage } from './docs-links.js';
|
|
38
|
-
import { toCliError, usageError } from './errors.js';
|
|
39
|
-
import {
|
|
43
|
+
import { preconditionError, toCliError, usageError } from './errors.js';
|
|
44
|
+
import { detectInvocation, setInvocation } from './invocation.js';
|
|
40
45
|
import { parseArgv } from './parse-argv.js';
|
|
46
|
+
import { unknownCommand } from './unknown-command.js';
|
|
41
47
|
export { CliContext } from './context.js';
|
|
42
48
|
export { EXIT_CODES, ERROR_CODES } from './exit-codes.js';
|
|
43
49
|
const GLOBAL_SPECS = {
|
|
@@ -61,12 +67,44 @@ const DIR = {
|
|
|
61
67
|
type: 'string',
|
|
62
68
|
description: 'Project directory, where ekanos.json and relative paths are read (default: the current one)',
|
|
63
69
|
};
|
|
70
|
+
/**
|
|
71
|
+
* Where a secret comes from without a terminal (`secret-input.ts`), for every
|
|
72
|
+
* command that takes one. Never a value: a secret in argv lands in shell
|
|
73
|
+
* history and the process list.
|
|
74
|
+
*/
|
|
75
|
+
const SECRET_INPUT = {
|
|
76
|
+
'secret-env': {
|
|
77
|
+
type: 'string',
|
|
78
|
+
description: 'The secret, from this environment variable (its NAME, never the value)',
|
|
79
|
+
},
|
|
80
|
+
'secret-file': {
|
|
81
|
+
type: 'string',
|
|
82
|
+
description: 'The secret, from this file: yours, mode 600, not a symlink',
|
|
83
|
+
},
|
|
84
|
+
'secret-stdin': {
|
|
85
|
+
type: 'boolean',
|
|
86
|
+
description: 'The secret, piped in on stdin',
|
|
87
|
+
},
|
|
88
|
+
'set-secret': {
|
|
89
|
+
type: 'string',
|
|
90
|
+
repeatable: true,
|
|
91
|
+
description: 'One field of a form: <field>=env:<NAME> | file:<path> | stdin',
|
|
92
|
+
},
|
|
93
|
+
browser: {
|
|
94
|
+
type: 'boolean',
|
|
95
|
+
description: 'Type the secret into a one-time form in your browser on this computer (never shown to the run that asked)',
|
|
96
|
+
},
|
|
97
|
+
};
|
|
64
98
|
const COMMAND_SPECS = {
|
|
65
99
|
init: {
|
|
66
100
|
slug: {
|
|
67
101
|
type: 'string',
|
|
68
102
|
description: 'Kebab-case id of the integration, e.g. acme-crm',
|
|
69
103
|
},
|
|
104
|
+
kind: {
|
|
105
|
+
type: 'string',
|
|
106
|
+
description: 'What to scaffold: integration (default), experience (widgets and workflows that depend on integrations) or repo (one repo holding many of both)',
|
|
107
|
+
},
|
|
70
108
|
dir: {
|
|
71
109
|
type: 'string',
|
|
72
110
|
description: 'Target directory (default ./<slug>; --dir . scaffolds in place)',
|
|
@@ -103,7 +141,11 @@ const COMMAND_SPECS = {
|
|
|
103
141
|
},
|
|
104
142
|
start: {
|
|
105
143
|
type: 'boolean',
|
|
106
|
-
description: 'Start the server even in JSON mode; --no-start only scaffolds',
|
|
144
|
+
description: 'Start the server even in JSON mode or under an agent (non-interactive runs only scaffold and print the command); --no-start only scaffolds',
|
|
145
|
+
},
|
|
146
|
+
'contracts-dir': {
|
|
147
|
+
type: 'string',
|
|
148
|
+
description: 'Experiences: a directory of <integration>.contract.json files to resolve integrations from (offline registry)',
|
|
107
149
|
},
|
|
108
150
|
},
|
|
109
151
|
test: {
|
|
@@ -165,179 +207,271 @@ const COMMAND_SPECS = {
|
|
|
165
207
|
source: SOURCE,
|
|
166
208
|
yes: {
|
|
167
209
|
type: 'boolean',
|
|
168
|
-
description: 'Confirm products disable, scopes remove',
|
|
210
|
+
description: 'Confirm products disable, scopes remove, roles delete',
|
|
169
211
|
},
|
|
212
|
+
// `sources roles create|update`.
|
|
213
|
+
'display-name': {
|
|
214
|
+
type: 'string',
|
|
215
|
+
description: "roles create|update: the role's display name",
|
|
216
|
+
},
|
|
217
|
+
description: {
|
|
218
|
+
type: 'string',
|
|
219
|
+
description: "roles create|update: the role's description",
|
|
220
|
+
},
|
|
221
|
+
level: {
|
|
222
|
+
type: 'string',
|
|
223
|
+
description: 'roles create|update: its level, 1 to 1000; lower ranks higher (default 100)',
|
|
224
|
+
},
|
|
225
|
+
permission: {
|
|
226
|
+
type: 'string',
|
|
227
|
+
repeatable: true,
|
|
228
|
+
description: 'roles create|update: a permission it holds (update: replaces them all)',
|
|
229
|
+
},
|
|
230
|
+
grant: {
|
|
231
|
+
type: 'string',
|
|
232
|
+
repeatable: true,
|
|
233
|
+
description: 'roles update: add this permission',
|
|
234
|
+
},
|
|
235
|
+
revoke: {
|
|
236
|
+
type: 'string',
|
|
237
|
+
repeatable: true,
|
|
238
|
+
description: 'roles update: take this permission away',
|
|
239
|
+
},
|
|
240
|
+
// `sources people`.
|
|
241
|
+
search: {
|
|
242
|
+
type: 'string',
|
|
243
|
+
description: 'people: only those whose name or email matches',
|
|
244
|
+
},
|
|
245
|
+
page: { type: 'string', description: 'people: which page, from 1' },
|
|
170
246
|
},
|
|
171
|
-
|
|
172
|
-
host: HOST,
|
|
173
|
-
source: SOURCE,
|
|
174
|
-
dir: DIR,
|
|
175
|
-
},
|
|
176
|
-
apps: {
|
|
247
|
+
audiences: {
|
|
177
248
|
host: HOST,
|
|
178
249
|
source: SOURCE,
|
|
179
250
|
dir: DIR,
|
|
180
|
-
|
|
251
|
+
yes: {
|
|
181
252
|
type: 'boolean',
|
|
182
|
-
description: '
|
|
253
|
+
description: 'set: confirm dropping a product people then stop seeing',
|
|
183
254
|
},
|
|
184
|
-
|
|
255
|
+
name: { type: 'string', description: 'set: rename the audience' },
|
|
256
|
+
description: {
|
|
257
|
+
type: 'string',
|
|
258
|
+
description: 'create|set: what the audience is for',
|
|
259
|
+
},
|
|
260
|
+
products: {
|
|
261
|
+
type: 'string',
|
|
262
|
+
description: 'create|set: the products it shows, as a,b (set: replaces them; none empties it)',
|
|
263
|
+
},
|
|
264
|
+
widgets: {
|
|
265
|
+
type: 'string',
|
|
266
|
+
repeatable: true,
|
|
267
|
+
description: 'create|set: <product>=<id>,<id> shows only those widgets of the product (<product>= lifts the rule)',
|
|
268
|
+
},
|
|
269
|
+
tools: {
|
|
270
|
+
type: 'string',
|
|
271
|
+
repeatable: true,
|
|
272
|
+
description: 'create|set: <product>=<name>,<name> allows only those tools of the product (<product>= lifts the rule)',
|
|
273
|
+
},
|
|
274
|
+
default: {
|
|
185
275
|
type: 'boolean',
|
|
186
|
-
description: '
|
|
276
|
+
description: 'create|set: new teams of the Source start on it',
|
|
277
|
+
},
|
|
278
|
+
'all-entitled': {
|
|
279
|
+
type: 'boolean',
|
|
280
|
+
description: 'create|set: show every product the Source has, now and later (--no-all-entitled turns it off)',
|
|
187
281
|
},
|
|
188
282
|
},
|
|
189
|
-
|
|
283
|
+
catalog: {
|
|
190
284
|
host: HOST,
|
|
191
285
|
source: SOURCE,
|
|
192
286
|
dir: DIR,
|
|
193
|
-
|
|
287
|
+
},
|
|
288
|
+
apps: Object.assign({ host: HOST, source: SOURCE, dir: DIR, 'no-wait': {
|
|
289
|
+
type: 'boolean',
|
|
290
|
+
description: 'connect: print the links and return without waiting',
|
|
291
|
+
}, yes: {
|
|
292
|
+
type: 'boolean',
|
|
293
|
+
description: 'disconnect: confirm without the question (needed in a script or agent run)',
|
|
294
|
+
}, set: {
|
|
295
|
+
type: 'string',
|
|
296
|
+
repeatable: true,
|
|
297
|
+
description: 'set, connect: <name>=<value> for a field that is not a secret (set: clientId)',
|
|
298
|
+
} }, SECRET_INPUT),
|
|
299
|
+
teams: Object.assign(Object.assign({ host: HOST, source: SOURCE, dir: DIR, connection: {
|
|
194
300
|
type: 'string',
|
|
195
301
|
description: 'connect, app set: which of the integration\'s connections (e.g. "agent" for Linear\'s agent)',
|
|
196
|
-
},
|
|
302
|
+
},
|
|
197
303
|
// `teams app set`: which fields to enter, non-secret values, removals.
|
|
198
304
|
field: {
|
|
199
305
|
type: 'string',
|
|
200
306
|
repeatable: true,
|
|
201
307
|
description: 'app set: enter just this field at your terminal',
|
|
202
|
-
},
|
|
203
|
-
set: {
|
|
308
|
+
}, set: {
|
|
204
309
|
type: 'string',
|
|
205
310
|
repeatable: true,
|
|
206
|
-
description: 'app set: <name>=<value> for a
|
|
207
|
-
},
|
|
208
|
-
|
|
311
|
+
description: 'app set, connect: <name>=<value> for a field that is not a secret (a list as a,b)',
|
|
312
|
+
}, self: {
|
|
313
|
+
type: 'boolean',
|
|
314
|
+
description: 'members add: you join the team now, with no invitation email',
|
|
315
|
+
},
|
|
316
|
+
// `teams audience`.
|
|
317
|
+
member: {
|
|
318
|
+
type: 'string',
|
|
319
|
+
description: "audience: one member's own audience, by email",
|
|
320
|
+
}, inherit: {
|
|
321
|
+
type: 'boolean',
|
|
322
|
+
description: "audience --member: clear their own audience so the team's applies",
|
|
323
|
+
} }, SECRET_INPUT), { clear: {
|
|
209
324
|
type: 'string',
|
|
210
325
|
repeatable: true,
|
|
211
326
|
description: "app set: remove this field's saved value",
|
|
212
|
-
},
|
|
213
|
-
slug: {
|
|
327
|
+
}, slug: {
|
|
214
328
|
type: 'string',
|
|
215
329
|
description: "create: the team's slug (default: from its name)",
|
|
216
|
-
},
|
|
217
|
-
owner: {
|
|
330
|
+
}, owner: {
|
|
218
331
|
type: 'string',
|
|
219
332
|
description: 'create: invite this email as the owner instead of you',
|
|
220
|
-
},
|
|
221
|
-
role: {
|
|
333
|
+
}, role: {
|
|
222
334
|
type: 'string',
|
|
223
|
-
description: 'members invite: the role to
|
|
224
|
-
},
|
|
225
|
-
yes: {
|
|
335
|
+
description: 'members add, members invite: the role to give (default member)',
|
|
336
|
+
}, yes: {
|
|
226
337
|
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
|
-
},
|
|
338
|
+
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)',
|
|
339
|
+
},
|
|
229
340
|
// `teams agents|triggers|links|mcp` (team-agents.ts).
|
|
230
341
|
as: {
|
|
231
342
|
type: 'string',
|
|
232
|
-
description: 'connect: the member who signs in; agents enable: the member the agent runs as',
|
|
233
|
-
},
|
|
343
|
+
description: 'connect: the member who signs in; agents enable: the member the agent runs as (chosen once, when it is turned on)',
|
|
344
|
+
},
|
|
234
345
|
// `teams agents enable|pin … --draft`: test the unpublished draft there.
|
|
235
346
|
draft: {
|
|
236
347
|
type: 'boolean',
|
|
237
348
|
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).
|
|
349
|
+
},
|
|
350
|
+
// `teams agents enable|policy|create|apply`: also confirm, as yourself,
|
|
351
|
+
// what the agent may use (whoever sets it up confirms it, plan 247.2).
|
|
241
352
|
'confirm-access': {
|
|
242
353
|
type: 'boolean',
|
|
243
|
-
description: 'agents enable|policy: also confirm, as yourself, what it may use',
|
|
244
|
-
},
|
|
245
|
-
|
|
354
|
+
description: 'agents enable|policy|create|apply: also confirm, as yourself, what it may use',
|
|
355
|
+
},
|
|
356
|
+
// `teams agents create|apply`: the agent.json, read as `agents apply`
|
|
357
|
+
// reads it (team-agents-define.ts).
|
|
358
|
+
from: {
|
|
359
|
+
type: 'string',
|
|
360
|
+
description: 'agents create: the agent directory or agent.json',
|
|
361
|
+
}, personal: {
|
|
362
|
+
type: 'boolean',
|
|
363
|
+
description: 'agents create|apply: your own agent, which acts for you and only you change',
|
|
364
|
+
}, 'base-version': {
|
|
365
|
+
type: 'string',
|
|
366
|
+
description: 'agents apply: the agent version your edit starts from ("teams agents show")',
|
|
367
|
+
}, overwrite: {
|
|
368
|
+
type: 'boolean',
|
|
369
|
+
description: 'agents apply: replace a newer version on the host anyway',
|
|
370
|
+
}, skills: {
|
|
371
|
+
type: 'boolean',
|
|
372
|
+
description: 'agents create|apply: --no-skills skips pushing <dir>/skills/<slug>/ as team skills',
|
|
373
|
+
}, reads: {
|
|
246
374
|
type: 'string',
|
|
247
375
|
description: 'agents policy: auto|approve for every read tool',
|
|
248
|
-
},
|
|
249
|
-
writes: {
|
|
376
|
+
}, writes: {
|
|
250
377
|
type: 'string',
|
|
251
378
|
description: 'agents policy: auto|approve for every write tool',
|
|
252
|
-
},
|
|
253
|
-
effect: {
|
|
379
|
+
}, effect: {
|
|
254
380
|
type: 'string',
|
|
255
381
|
description: 'Not read: "teams mcp effect" takes the effect as an argument',
|
|
256
|
-
},
|
|
257
|
-
|
|
258
|
-
|
|
382
|
+
}, agent: {
|
|
383
|
+
type: 'string',
|
|
384
|
+
description: 'mcp refresh: list again the tools of every server this agent has',
|
|
385
|
+
}, kind: { type: 'string', description: 'links add: talk|delegate' }, mode: {
|
|
259
386
|
type: 'string',
|
|
260
387
|
description: 'links add: await|handoff, for a delegate link',
|
|
261
|
-
},
|
|
262
|
-
url: { type: 'string', description: "mcp add: the server's URL" },
|
|
263
|
-
auth: {
|
|
388
|
+
}, url: { type: 'string', description: "mcp add: the server's URL" }, auth: {
|
|
264
389
|
type: 'string',
|
|
265
390
|
description: 'mcp add: none|token|oauth (default oauth)',
|
|
266
|
-
},
|
|
267
|
-
name: { type: 'string', description: "mcp add: the server's display name" },
|
|
268
|
-
cron: {
|
|
391
|
+
}, name: {
|
|
269
392
|
type: 'string',
|
|
270
|
-
description:
|
|
271
|
-
},
|
|
272
|
-
|
|
393
|
+
description: "mcp add: the server's display name; groups update: the group's new name",
|
|
394
|
+
},
|
|
395
|
+
// `teams groups create|update`.
|
|
396
|
+
description: {
|
|
273
397
|
type: 'string',
|
|
274
|
-
description:
|
|
275
|
-
},
|
|
276
|
-
prompt: {
|
|
398
|
+
description: "groups create|update: the group's description",
|
|
399
|
+
}, products: {
|
|
277
400
|
type: 'string',
|
|
278
|
-
description: '
|
|
279
|
-
},
|
|
401
|
+
description: 'groups create|update: the products it narrows to, comma-separated (none: no narrowing)',
|
|
402
|
+
},
|
|
403
|
+
// `teams disconnect|health <team> <product> --mine`: the caller's own.
|
|
404
|
+
mine: {
|
|
405
|
+
type: 'boolean',
|
|
406
|
+
description: "disconnect, health <product>: your own personal connection, never another member's",
|
|
407
|
+
},
|
|
408
|
+
// `teams health <team> <product> --run`.
|
|
409
|
+
run: {
|
|
410
|
+
type: 'boolean',
|
|
411
|
+
description: "health: run the integration's health check now",
|
|
412
|
+
}, cron: {
|
|
413
|
+
type: 'string',
|
|
414
|
+
description: 'triggers add|edit schedule: a cron expression',
|
|
415
|
+
}, timezone: {
|
|
416
|
+
type: 'string',
|
|
417
|
+
description: 'triggers add|edit schedule: an IANA time zone (default UTC)',
|
|
418
|
+
}, prompt: {
|
|
419
|
+
type: 'string',
|
|
420
|
+
description: 'triggers add|edit: what the agent is told when it fires',
|
|
421
|
+
},
|
|
280
422
|
// Repeatable `field=value`, or one JSON object — as at the template level.
|
|
281
423
|
filter: {
|
|
282
424
|
type: 'string',
|
|
283
425
|
repeatable: true,
|
|
284
|
-
description: 'triggers add event: field=a,b (repeatable) or one JSON object',
|
|
285
|
-
},
|
|
426
|
+
description: 'triggers add|edit event: field=a,b (repeatable) or one JSON object',
|
|
427
|
+
},
|
|
286
428
|
// `teams <area> … --team <slug>`: the team, in place of the positional.
|
|
287
429
|
team: {
|
|
288
430
|
type: 'string',
|
|
289
431
|
description: 'The team, in place of the <team> argument (teams <area> … --team <slug>)',
|
|
290
|
-
},
|
|
432
|
+
},
|
|
291
433
|
// `teams triggers add … slack|linear`: where it answers. `--no-mention`
|
|
292
434
|
// is the negation of `mention`.
|
|
293
435
|
channel: {
|
|
294
436
|
type: 'string',
|
|
295
437
|
repeatable: true,
|
|
296
|
-
description: 'triggers add slack: a channel it answers in (#name or id)',
|
|
297
|
-
},
|
|
298
|
-
dms: {
|
|
438
|
+
description: 'triggers add|edit slack: a channel it answers in (#name or id); edit replaces the list',
|
|
439
|
+
}, dms: {
|
|
299
440
|
type: 'boolean',
|
|
300
|
-
description: 'triggers add slack: also answer direct messages',
|
|
301
|
-
},
|
|
302
|
-
label: {
|
|
441
|
+
description: 'triggers add|edit slack: also answer direct messages (edit: --no-dms stops)',
|
|
442
|
+
}, label: {
|
|
303
443
|
type: 'string',
|
|
304
444
|
repeatable: true,
|
|
305
|
-
description: 'triggers add linear: a label that hands an issue to it',
|
|
306
|
-
},
|
|
307
|
-
mention: {
|
|
445
|
+
description: 'triggers add|edit linear: a label that hands an issue to it; edit replaces the list',
|
|
446
|
+
}, mention: {
|
|
308
447
|
type: 'boolean',
|
|
309
|
-
description: 'triggers add linear: --no-mention ignores @mentions',
|
|
310
|
-
},
|
|
448
|
+
description: 'triggers add|edit linear: --no-mention ignores @mentions (edit: --mention answers them)',
|
|
449
|
+
},
|
|
311
450
|
// `teams connect`: `--no-wait`, `--no-open` (the negation of `open`),
|
|
312
451
|
// `--link-only`.
|
|
313
452
|
'no-wait': {
|
|
314
453
|
type: 'boolean',
|
|
315
454
|
description: 'connect: print the sign-in link and return at once',
|
|
316
|
-
},
|
|
317
|
-
open: {
|
|
455
|
+
}, open: {
|
|
318
456
|
type: 'boolean',
|
|
319
457
|
description: 'connect: --no-open prints the link without opening a browser',
|
|
320
|
-
},
|
|
321
|
-
'link-only': {
|
|
458
|
+
}, 'link-only': {
|
|
322
459
|
type: 'boolean',
|
|
323
460
|
description: "connect: print the team's page instead of connecting",
|
|
324
|
-
},
|
|
461
|
+
},
|
|
325
462
|
// `teams events <team> [--product] [--since] [--limit]`.
|
|
326
463
|
product: {
|
|
327
464
|
type: 'string',
|
|
328
465
|
description: 'events: only this product (or name it after the team)',
|
|
329
|
-
},
|
|
330
|
-
since: {
|
|
466
|
+
}, since: {
|
|
331
467
|
type: 'string',
|
|
332
468
|
description: 'events: since 30m, 24h, 7d or a date',
|
|
333
|
-
},
|
|
334
|
-
limit: { type: 'string', description: 'events: how many, 1 to 100' },
|
|
469
|
+
}, limit: { type: 'string', description: 'events: how many, 1 to 100' },
|
|
335
470
|
// `teams connect --reconnect`.
|
|
336
471
|
reconnect: {
|
|
337
472
|
type: 'boolean',
|
|
338
473
|
description: 'connect: connect again though it reads as connected (revoked or expired)',
|
|
339
|
-
},
|
|
340
|
-
},
|
|
474
|
+
} }),
|
|
341
475
|
reviewers: {
|
|
342
476
|
host: HOST,
|
|
343
477
|
source: SOURCE,
|
|
@@ -542,6 +676,51 @@ const COMMAND_SPECS = {
|
|
|
542
676
|
description: 'edit: a file with the reply to send instead',
|
|
543
677
|
},
|
|
544
678
|
},
|
|
679
|
+
workflows: {
|
|
680
|
+
host: HOST,
|
|
681
|
+
source: SOURCE,
|
|
682
|
+
dir: DIR,
|
|
683
|
+
team: { type: 'string', description: 'The team whose workflows these are' },
|
|
684
|
+
all: { type: 'boolean', description: 'list: include archived workflows' },
|
|
685
|
+
out: {
|
|
686
|
+
type: 'string',
|
|
687
|
+
description: 'pull: where to write workflow.json (default workflows/<name>)',
|
|
688
|
+
},
|
|
689
|
+
force: {
|
|
690
|
+
type: 'boolean',
|
|
691
|
+
description: 'pull: overwrite a local workflow.json that differs',
|
|
692
|
+
},
|
|
693
|
+
update: {
|
|
694
|
+
type: 'string',
|
|
695
|
+
description: 'apply: the workflow (id or name) to replace; without it apply creates a draft',
|
|
696
|
+
},
|
|
697
|
+
'confirm-access': {
|
|
698
|
+
type: 'boolean',
|
|
699
|
+
description: 'enable: approve, as yourself, what its Custom Code reaches (hosts, writes)',
|
|
700
|
+
},
|
|
701
|
+
'dry-run': {
|
|
702
|
+
type: 'boolean',
|
|
703
|
+
description: 'run: rehearse it (writes recorded, not sent; gates pass); a draft may run so',
|
|
704
|
+
},
|
|
705
|
+
input: {
|
|
706
|
+
type: 'string',
|
|
707
|
+
description: 'run --dry-run: a JSON file read as the sample trigger.*',
|
|
708
|
+
},
|
|
709
|
+
follow: {
|
|
710
|
+
type: 'boolean',
|
|
711
|
+
description: 'run: wait, printing each step, until it ends or waits on a gate',
|
|
712
|
+
},
|
|
713
|
+
workflow: {
|
|
714
|
+
type: 'string',
|
|
715
|
+
description: "runs list: only this workflow's runs (id or name)",
|
|
716
|
+
},
|
|
717
|
+
status: {
|
|
718
|
+
type: 'string',
|
|
719
|
+
description: 'runs list: only runs in this status (running, waiting_approval, completed, rejected, failed, canceled)',
|
|
720
|
+
},
|
|
721
|
+
reason: { type: 'string', description: 'approvals reject: why' },
|
|
722
|
+
yes: { type: 'boolean', description: 'runs cancel: confirm' },
|
|
723
|
+
},
|
|
545
724
|
use: {
|
|
546
725
|
host: HOST,
|
|
547
726
|
dir: DIR,
|
|
@@ -554,6 +733,14 @@ const COMMAND_SPECS = {
|
|
|
554
733
|
type: 'boolean',
|
|
555
734
|
description: 'Publish to the ekanos.json source without asking (needed in a script with several seats)',
|
|
556
735
|
},
|
|
736
|
+
'dry-run': {
|
|
737
|
+
type: 'boolean',
|
|
738
|
+
description: 'Experiences and repos: gate, build and pack every package under .ekanos/publish/, publish nothing (publishing an experience is not supported by the host yet)',
|
|
739
|
+
},
|
|
740
|
+
all: {
|
|
741
|
+
type: 'boolean',
|
|
742
|
+
description: 'In a repo: publish every package',
|
|
743
|
+
},
|
|
557
744
|
},
|
|
558
745
|
upgrade: {
|
|
559
746
|
dir: DIR,
|
|
@@ -577,9 +764,12 @@ const COMMAND_SPECS = {
|
|
|
577
764
|
/** Commands that take positional arguments, and what each means, in order. Every other command is positional-free. */
|
|
578
765
|
const POSITIONAL_COMMANDS = {
|
|
579
766
|
use: ['source-slug'],
|
|
767
|
+
// In a repo: `publish <package>...` (repeatable, see VARIADIC_COMMANDS).
|
|
768
|
+
publish: ['package'],
|
|
580
769
|
// `sources scopes add <scope> <product>` is the longest form.
|
|
581
770
|
sources: ['subcommand', 'verb', 'product-or-scope', 'product-slug'],
|
|
582
771
|
catalog: ['product-slug'],
|
|
772
|
+
audiences: ['subcommand', 'audience'],
|
|
583
773
|
apps: ['subcommand', 'product-slug'],
|
|
584
774
|
// `teams agents policy <team> <key> set <tool> auto` is the longest form.
|
|
585
775
|
teams: [
|
|
@@ -597,15 +787,37 @@ const POSITIONAL_COMMANDS = {
|
|
|
597
787
|
knowledge: ['subcommand', 'path-or-query'],
|
|
598
788
|
runs: ['subcommand', 'agent-key-or-run-id'],
|
|
599
789
|
approvals: ['subcommand', 'approval-id'],
|
|
790
|
+
// `workflows runs show <run-id>` is the longest form.
|
|
791
|
+
workflows: ['subcommand', 'workflow-or-verb', 'id'],
|
|
600
792
|
// `triggers <key> add event <trigger-key>` is the longest form: five tokens.
|
|
601
793
|
agents: ['subcommand', 'key-or-path', 'action', 'arg', 'value'],
|
|
602
794
|
};
|
|
795
|
+
for (const command of EXPERIENCE_COMMANDS) {
|
|
796
|
+
COMMAND_SPECS[command.name] = command.specs;
|
|
797
|
+
if (command.positionals)
|
|
798
|
+
POSITIONAL_COMMANDS[command.name] = command.positionals;
|
|
799
|
+
}
|
|
800
|
+
/** Commands that act on one package: refused at a repo root, with the way in. */
|
|
801
|
+
const REPO_ROOT_REFUSED = new Set([
|
|
802
|
+
'validate',
|
|
803
|
+
'test',
|
|
804
|
+
'check',
|
|
805
|
+
'build',
|
|
806
|
+
'sync',
|
|
807
|
+
'add',
|
|
808
|
+
'codegen',
|
|
809
|
+
'contract',
|
|
810
|
+
]);
|
|
811
|
+
/** Commands whose last positional repeats. */
|
|
812
|
+
const VARIADIC_COMMANDS = new Set(['publish']);
|
|
603
813
|
const COMMANDS = Object.keys(COMMAND_SPECS);
|
|
604
814
|
const USAGE = [
|
|
605
815
|
'Usage: ekanos <command> [options]',
|
|
606
816
|
'',
|
|
607
817
|
'Commands:',
|
|
608
|
-
' init Scaffold a new integration project into ./<slug> (--slug <slug> --yes)',
|
|
818
|
+
' init Scaffold a new integration project into ./<slug> (--slug <slug> --yes);',
|
|
819
|
+
' --kind experience for an experience, --kind repo for a repo of many',
|
|
820
|
+
...EXPERIENCE_COMMANDS.flatMap((command) => command.usage),
|
|
609
821
|
' validate Validate ekanos.json + the integration definition (--json)',
|
|
610
822
|
' dev Scaffold .ekanos/harness and run it with your own Next',
|
|
611
823
|
' test Run the project test script via its package manager (--json).',
|
|
@@ -630,13 +842,35 @@ const USAGE = [
|
|
|
630
842
|
' and pointed at /admin) | scopes (each product scope: its',
|
|
631
843
|
' products and how many teams hold it; a team sees in the app',
|
|
632
844
|
" only its scopes' products) | scopes add <scope> <product> |",
|
|
633
|
-
' scopes remove <scope> <product> --yes',
|
|
634
|
-
'
|
|
845
|
+
' scopes remove <scope> <product> --yes | roles [list] (the roles',
|
|
846
|
+
' every team of the Source hands out, each with its level and',
|
|
847
|
+
' permissions) | roles create <name> [--display-name <text>]',
|
|
848
|
+
' [--description <text>] [--level <n>] [--permission <p>]… |',
|
|
849
|
+
' roles update <role> [--display-name] [--description] [--level]',
|
|
850
|
+
' [--permission <p>]… (replaces) [--grant <p>]… [--revoke <p>]… |',
|
|
851
|
+
' roles delete <role> [--yes] (owner, admin and member are system',
|
|
852
|
+
" roles: never changed or deleted; a held role isn't deleted) |",
|
|
853
|
+
' people [--search <text>] [--page <n>] (everyone with access, one',
|
|
854
|
+
' row per person, with their teams and role on each)',
|
|
855
|
+
" audiences A source's audiences, for its Source admin (they replace product",
|
|
856
|
+
' scopes): list | show <audience> | create <name> [--products a,b |',
|
|
857
|
+
' --all-entitled] [--description <text>] [--default] [--widgets',
|
|
858
|
+
' <product>=<id>,…]… [--tools <product>=<name>,…]… | set <audience>',
|
|
859
|
+
' [--name] [--description] [--default] [--all-entitled] [--products',
|
|
860
|
+
' a,b|none] [--widgets …]… [--tools …]… [--yes] (--products replaces;',
|
|
861
|
+
' dropping a product needs --yes). A team or member is put on one',
|
|
862
|
+
' with "teams audience <team> [<audience>] [--member <email>]"',
|
|
863
|
+
' catalog What a source can already use, and how to set it up:',
|
|
864
|
+
' Experiences, then Integrations; one product shows its tools',
|
|
865
|
+
' with their inputs and whose connection agent runs use',
|
|
635
866
|
' ("ekanos catalog [<product-slug>] --source <slug>", --json)',
|
|
636
867
|
" apps The Source's app for an integration teams sign in through:",
|
|
637
868
|
' show <product> | set <product> (Source admin; takes the secret',
|
|
638
|
-
' at your terminal, Enter keeps a saved value
|
|
639
|
-
' <
|
|
869
|
+
' at your terminal, Enter keeps a saved value; without one,',
|
|
870
|
+
' --set clientId=<id> and --secret-env <NAME> | --secret-file',
|
|
871
|
+
' <path> | --secret-stdin | --browser) | connect',
|
|
872
|
+
' <product> [--no-wait] [--set <field>=<value>]… [--set-secret',
|
|
873
|
+
' <field>=env:<NAME>|file:<path>|stdin]… [--browser] (one',
|
|
640
874
|
" connection for the whole Source, used by the Source's provided",
|
|
641
875
|
' agents in every team) | disconnect <product> [--yes] (a',
|
|
642
876
|
' script or agent run needs --yes) | list',
|
|
@@ -644,15 +878,32 @@ const USAGE = [
|
|
|
644
878
|
' create <name> [--slug <slug>] [--owner <email>] (you own it',
|
|
645
879
|
' unless --owner, who is invited as owner) |',
|
|
646
880
|
' rename <team> <name> (the slug follows the name, as in the app) |',
|
|
647
|
-
' members list <team> | members
|
|
648
|
-
' <role>] (
|
|
881
|
+
' members list <team> | members add <team> --self | <email>',
|
|
882
|
+
' [--role <role>] (a member now, no email: you, or someone with',
|
|
883
|
+
' an Ekanos account on the Source) | members invite <team> <email>',
|
|
884
|
+
' [--role <role>] (default member; sends the invitation email) |',
|
|
649
885
|
' members role <team> <email> <role> | members remove <team>',
|
|
650
|
-
|
|
886
|
+
' <email> --yes | members resend <team> <email> (a live',
|
|
887
|
+
' invitation is resent, an expired one renewed) |',
|
|
888
|
+
" roles list <team> (each role's permissions) |",
|
|
889
|
+
' leave <team> [--yes] (you leave it; never the primary owner) |',
|
|
890
|
+
' groups list <team> | groups create <team> <name> [--description',
|
|
891
|
+
' <text>] [--products <slug,slug>] | groups update <team> <group>',
|
|
892
|
+
' [--name <name>] [--description <text>] [--products <slug,…>|none]',
|
|
893
|
+
' | groups delete <team> <group> [--yes] | groups members',
|
|
894
|
+
' add|remove <team> <group> <email> (leave, groups delete and',
|
|
895
|
+
' remove ask first; a script or agent run needs --yes) |',
|
|
896
|
+
' health <team> [<product>] [--run] (each connected integration',
|
|
897
|
+
' and its health; --run checks one now; <product> --mine: your own',
|
|
898
|
+
' personal connection, any seat, as a member) | workspace list <team> |',
|
|
899
|
+
' workspace default <team> <workspace> (where the team lands) |',
|
|
651
900
|
' connect <team> <product> [--connection <id>] [--as',
|
|
652
|
-
' <member-email>] [--
|
|
653
|
-
' [--reconnect] (connects',
|
|
654
|
-
" it: asks the form's fields at your terminal
|
|
655
|
-
'
|
|
901
|
+
' <member-email>] [--set <field>=<value>]… [--no-wait] [--no-open]',
|
|
902
|
+
' [--link-only] [--reconnect] (connects',
|
|
903
|
+
" it: asks the form's fields at your terminal or takes them from",
|
|
904
|
+
' --set (a list as a,b; secrets and JSON only at a prompt; an optional',
|
|
905
|
+
' one can be skipped), then opens the sign-in for you — your own',
|
|
906
|
+
' connection, for a personal product — or the member --as names, and waits;',
|
|
656
907
|
" --connection agent installs the team's Linear agent (its own",
|
|
657
908
|
' Linear app, as a member), which @mention and assign triggers',
|
|
658
909
|
" need; --link-only prints the team's page; --reconnect connects",
|
|
@@ -662,30 +913,52 @@ const USAGE = [
|
|
|
662
913
|
' Slack, or the Ekanos Agents app for Linear, which slack and',
|
|
663
914
|
' linear triggers answer through; same link-and-wait) |',
|
|
664
915
|
" disconnect <team> <product> --yes (takes the team's connection",
|
|
665
|
-
" and its tokens down; its own app's saved fields stay
|
|
916
|
+
" and its tokens down; its own app's saved fields stay; --mine:",
|
|
917
|
+
" your own personal connection, never another member's) |",
|
|
666
918
|
' list | show <team> (one screen: members, each integration and',
|
|
667
919
|
' whose connection it is, each agent live or the next step) |',
|
|
668
920
|
' show <team> <product> (a checklist: fields, callback',
|
|
669
921
|
' URLs, webhooks, connect link) | app set <team> <product>',
|
|
670
922
|
' [--connection <id>] [--field <name>]… [--set <name>=<value>]…',
|
|
671
|
-
' [--clear <name>]…
|
|
672
|
-
'
|
|
923
|
+
' [--clear <name>]… [--set-secret <name>=env:<NAME>|file:<path>|stdin]…',
|
|
924
|
+
' [--browser] (any one field at a time; a field you skip keeps',
|
|
925
|
+
' its saved value; a secret at your terminal, from the',
|
|
926
|
+
' environment, a private file, stdin or a browser form, never',
|
|
927
|
+
' as an argument) |',
|
|
928
|
+
' llm-key show <team> | llm-key set <team> [--secret-env <NAME> |',
|
|
929
|
+
' --secret-file <path> | --secret-stdin | --browser] | llm-key',
|
|
930
|
+
" remove <team> --yes (the team's own Anthropic key, as its",
|
|
931
|
+
' settings page sets it; show gives only its last four characters) |',
|
|
673
932
|
' webhook <team> <product> [<webhook-id>] [--yes] (URL saved to a 0600 file under ~/.ekanos/secrets, never printed) |',
|
|
674
933
|
' events <team> [<product>] [--product <slug>] [--since 24h|7d|<date>]',
|
|
675
934
|
' [--limit <n>] (the integration events recorded for the team, each',
|
|
676
935
|
' with its status, last error and the runs it started, or why none did)',
|
|
677
|
-
' |
|
|
936
|
+
' | audience <team> [<audience>] [--member <email> [--inherit]] [--yes]',
|
|
937
|
+
" (the audience a team starts its members on; a member's own, a Source",
|
|
938
|
+
" admin's only, overrides it; --inherit clears it; moving people to an",
|
|
939
|
+
' audience that shows less needs --yes)',
|
|
940
|
+
' | scope show <team> (DEPRECATED, use audience: the product scopes it holds and the products',
|
|
678
941
|
' it sees in the app) | scope set <team> <scope> [<scope>…] [--yes]',
|
|
679
942
|
' (replaces them; dropping one needs --yes)',
|
|
680
943
|
" A team's agents, for the Source admin (teams <area> <verb> <team> …):",
|
|
681
944
|
' agents list <team> | agents show <team> <key> (is it live, and if',
|
|
682
945
|
' not, why: each connection and whose it is, each trigger and how its',
|
|
683
946
|
' events arrive, last event and run, one Next command)',
|
|
947
|
+
' | agents create <team> --from <dir|agent.json> [--personal]',
|
|
948
|
+
" [--confirm-access] [--no-skills] (the team's own agent, or with",
|
|
949
|
+
' --personal your own, from the agent.json "agents apply" reads;',
|
|
950
|
+
' you become its creator, so you must be an active member of the',
|
|
951
|
+
' team; it starts as a draft) | agents apply <team> <dir|agent.json>',
|
|
952
|
+
' [--personal] [--base-version <n>] [--overwrite] [--confirm-access]',
|
|
953
|
+
' (creates it, or changes it from the same file; a personal agent',
|
|
954
|
+
" is its creator's alone to change)",
|
|
684
955
|
' | agents enable <team> <key> [--as <member-email>]',
|
|
685
956
|
' [--draft] [--confirm-access] (--confirm-access: you also confirm',
|
|
686
957
|
' what it may use) | agents confirm <team> <key> (you confirm what',
|
|
687
958
|
' it may use, as yourself: whoever sets an agent up confirms it, never',
|
|
688
959
|
' a team member) | agents disable <team> <key> --yes | agents',
|
|
960
|
+
' archive <team> <key> [--yes] (off the list; runs and setup kept) |',
|
|
961
|
+
' agents unarchive <team> <key> (back, paused) | agents',
|
|
689
962
|
' unpin <team> <key> | agents pin <team> <key> <version> | agents pin',
|
|
690
963
|
' <team> <key> --draft (this team only runs the unpublished draft, by',
|
|
691
964
|
' hand, every write waiting; the next publish puts it back to',
|
|
@@ -694,17 +967,29 @@ const USAGE = [
|
|
|
694
967
|
' [--reads auto|approve] [--writes auto|approve] [--confirm-access]',
|
|
695
968
|
' | agents skills <team> <key> [add|remove <skill>] (where the',
|
|
696
969
|
' template allows team skills; its own skills stay)',
|
|
697
|
-
'
|
|
970
|
+
' | agents tags <team> <key> [add|remove <tag>] (labels that grant',
|
|
971
|
+
' nothing; a tag the team lacks is made)',
|
|
972
|
+
' triggers list|add|remove <team> <key> … (add … schedule --cron',
|
|
973
|
+
' <expr> [--timezone <zone>] --prompt <text> | add … webhook --prompt',
|
|
974
|
+
' <text> (its token saved to a 0600 file, never printed; a personal',
|
|
975
|
+
" agent's webhook acts as its creator) | add … event <id>",
|
|
698
976
|
" [--filter field=a,b]… or --filter '<json>'; remove <trigger-id|key> --yes;",
|
|
699
977
|
' add … slack --channel',
|
|
700
978
|
' <#name|id>… [--dms] --yes | add … linear [--label <name>]…',
|
|
701
979
|
' [--no-mention], once installed with teams connect) | triggers',
|
|
702
980
|
" 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)
|
|
981
|
+
' new token, the old one revoked; saved to a 0600 file, never printed)',
|
|
982
|
+
' | triggers enable|disable <team> <key> <trigger-id|key> (disable',
|
|
983
|
+
' asks first, --yes in a script) | triggers edit <team> <key>',
|
|
984
|
+
' <trigger-id|key> [--prompt …] [--cron … --timezone …] [--filter …]',
|
|
985
|
+
' [--channel …] [--dms|--no-dms] [--label …] [--mention|--no-mention]',
|
|
986
|
+
' (in place: a webhook keeps its URL and token) | links list|add|remove',
|
|
704
987
|
' <team> <from-key> [<to-key> --kind talk|delegate --mode await|handoff]',
|
|
705
988
|
' (remove <link-id|to-key> [--kind <kind>] --yes)',
|
|
706
|
-
' | mcp list|add|status|token|effect|remove <team> [<server-key> …]',
|
|
707
|
-
' (remove needs --yes
|
|
989
|
+
' | mcp list|add|status|token|effect|refresh|remove <team> [<server-key> …]',
|
|
990
|
+
' (remove needs --yes; refresh <team> --agent <key>: every server it',
|
|
991
|
+
' has) | mcp attach|detach <team> <server-key> <agent-key> (detach',
|
|
992
|
+
' asks first, --yes in a script; where the template allows)',
|
|
708
993
|
' Every area also takes the team as --team <slug>.',
|
|
709
994
|
' ("ekanos teams --help" spells out each area)',
|
|
710
995
|
' reviewers Who decides agent reply drafts, for the Source admin:',
|
|
@@ -782,8 +1067,29 @@ const USAGE = [
|
|
|
782
1067
|
" approvals What a team's agent runs wait on: list --team <slug> |",
|
|
783
1068
|
' approve|reject <id> --team <slug> [--reason "…"] |',
|
|
784
1069
|
' edit <id> --team <slug> --body <file> (edit & send a reply draft)',
|
|
1070
|
+
' The Source admin sees all; any other seat holder only what they',
|
|
1071
|
+
" may decide (managing or reviewing the team's agents, a named",
|
|
1072
|
+
" reviewer, a personal agent's creator). The first decision wins.",
|
|
1073
|
+
" workflows A team's workflows, for the Source admin (each takes --team <slug>;",
|
|
1074
|
+
' a workflow is named by its id or its name):',
|
|
1075
|
+
' list [--all] | show <workflow> (status, trigger, Custom Code review',
|
|
1076
|
+
' state, recent runs; --json: the definition) | pull <workflow>',
|
|
1077
|
+
' [--out <dir>] [--force] (writes workflow.json, the JSON the editor',
|
|
1078
|
+
' saves) | apply <file|dir> [--update <workflow>] (a new draft, or',
|
|
1079
|
+
" that workflow's definition replaced; the editor's checks: shape,",
|
|
1080
|
+
' tool effects, Custom Code security review, approval gates before',
|
|
1081
|
+
' writes) | enable <workflow> [--confirm-access] (activation re-checks',
|
|
1082
|
+
' it; Custom Code that writes or reaches a host needs your approval,',
|
|
1083
|
+
' asked at a terminal) | disable <workflow> | run <workflow>',
|
|
1084
|
+
' [--dry-run [--input <file.json>]] [--follow] (a live run needs it',
|
|
1085
|
+
' on; --dry-run records writes instead of sending them) |',
|
|
1086
|
+
' runs list [--workflow <workflow>] [--status <status>] | runs show',
|
|
1087
|
+
' <run-id> | runs cancel <run-id> [--yes] | approvals list |',
|
|
1088
|
+
' approvals approve|reject <id> [--reason "…"]',
|
|
785
1089
|
' use Set this project\'s publish target ("ekanos use <source-slug>")',
|
|
786
|
-
' publish Validate, pack and submit the integration to an Ekanos host',
|
|
1090
|
+
' publish Validate, pack and submit the integration to an Ekanos host.',
|
|
1091
|
+
' In a repo: publish [<package>...] | --all [--dry-run] (integrations',
|
|
1092
|
+
' first, each package gated, artifacts under .ekanos/publish/)',
|
|
787
1093
|
' upgrade Move this toolchain to a coherent target version, with',
|
|
788
1094
|
' verify-and-rollback (--check --yes --no-verify --host <url>)',
|
|
789
1095
|
'',
|
|
@@ -796,7 +1102,7 @@ const USAGE = [
|
|
|
796
1102
|
' bare "ekanos upgrade" MUTATES the project (installs the target versions,',
|
|
797
1103
|
' verifies with validate + the test script, rolls back on any failure).',
|
|
798
1104
|
'',
|
|
799
|
-
'Host resolution (logout, whoami, status, sources, catalog, apps, teams, reviewers, routes, agents, skills, knowledge, runs, approvals, use, publish, upgrade):',
|
|
1105
|
+
'Host resolution (logout, whoami, status, sources, catalog, apps, teams, reviewers, routes, agents, skills, knowledge, runs, approvals, workflows, use, publish, upgrade):',
|
|
800
1106
|
' --host, else EKANOS_HOST, else the "host" field in ekanos.json, else the',
|
|
801
1107
|
' sole stored login. "ekanos publish" saves host and source to ekanos.json.',
|
|
802
1108
|
' "ekanos login" never reads ekanos.json for a host (--host, else',
|
|
@@ -825,16 +1131,17 @@ const USAGE = [
|
|
|
825
1131
|
* `process.exit`, so this stays fully testable.
|
|
826
1132
|
*/
|
|
827
1133
|
export async function run(argv, options = {}) {
|
|
828
|
-
var _a, _b, _c, _d;
|
|
1134
|
+
var _a, _b, _c, _d, _e, _f;
|
|
829
1135
|
const jsonFlag = scanJsonFlag(argv);
|
|
1136
|
+
setInvocation((_a = options.invocation) !== null && _a !== void 0 ? _a : detectInvocation((_b = options.env) !== null && _b !== void 0 ? _b : process.env), COMMANDS);
|
|
830
1137
|
const ctx = new CliContext({
|
|
831
1138
|
jsonFlag,
|
|
832
1139
|
stdout: options.stdout,
|
|
833
1140
|
stderr: options.stderr,
|
|
834
1141
|
env: options.env,
|
|
835
1142
|
});
|
|
836
|
-
const cwd = (
|
|
837
|
-
const env = (
|
|
1143
|
+
const cwd = (_c = options.cwd) !== null && _c !== void 0 ? _c : process.cwd();
|
|
1144
|
+
const env = (_d = options.env) !== null && _d !== void 0 ? _d : process.env;
|
|
838
1145
|
try {
|
|
839
1146
|
// `--version` is global and verb-independent, so it is answered before the
|
|
840
1147
|
// command is even resolved: `ekanos --version` and `ekanos validate
|
|
@@ -853,36 +1160,35 @@ export async function run(argv, options = {}) {
|
|
|
853
1160
|
tool: 'ekanos',
|
|
854
1161
|
error: 'unknown-command',
|
|
855
1162
|
commands: COMMANDS,
|
|
856
|
-
|
|
1163
|
+
help: 'ekanos --help',
|
|
857
1164
|
});
|
|
858
1165
|
throw usageError(`Unknown command or flag "${argv[0]}".`, `Run one of: ${COMMANDS.join(', ')}. See "ekanos --help".`);
|
|
859
1166
|
}
|
|
860
1167
|
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".`);
|
|
1168
|
+
const unknown = unknownCommand(command, rest, COMMANDS);
|
|
1169
|
+
ctx.emitClaudeCodeHint(Object.assign(Object.assign({ tool: 'ekanos', error: 'unknown-command', given: command }, (unknown.suggestion ? { suggestion: unknown.suggestion } : {})), { commands: COMMANDS, help: 'ekanos --help' }));
|
|
1170
|
+
throw unknown.error;
|
|
869
1171
|
}
|
|
870
1172
|
const specs = Object.assign(Object.assign({}, GLOBAL_SPECS), COMMAND_SPECS[command]);
|
|
871
1173
|
const parsed = parseArgv(rest, specs);
|
|
872
1174
|
if (parsed.flags.help === true) {
|
|
873
1175
|
return emitCommandHelp(ctx, command);
|
|
874
1176
|
}
|
|
875
|
-
const positionalNames = (
|
|
1177
|
+
const positionalNames = (_e = POSITIONAL_COMMANDS[command]) !== null && _e !== void 0 ? _e : [];
|
|
876
1178
|
if (positionalNames.length === 0 && parsed.positionals.length > 0) {
|
|
877
1179
|
throw usageError(`"${command}" takes no positional arguments (got "${parsed.positionals[0]}").`, `Pass options as flags, e.g. "--dir <path>". See "ekanos ${command} --help".`);
|
|
878
1180
|
}
|
|
879
|
-
if (parsed.positionals.length > positionalNames.length
|
|
1181
|
+
if (parsed.positionals.length > positionalNames.length &&
|
|
1182
|
+
!VARIADIC_COMMANDS.has(command)) {
|
|
880
1183
|
const usage = positionalNames.map((name) => `<${name}>`).join(' ');
|
|
881
1184
|
throw usageError(`"${command}" takes at most ${positionalNames.length} positional ` +
|
|
882
1185
|
`argument${positionalNames.length === 1 ? '' : 's'} (${usage}), ` +
|
|
883
1186
|
`got ${parsed.positionals.length}.`, `e.g. "ekanos ${command} ${usage}". See "ekanos ${command} --help".`);
|
|
884
1187
|
}
|
|
885
|
-
const dir = (
|
|
1188
|
+
const dir = (_f = parsed.flags.dir) !== null && _f !== void 0 ? _f : cwd;
|
|
1189
|
+
if (REPO_ROOT_REFUSED.has(command) && isRepoRoot(path.resolve(dir))) {
|
|
1190
|
+
throw preconditionError(`"${command}" works on one package, and ${dir} is a repo root.`, `Run it inside a package (cd integrations/<slug> or cd experiences/<slug>), or use "ekanos publish --all" for the whole repo.`);
|
|
1191
|
+
}
|
|
886
1192
|
switch (command) {
|
|
887
1193
|
case 'init':
|
|
888
1194
|
return await runInit(ctx, {
|
|
@@ -892,6 +1198,7 @@ export async function run(argv, options = {}) {
|
|
|
892
1198
|
force: parsed.flags.force === true,
|
|
893
1199
|
yes: parsed.flags.yes === true,
|
|
894
1200
|
docs: parsed.flags.docs,
|
|
1201
|
+
kind: parsed.flags.kind,
|
|
895
1202
|
stdinIsTTY: options.stdinIsTTY,
|
|
896
1203
|
});
|
|
897
1204
|
case 'validate':
|
|
@@ -903,6 +1210,7 @@ export async function run(argv, options = {}) {
|
|
|
903
1210
|
host: parsed.flags.host,
|
|
904
1211
|
force: parsed.flags.force === true,
|
|
905
1212
|
start: parsed.flags.start,
|
|
1213
|
+
contractsDir: parsed.flags['contracts-dir'],
|
|
906
1214
|
env,
|
|
907
1215
|
});
|
|
908
1216
|
case 'test':
|
|
@@ -952,6 +1260,19 @@ export async function run(argv, options = {}) {
|
|
|
952
1260
|
positionals: parsed.positionals,
|
|
953
1261
|
source: parsed.flags.source,
|
|
954
1262
|
yes: parsed.flags.yes === true,
|
|
1263
|
+
flags: parsed.flags,
|
|
1264
|
+
dir,
|
|
1265
|
+
env,
|
|
1266
|
+
stdinIsTTY: options.stdinIsTTY,
|
|
1267
|
+
ask: options.ask,
|
|
1268
|
+
});
|
|
1269
|
+
case 'audiences':
|
|
1270
|
+
return await runAudiences(ctx, {
|
|
1271
|
+
host: parsed.flags.host,
|
|
1272
|
+
source: parsed.flags.source,
|
|
1273
|
+
positionals: parsed.positionals,
|
|
1274
|
+
yes: parsed.flags.yes === true,
|
|
1275
|
+
flags: parsed.flags,
|
|
955
1276
|
dir,
|
|
956
1277
|
env,
|
|
957
1278
|
});
|
|
@@ -977,6 +1298,10 @@ export async function run(argv, options = {}) {
|
|
|
977
1298
|
confirm: options.confirm,
|
|
978
1299
|
noWait: parsed.flags['no-wait'] === true,
|
|
979
1300
|
yes: parsed.flags.yes === true,
|
|
1301
|
+
flags: parsed.flags,
|
|
1302
|
+
readStdin: options.readStdin,
|
|
1303
|
+
openUrl: options.openUrl,
|
|
1304
|
+
secretFormTimeoutMs: options.secretFormTimeoutMs,
|
|
980
1305
|
});
|
|
981
1306
|
case 'teams':
|
|
982
1307
|
return await runTeams(ctx, {
|
|
@@ -1000,6 +1325,8 @@ export async function run(argv, options = {}) {
|
|
|
1000
1325
|
askSecret: options.askSecret,
|
|
1001
1326
|
openUrl: options.openUrl,
|
|
1002
1327
|
pollDelayMs: options.pollDelayMs,
|
|
1328
|
+
readStdin: options.readStdin,
|
|
1329
|
+
secretFormTimeoutMs: options.secretFormTimeoutMs,
|
|
1003
1330
|
});
|
|
1004
1331
|
case 'reviewers':
|
|
1005
1332
|
return await runReviewers(ctx, {
|
|
@@ -1112,6 +1439,30 @@ export async function run(argv, options = {}) {
|
|
|
1112
1439
|
stdinIsTTY: options.stdinIsTTY,
|
|
1113
1440
|
confirm: options.confirm,
|
|
1114
1441
|
});
|
|
1442
|
+
case 'workflows':
|
|
1443
|
+
return await runWorkflows(ctx, {
|
|
1444
|
+
host: parsed.flags.host,
|
|
1445
|
+
source: parsed.flags.source,
|
|
1446
|
+
positionals: parsed.positionals,
|
|
1447
|
+
team: parsed.flags.team,
|
|
1448
|
+
all: parsed.flags.all === true,
|
|
1449
|
+
out: parsed.flags.out,
|
|
1450
|
+
force: parsed.flags.force === true,
|
|
1451
|
+
update: parsed.flags.update,
|
|
1452
|
+
confirmAccess: parsed.flags['confirm-access'] === true,
|
|
1453
|
+
dryRun: parsed.flags['dry-run'] === true,
|
|
1454
|
+
input: parsed.flags.input,
|
|
1455
|
+
follow: parsed.flags.follow === true,
|
|
1456
|
+
workflow: parsed.flags.workflow,
|
|
1457
|
+
status: parsed.flags.status,
|
|
1458
|
+
reason: parsed.flags.reason,
|
|
1459
|
+
yes: parsed.flags.yes === true,
|
|
1460
|
+
dir,
|
|
1461
|
+
env,
|
|
1462
|
+
sleep: options.sleep,
|
|
1463
|
+
stdinIsTTY: options.stdinIsTTY,
|
|
1464
|
+
confirm: options.confirm,
|
|
1465
|
+
});
|
|
1115
1466
|
case 'use':
|
|
1116
1467
|
return await runUse(ctx, {
|
|
1117
1468
|
host: parsed.flags.host,
|
|
@@ -1125,6 +1476,9 @@ export async function run(argv, options = {}) {
|
|
|
1125
1476
|
source: parsed.flags.source,
|
|
1126
1477
|
dir,
|
|
1127
1478
|
yes: parsed.flags.yes === true,
|
|
1479
|
+
dryRun: parsed.flags['dry-run'] === true,
|
|
1480
|
+
packages: parsed.positionals,
|
|
1481
|
+
all: parsed.flags.all === true,
|
|
1128
1482
|
env,
|
|
1129
1483
|
stdinIsTTY: options.stdinIsTTY,
|
|
1130
1484
|
confirm: options.confirm,
|
|
@@ -1140,9 +1494,21 @@ export async function run(argv, options = {}) {
|
|
|
1140
1494
|
stdinIsTTY: options.stdinIsTTY,
|
|
1141
1495
|
confirm: options.confirm,
|
|
1142
1496
|
});
|
|
1143
|
-
default:
|
|
1497
|
+
default: {
|
|
1498
|
+
const experienceCommand = EXPERIENCE_COMMANDS.find((candidate) => candidate.name === command);
|
|
1499
|
+
if (experienceCommand) {
|
|
1500
|
+
return await experienceCommand.run(ctx, {
|
|
1501
|
+
flags: parsed.flags,
|
|
1502
|
+
positionals: parsed.positionals,
|
|
1503
|
+
passthrough: parsed.passthrough,
|
|
1504
|
+
dir,
|
|
1505
|
+
cwd,
|
|
1506
|
+
env,
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1144
1509
|
// Unreachable — COMMANDS gate above — but keeps the switch total.
|
|
1145
1510
|
throw usageError(`Unknown command "${command}".`, `Run one of: ${COMMANDS.join(', ')}.`);
|
|
1511
|
+
}
|
|
1146
1512
|
}
|
|
1147
1513
|
}
|
|
1148
1514
|
catch (error) {
|
|
@@ -1221,11 +1587,12 @@ function emitVersion(ctx) {
|
|
|
1221
1587
|
}
|
|
1222
1588
|
const DOCS_FOOTER = `\nDocs: ${SDK_DOCS_URL} (commands: ${docsPage('cli/commands')})`;
|
|
1223
1589
|
function emitHelp(ctx) {
|
|
1590
|
+
// Short on purpose: the command list and where each command's usage is.
|
|
1591
|
+
// The full usage is already the result, and a hint line is not a manual.
|
|
1224
1592
|
ctx.emitClaudeCodeHint({
|
|
1225
1593
|
tool: 'ekanos',
|
|
1226
1594
|
commands: COMMANDS,
|
|
1227
|
-
|
|
1228
|
-
exitCodes: EXIT_CODES,
|
|
1595
|
+
help: 'ekanos <command> --help',
|
|
1229
1596
|
});
|
|
1230
1597
|
return ctx.succeed({ usage: USAGE, commands: COMMANDS, docs: SDK_DOCS_URL }, `${USAGE}${DOCS_FOOTER}`);
|
|
1231
1598
|
}
|