@copado/agentia-cli 1.0.0-beta.8 → 1.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +494 -278
  3. package/dist/commands/adv/auth/status.js +1 -0
  4. package/dist/commands/adv/component/add.js +3 -0
  5. package/dist/commands/adv/component/remove.js +3 -0
  6. package/dist/commands/adv/component/types.js +1 -0
  7. package/dist/commands/adv/job/wait.js +1 -1
  8. package/dist/commands/adv/organization/list.js +1 -0
  9. package/dist/commands/cicd/template/defaults.js +42 -0
  10. package/dist/commands/cicd/template/delete.js +36 -0
  11. package/dist/commands/cicd/template/get.js +48 -0
  12. package/dist/commands/cicd/template/list.js +53 -0
  13. package/dist/commands/cicd/template/upsert.js +45 -0
  14. package/dist/commands/cicd/work/ahead-behind.js +51 -0
  15. package/dist/commands/cicd/work/environment-sync.js +1 -0
  16. package/dist/commands/cicd/work/submit.js +17 -4
  17. package/dist/commands/update.js +10 -2
  18. package/dist/lib/adv-operations.js +3 -1
  19. package/dist/lib/agentia-command.js +35 -0
  20. package/dist/lib/cli-version.js +6 -2
  21. package/dist/lib/headless-file-upload.js +10 -0
  22. package/dist/lib/java-runtime.js +6 -0
  23. package/dist/lib/mcp/adv-tools.js +40 -26
  24. package/dist/lib/mcp/tool-annotations.js +5 -0
  25. package/dist/lib/mcp/tools.js +118 -0
  26. package/dist/lib/mcp/work-tools.js +18 -4
  27. package/dist/lib/runtime.js +1 -1
  28. package/dist/lib/template-flags.js +8 -0
  29. package/dist/lib/template-types.js +21 -0
  30. package/dist/lib/version-warning.js +24 -8
  31. package/dist/lib/work-ahead-behind.js +5 -0
  32. package/dist/lib/work-push.js +2 -1
  33. package/dist/lib/work-types.js +2 -1
  34. package/oclif.manifest.json +898 -508
  35. package/package.json +1 -1
  36. package/templates/AGENTS.md +1 -1
  37. package/templates/skills/agentia-adv/SKILL.md +7 -1
  38. package/templates/skills/agentia-adv/references/pipelines-advanced.md +7 -7
  39. package/templates/skills/agentia-cicd/SKILL.md +5 -1
  40. package/templates/skills/agentia-cicd/references/functions.md +148 -0
  41. package/templates/skills/agentia-cicd/references/templates.md +132 -0
@@ -8,6 +8,7 @@ export default class AdvAuthStatus extends AgentiaCommand {
8
8
  '<%= config.bin %> <%= command.id %> --json',
9
9
  ];
10
10
  async run() {
11
+ await this.parse(AdvAuthStatus);
11
12
  const result = await this.withSpinner('Checking Pipelines Advanced authentication', () => getAdvAuthStatus());
12
13
  this.display(() => {
13
14
  this.log(formatAdvRecord(result));
@@ -29,6 +29,9 @@ export default class AdvComponentAdd extends AgentiaCommand {
29
29
  };
30
30
  async run() {
31
31
  const { args, flags } = await this.parse(AdvComponentAdd);
32
+ if (flags.component === undefined && flags.file === undefined && flags['json-file'] === undefined) {
33
+ this.error('Provide one component input: --component, --file, or --json-file.', { exit: 2 });
34
+ }
32
35
  const components = flags.file === undefined
33
36
  ? flags['json-file'] === undefined
34
37
  ? (flags.component ?? []).map((component) => parseAdvComponentSpec(component))
@@ -24,6 +24,9 @@ export default class AdvComponentRemove extends AgentiaCommand {
24
24
  };
25
25
  async run() {
26
26
  const { args, flags } = await this.parse(AdvComponentRemove);
27
+ if (flags.component === undefined && flags['json-file'] === undefined) {
28
+ this.error('Provide one component input: --component or --json-file.', { exit: 2 });
29
+ }
27
30
  const components = flags['json-file'] === undefined
28
31
  ? (flags.component ?? []).map((component) => parseAdvComponentSpec(component))
29
32
  : readAdvComponentsFromJsonFile(flags['json-file']);
@@ -8,6 +8,7 @@ export default class AdvComponentTypes extends AgentiaCommand {
8
8
  '<%= config.bin %> <%= command.id %> --json',
9
9
  ];
10
10
  async run() {
11
+ await this.parse(AdvComponentTypes);
11
12
  const result = await this.withSpinner('Fetching Pipelines Advanced component types', () => listAdvComponentTypes());
12
13
  this.display(() => this.log(formatAdvRecord({ views: result.views.length })));
13
14
  return result;
@@ -13,7 +13,7 @@ export default class AdvJobWait extends AgentiaCommand {
13
13
  ];
14
14
  static flags = {
15
15
  interval: Flags.integer({ description: 'Seconds between job status polls (default: 3).' }),
16
- timeout: Flags.integer({ description: 'Maximum seconds to wait (default: 3600).' }),
16
+ timeout: Flags.integer({ description: 'Maximum seconds to wait; the remote run continues after timeout (default: 3600).' }),
17
17
  };
18
18
  async run() {
19
19
  const { args, flags } = await this.parse(AdvJobWait);
@@ -8,6 +8,7 @@ export default class AdvOrganizationList extends AgentiaCommand {
8
8
  '<%= config.bin %> <%= command.id %> --json',
9
9
  ];
10
10
  async run() {
11
+ await this.parse(AdvOrganizationList);
11
12
  const result = await this.withSpinner('Fetching Pipelines Advanced organizations', () => listAdvOrganizations());
12
13
  this.display(() => {
13
14
  if (result.organizations.length === 0)
@@ -0,0 +1,42 @@
1
+ import { AgentiaCommand } from '../../../lib/agentia-command.js';
2
+ import { CicdGateway } from '../../../lib/cicd-gateway.js';
3
+ import { buildTemplateDefaultsQuery, resolveTemplateWritePath, templateDefaultsFlags } from '../../../lib/template-flags.js';
4
+ import { formatTemplateDetail, normalizeTemplate, templateDefaultsEndpoint, writeTemplateDiskFile, } from '../../../lib/template-types.js';
5
+ export default class TemplateDefaults extends AgentiaCommand {
6
+ static description = 'Scaffold default Copado Job Template metadata without writing to Salesforce (legacy create ≈ defaults --write)';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %> --name MyTemplate',
9
+ '<%= config.bin %> <%= command.id %> --name MyTemplate --api-name MyTemplate_1 --write',
10
+ '<%= config.bin %> <%= command.id %> --name MyTemplate --output ./copado/templates/MyTemplate_1.metadata.json --json',
11
+ ];
12
+ static flags = templateDefaultsFlags;
13
+ async run() {
14
+ const { flags } = await this.parse(TemplateDefaults);
15
+ let query;
16
+ try {
17
+ query = buildTemplateDefaultsQuery(flags);
18
+ }
19
+ catch (error) {
20
+ this.error(error instanceof Error ? error.message : String(error), { exit: 2 });
21
+ }
22
+ const response = await this.withSpinner('Scaffolding template defaults', () => CicdGateway.call({
23
+ endpoint: templateDefaultsEndpoint(query),
24
+ method: 'GET',
25
+ }));
26
+ const template = normalizeTemplate(response);
27
+ let filePath;
28
+ const writePath = resolveTemplateWritePath(template.apiName, flags);
29
+ if (writePath !== undefined) {
30
+ filePath = await writeTemplateDiskFile(template, writePath);
31
+ }
32
+ this.display(() => {
33
+ this.log('Scaffolded template defaults (not persisted).');
34
+ this.log(formatTemplateDetail(template));
35
+ if (filePath !== undefined) {
36
+ this.log(`Wrote ${filePath}`);
37
+ }
38
+ });
39
+ return filePath === undefined ? template : { ...template, filePath };
40
+ }
41
+ }
42
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1,36 @@
1
+ import { Args } from '@oclif/core';
2
+ import { AgentiaCommand } from '../../../lib/agentia-command.js';
3
+ import { CicdGateway } from '../../../lib/cicd-gateway.js';
4
+ import { assertValidTemplateApiName, templateEndpoint } from '../../../lib/template-types.js';
5
+ export default class TemplateDelete extends AgentiaCommand {
6
+ static args = {
7
+ 'api-name': Args.string({
8
+ description: 'Template API name',
9
+ required: true,
10
+ }),
11
+ };
12
+ static description = 'Delete a Copado Job Template by API name';
13
+ static examples = [
14
+ '<%= config.bin %> <%= command.id %> MyTemplate_1',
15
+ '<%= config.bin %> <%= command.id %> MyTemplate_1 --json',
16
+ ];
17
+ async run() {
18
+ const { args } = await this.parse(TemplateDelete);
19
+ let apiName;
20
+ try {
21
+ apiName = assertValidTemplateApiName(args['api-name']);
22
+ }
23
+ catch (error) {
24
+ this.error(error instanceof Error ? error.message : String(error), { exit: 2 });
25
+ }
26
+ await this.withSpinner('Deleting template', () => CicdGateway.call({
27
+ endpoint: templateEndpoint(apiName),
28
+ method: 'DELETE',
29
+ }));
30
+ this.display(() => {
31
+ this.log(`Deleted template ${apiName}.`);
32
+ });
33
+ return { apiName };
34
+ }
35
+ }
36
+ //# sourceMappingURL=delete.js.map
@@ -0,0 +1,48 @@
1
+ import { Args } from '@oclif/core';
2
+ import { AgentiaCommand } from '../../../lib/agentia-command.js';
3
+ import { CicdGateway } from '../../../lib/cicd-gateway.js';
4
+ import { resolveTemplateWritePath, templateGetFlags } from '../../../lib/template-flags.js';
5
+ import { formatTemplateDetail, normalizeTemplate, templateEndpoint, writeTemplateDiskFile, } from '../../../lib/template-types.js';
6
+ export default class TemplateGet extends AgentiaCommand {
7
+ static args = {
8
+ 'api-name': Args.string({
9
+ description: 'Template API name',
10
+ required: true,
11
+ }),
12
+ };
13
+ static description = 'Get a Copado Job Template by API name (legacy retrieve ≈ get --write)';
14
+ static examples = [
15
+ '<%= config.bin %> <%= command.id %> MyTemplate_1',
16
+ '<%= config.bin %> <%= command.id %> MyTemplate_1 --write',
17
+ '<%= config.bin %> <%= command.id %> MyTemplate_1 --json',
18
+ ];
19
+ static flags = templateGetFlags;
20
+ async run() {
21
+ const { args, flags } = await this.parse(TemplateGet);
22
+ let endpoint;
23
+ try {
24
+ endpoint = templateEndpoint(args['api-name']);
25
+ }
26
+ catch (error) {
27
+ this.error(error instanceof Error ? error.message : String(error), { exit: 2 });
28
+ }
29
+ const response = await this.withSpinner('Fetching template', () => CicdGateway.call({
30
+ endpoint,
31
+ method: 'GET',
32
+ }));
33
+ const template = normalizeTemplate(response);
34
+ let filePath;
35
+ const writePath = resolveTemplateWritePath(template.apiName, flags);
36
+ if (writePath !== undefined) {
37
+ filePath = await writeTemplateDiskFile(template, writePath);
38
+ }
39
+ this.display(() => {
40
+ this.log(formatTemplateDetail(template));
41
+ if (filePath !== undefined) {
42
+ this.log(`Wrote ${filePath}`);
43
+ }
44
+ });
45
+ return filePath === undefined ? template : { ...template, filePath };
46
+ }
47
+ }
48
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1,53 @@
1
+ import { Flags } from '@oclif/core';
2
+ import { AgentiaCommand } from '../../../lib/agentia-command.js';
3
+ import { CicdGateway } from '../../../lib/cicd-gateway.js';
4
+ import { buildListPaginationQuery, displayListPagination, listPaginationFlags, } from '../../../lib/list-pagination.js';
5
+ import { formatTemplateTable, normalizeTemplatesListPage, TEMPLATE_LIST_TYPES, templatesEndpoint, } from '../../../lib/template-types.js';
6
+ export default class TemplateList extends AgentiaCommand {
7
+ static description = 'List Copado Job Templates';
8
+ static examples = [
9
+ '<%= config.bin %> <%= command.id %>',
10
+ '<%= config.bin %> <%= command.id %> --type all',
11
+ '<%= config.bin %> <%= command.id %> --name Demo --page-size 50',
12
+ '<%= config.bin %> <%= command.id %> --fetch-all --json',
13
+ ];
14
+ static flags = {
15
+ ...listPaginationFlags,
16
+ 'fetch-all': Flags.boolean({
17
+ default: false,
18
+ description: 'Fetch all matching templates (incompatible with --cursor on the gateway)',
19
+ }),
20
+ name: Flags.string({
21
+ description: 'Filter by name substring',
22
+ }),
23
+ type: Flags.string({
24
+ default: 'custom',
25
+ description: 'List Custom templates only, or all templates',
26
+ options: [...TEMPLATE_LIST_TYPES],
27
+ }),
28
+ };
29
+ async run() {
30
+ const { flags } = await this.parse(TemplateList);
31
+ const pagination = buildListPaginationQuery(flags);
32
+ const response = await this.withSpinner('Fetching templates', () => CicdGateway.call({
33
+ endpoint: templatesEndpoint({
34
+ ...pagination,
35
+ fetchAll: flags['fetch-all'] === true ? true : undefined,
36
+ name: flags.name,
37
+ type: flags.type,
38
+ }),
39
+ method: 'GET',
40
+ }));
41
+ const page = normalizeTemplatesListPage(response);
42
+ this.display(() => {
43
+ if (page.data.length === 0) {
44
+ this.log('No templates found.');
45
+ return;
46
+ }
47
+ this.log(formatTemplateTable(page.data));
48
+ displayListPagination(this.log.bind(this), page);
49
+ });
50
+ return page;
51
+ }
52
+ }
53
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1,45 @@
1
+ import { Args } from '@oclif/core';
2
+ import { AgentiaCommand } from '../../../lib/agentia-command.js';
3
+ import { CicdGateway } from '../../../lib/cicd-gateway.js';
4
+ import { buildTemplateUpsertPayload, templateUpsertFlags } from '../../../lib/template-flags.js';
5
+ import { formatTemplateDetail, normalizeTemplate, templateEndpoint, } from '../../../lib/template-types.js';
6
+ export default class TemplateUpsert extends AgentiaCommand {
7
+ static args = {
8
+ 'api-name': Args.string({
9
+ description: 'Template API name',
10
+ required: true,
11
+ }),
12
+ };
13
+ static description = 'Create or update a Copado Job Template by API name (legacy deploy ≈ upsert reading disk or --file)';
14
+ static examples = [
15
+ '<%= config.bin %> <%= command.id %> MyTemplate_1',
16
+ '<%= config.bin %> <%= command.id %> MyTemplate_1 --file ./copado/templates/MyTemplate_1.metadata.json',
17
+ '<%= config.bin %> <%= command.id %> MyTemplate_1 --name "My Template" --steps-file ./steps.json --json',
18
+ ];
19
+ static flags = templateUpsertFlags;
20
+ async run() {
21
+ const { args, flags } = await this.parse(TemplateUpsert);
22
+ let payload;
23
+ try {
24
+ payload = await buildTemplateUpsertPayload(args['api-name'], flags);
25
+ }
26
+ catch (error) {
27
+ this.error(error instanceof Error ? error.message : String(error), { exit: 2 });
28
+ }
29
+ const response = await this.withSpinner('Upserting template', () => CicdGateway.call({
30
+ body: payload,
31
+ endpoint: templateEndpoint(args['api-name']),
32
+ headers: {
33
+ 'Content-Type': 'application/json',
34
+ },
35
+ method: 'PUT',
36
+ }));
37
+ const template = normalizeTemplate(response);
38
+ this.display(() => {
39
+ this.log(`Upserted template ${template.apiName ?? args['api-name']} (ID: ${template.id ?? 'unknown id'}).`);
40
+ this.log(formatTemplateDetail(template));
41
+ });
42
+ return template;
43
+ }
44
+ }
45
+ //# sourceMappingURL=upsert.js.map
@@ -0,0 +1,51 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { AgentiaCommand } from '../../../lib/agentia-command.js';
3
+ import { formatWorkAheadBehindResult, performWorkAheadBehind, WorkAheadBehindValidationError, } from '../../../lib/work-ahead-behind.js';
4
+ export default class WorkAheadBehind extends AgentiaCommand {
5
+ static args = {
6
+ environment: Args.string({
7
+ description: 'Copado environment Id or name (defaults to the configured project default environment)',
8
+ required: false,
9
+ }),
10
+ };
11
+ static description = [
12
+ 'Compare user stories ahead of and behind the next pipeline environment.',
13
+ 'Resolves the project (and its pipeline) from the project default or --project,',
14
+ 'finds the unique next environment from pipeline connections for the given or default environment,',
15
+ 'then GET /agentia/headless/work/user-stories-ahead-behind.',
16
+ ].join(' ');
17
+ static examples = [
18
+ '<%= config.bin %> <%= command.id %>',
19
+ '<%= config.bin %> <%= command.id %> dev1',
20
+ '<%= config.bin %> <%= command.id %> a0E... --project a0w...',
21
+ '<%= config.bin %> <%= command.id %> --json',
22
+ ];
23
+ static flags = {
24
+ project: Flags.string({
25
+ description: 'Copado project Id (defaults to the configured project default)',
26
+ }),
27
+ };
28
+ async run() {
29
+ const { args, flags } = await this.parse(WorkAheadBehind);
30
+ try {
31
+ const result = await this.withSpinner('Comparing user stories ahead and behind', () => performWorkAheadBehind({
32
+ ...(args.environment === undefined ? {} : { environment: args.environment }),
33
+ ...(flags.project === undefined ? {} : { project: flags.project }),
34
+ }));
35
+ this.display(() => {
36
+ this.log(formatWorkAheadBehindResult(result));
37
+ });
38
+ return result;
39
+ }
40
+ catch (error) {
41
+ if (error instanceof WorkAheadBehindValidationError) {
42
+ this.error(error.message, {
43
+ exit: 1,
44
+ ...(error.suggestions === undefined ? {} : { suggestions: error.suggestions }),
45
+ });
46
+ }
47
+ throw error;
48
+ }
49
+ }
50
+ }
51
+ //# sourceMappingURL=ahead-behind.js.map
@@ -13,6 +13,7 @@ export default class WorkEnvironmentSync extends AgentiaCommand {
13
13
  'If guessed pathspecs still conflict, PATCH the back-promotion status to Merge Conflict, resolve the files, and re-run with --promotion and --continue. The promotion destination environment supplies the dest org branch and the next-env branch.',
14
14
  'To discard a conflicted merge, re-run with --promotion and --abort (runs git merge --abort and sets the back-promotion status to Draft).',
15
15
  'After a successful sync, PATCH the back-promotion status to Completed.',
16
+ 'On git/merge failure (including conflicts) and after a successful --continue, uploads the captured command transcript as a Salesforce File on the back-promotion (`Environment Sync Logs <name-or-id> <datetime>.txt`) via `/agentia/headless/file/upload`. HTTP 404 is ignored until that endpoint is rolled out; other upload failures are warned and do not change the environment-sync outcome.',
16
17
  ].join(' ');
17
18
  static examples = [
18
19
  '<%= config.bin %> <%= command.id %> --destination-environment=dev1',
@@ -2,14 +2,15 @@ import { Flags } from '@oclif/core';
2
2
  import path from 'node:path';
3
3
  import { AgentiaCommand } from '../../../lib/agentia-command.js';
4
4
  import { CicdGateway } from '../../../lib/cicd-gateway.js';
5
- import { attachCapturedOutputLogs, commandStdioCaptureOptions, withCapturedCommandOutput } from '../../../lib/command-output-buffer.js';
5
+ import { commandStdioCaptureOptions, withCapturedCommandOutput } from '../../../lib/command-output-buffer.js';
6
6
  import { readLastBaseBranch, readLastPullRequestBaseUrl, readSkipPullRequest, } from '../../../lib/defaults-store.js';
7
- import { listPendingChanges } from '../../../lib/git-worktree.js';
7
+ import { getHeadCommitId, listPendingChanges } from '../../../lib/git-worktree.js';
8
8
  import { LocalQualityGatesError, resolveLocalQualityGatesScript, runLocalQualityGates, } from '../../../lib/local-quality-gates.js';
9
9
  import { openUrl } from '../../../lib/open-browser.js';
10
+ import { resolveWorkItemId } from '../../../lib/work-active.js';
10
11
  import { pickWorkDoneFlags, runWorkDone, workDoneFlags } from '../../../lib/work-done.js';
11
12
  import { reportLocalQualityGatesFailure, reportLocalQualityGatesOutcome, } from '../../../lib/work-local-run-tests.js';
12
- import { performWorkPush, resolveActiveFeatureWorkItem, resolveWorkPushContext, resolveWorkPushNeed, WorkPushValidationError, } from '../../../lib/work-push.js';
13
+ import { performWorkPush, resolveActiveFeatureWorkItem, resolveWorkPushContext, resolveWorkPushNeed, uploadCapturedPublishLogsBestEffort, WorkPushValidationError, } from '../../../lib/work-push.js';
13
14
  import { reportSubmitUserStoriesAheadBehind } from '../../../lib/work-submit-ahead-behind.js';
14
15
  import { waitForPendingCommitJobBeforeSubmit } from '../../../lib/work-submit-wait.js';
15
16
  import { buildPullRequestCompareUrl, formatWorkCommandMessage, workSubmitEndpoint, } from '../../../lib/work-types.js';
@@ -21,6 +22,7 @@ export default class WorkSubmit extends AgentiaCommand {
21
22
  '(Promote Action with validate=true).',
22
23
  'When the last pending related job template name contains Commit, waits up to 5 minutes for that job before submitting.',
23
24
  'Before submit or promote, counts user stories ahead and behind between the source environment and the next pipeline environment, and warns when stories behind might cause promotion conflicts (advising `agentia cicd work environment-sync`).',
25
+ 'After a successful submit or promote, uploads the captured command output as a Salesforce File on the user story (`Local Commit Logs <commitId> <datetime>.txt`) via `/agentia/headless/file/upload`. HTTP 404 is ignored until that endpoint is rolled out; other upload failures are warned and do not fail the command.',
24
26
  'With --done or --deploy, matches Copado UI Submit when promoting (validate=false / headless work/done).',
25
27
  'cicd work done is a compatibility alias of this command with --done.',
26
28
  ].join(' ');
@@ -185,6 +187,7 @@ export default class WorkSubmit extends AgentiaCommand {
185
187
  log: (message) => this.log(message),
186
188
  withSpinner: (message, action) => this.withSpinner(message, action),
187
189
  },
190
+ skipLogUpload: true,
188
191
  skipNestedMetadataDetection: flags['skip-nested-metadata-detection'],
189
192
  });
190
193
  }
@@ -209,7 +212,7 @@ export default class WorkSubmit extends AgentiaCommand {
209
212
  });
210
213
  await waitForPendingCommitJobBeforeSubmit(this, workItem);
211
214
  const submit = await this.withSpinner('Submitting work item', () => CicdGateway.call({
212
- body: attachCapturedOutputLogs({ workItem }),
215
+ body: { workItem },
213
216
  endpoint: workSubmitEndpoint(),
214
217
  headers: {
215
218
  'Content-Type': 'application/json',
@@ -219,6 +222,16 @@ export default class WorkSubmit extends AgentiaCommand {
219
222
  this.display(() => {
220
223
  this.log(formatWorkCommandMessage(submit.message));
221
224
  });
225
+ const tipCommitId = pushResult?.commits.at(-1)?.id ?? (await getHeadCommitId());
226
+ await uploadCapturedPublishLogsBestEffort({
227
+ commitId: tipCommitId,
228
+ hooks: {
229
+ display: (render) => this.display(render),
230
+ log: (message) => this.log(message),
231
+ withSpinner: (message, action) => this.withSpinner(message, action),
232
+ },
233
+ linkedEntityId: await resolveWorkItemId(),
234
+ });
222
235
  await this.openPullRequestCompareUrl(branch, flags['skip-pull-request']);
223
236
  this.logElapsed(startedAt);
224
237
  return {
@@ -2,20 +2,28 @@ import { Flags } from '@oclif/core';
2
2
  import { AgentiaCommand } from '../lib/agentia-command.js';
3
3
  import { runCliUpdate } from '../lib/cli-update.js';
4
4
  export default class Update extends AgentiaCommand {
5
- static description = 'Update the globally installed Agentia CLI to the newest beta release';
5
+ static description = 'Update the globally installed Agentia CLI to the newest release for the selected channel';
6
6
  static examples = [
7
7
  '<%= config.bin %> <%= command.id %>',
8
8
  '<%= config.bin %> <%= command.id %> --check',
9
+ '<%= config.bin %> <%= command.id %> --channel latest --check',
10
+ '<%= config.bin %> <%= command.id %> --channel rc',
9
11
  '<%= config.bin %> <%= command.id %> --check --json',
10
12
  ];
11
13
  static flags = {
14
+ channel: Flags.option({
15
+ description: 'npm dist-tag to check (rc or latest). Omit to auto-select: prerelease installs compare rc and latest; stable installs use latest only.',
16
+ options: ['rc', 'latest'],
17
+ })(),
12
18
  check: Flags.boolean({
13
19
  description: 'Check for an update without installing it',
14
20
  }),
15
21
  };
16
22
  async run() {
17
23
  const { flags } = await this.parse(Update);
24
+ const requestedChannel = flags.channel ?? 'auto';
18
25
  const result = await this.withSpinner(flags.check ? 'Checking for Agentia CLI updates' : 'Updating Agentia CLI', () => runCliUpdate({
26
+ channel: requestedChannel,
19
27
  checkOnly: flags.check,
20
28
  currentVersion: this.config.version,
21
29
  }));
@@ -24,7 +32,7 @@ export default class Update extends AgentiaCommand {
24
32
  this.log(`Updated Agentia CLI from ${result.currentVersion} to ${result.latestVersion}. Re-run \`agentia --version\` to verify the new installation.`);
25
33
  }
26
34
  else if (result.updateAvailable) {
27
- this.log(`Agentia CLI ${result.latestVersion} is available (current: ${result.currentVersion}). Run \`agentia update\` to install it.`);
35
+ this.log(`Agentia CLI ${result.latestVersion} is available on the ${result.channel} channel (current: ${result.currentVersion}). Run \`agentia update\` to install it.`);
28
36
  }
29
37
  else if (result.versionState === 'ahead') {
30
38
  this.log(`Installed Agentia CLI ${result.currentVersion} is newer than the ${result.channel} channel release ${result.latestVersion}.`);
@@ -1,5 +1,7 @@
1
1
  import {modules} from './runtime.js';
2
+ const AdvQuickDeployUnavailableError = modules["adv-operations.js"]["AdvQuickDeployUnavailableError"]
2
3
  const AdvRunFailedError = modules["adv-operations.js"]["AdvRunFailedError"]
4
+ const AdvWaitTimeoutError = modules["adv-operations.js"]["AdvWaitTimeoutError"]
3
5
  const addAdvComponents = modules["adv-operations.js"]["addAdvComponents"]
4
6
  const advRunErrorJson = modules["adv-operations.js"]["advRunErrorJson"]
5
7
  const assertAdvJobSucceeded = modules["adv-operations.js"]["assertAdvJobSucceeded"]
@@ -26,4 +28,4 @@ const selectedAdvComponents = modules["adv-operations.js"]["selectedAdvComponent
26
28
  const updateAdvDeploymentOptions = modules["adv-operations.js"]["updateAdvDeploymentOptions"]
27
29
  const validateAdvOrganization = modules["adv-operations.js"]["validateAdvOrganization"]
28
30
  const waitForAdvJob = modules["adv-operations.js"]["waitForAdvJob"]
29
- export {AdvRunFailedError, addAdvComponents, advRunErrorJson, assertAdvJobSucceeded, cancelAdvDeployment, createAdvDeployment, deriveAdvJobResult, getAdvAuthStatus, getAdvDeployment, getAdvJob, getAdvOrganization, getStoredAdvAuthSummary, listAdvComponentTypes, listAdvComponents, listAdvDeployments, listAdvJobs, listAdvOrganizations, parseAdvComponentSpec, readAdvComponentsFromJsonFile, readAdvComponentsFromTextFile, refreshAdvComponents, removeAdvComponents, runAdvDeploymentAction, selectedAdvComponents, updateAdvDeploymentOptions, validateAdvOrganization, waitForAdvJob};
31
+ export {AdvQuickDeployUnavailableError, AdvRunFailedError, AdvWaitTimeoutError, addAdvComponents, advRunErrorJson, assertAdvJobSucceeded, cancelAdvDeployment, createAdvDeployment, deriveAdvJobResult, getAdvAuthStatus, getAdvDeployment, getAdvJob, getAdvOrganization, getStoredAdvAuthSummary, listAdvComponentTypes, listAdvComponents, listAdvDeployments, listAdvJobs, listAdvOrganizations, parseAdvComponentSpec, readAdvComponentsFromJsonFile, readAdvComponentsFromTextFile, refreshAdvComponents, removeAdvComponents, runAdvDeploymentAction, selectedAdvComponents, updateAdvDeploymentOptions, validateAdvOrganization, waitForAdvJob};
@@ -4,8 +4,42 @@ import { createTransactionId, runWithGatewayTransactionContext } from './cicd-ga
4
4
  import { colorizeCliSeverityError, colorizeCliSeverityText } from './cli-severity-color.js';
5
5
  import { isCommandOutputCaptureActive } from './command-output-buffer.js';
6
6
  import { rememberIdeCommandError } from './ide-command-events.js';
7
+ import { redactErrorMessage, redactSecrets } from './secret-redaction.js';
7
8
  const TRANSACTION_ID_REPORTED = Symbol('agentiaTransactionIdReported');
8
9
  const EXPERIMENTAL_COMMAND_WARNING = 'This command is experimental and may change without notice.';
10
+ const SAFE_ERROR_FIELDS = [
11
+ 'categories',
12
+ 'code',
13
+ 'requestMethod',
14
+ 'requestUrl',
15
+ 'retryAfterSeconds',
16
+ 'statusCode',
17
+ 'suggestions',
18
+ ];
19
+ function recordValue(value) {
20
+ return typeof value === 'object' && value !== null ? value : {};
21
+ }
22
+ function safeErrorJson(err, base) {
23
+ const baseError = recordValue(base.error);
24
+ const source = recordValue(err);
25
+ const error = {
26
+ message: redactErrorMessage(err),
27
+ name: typeof baseError.name === 'string'
28
+ ? baseError.name
29
+ : err instanceof Error && err.name.length > 0
30
+ ? err.name
31
+ : 'Error',
32
+ };
33
+ for (const field of SAFE_ERROR_FIELDS) {
34
+ const value = source[field] ?? baseError[field];
35
+ if (value !== undefined)
36
+ error[field] = redactSecrets(value);
37
+ }
38
+ const oclif = recordValue(baseError.oclif);
39
+ if (typeof oclif.exit === 'number')
40
+ error.oclif = { exit: oclif.exit };
41
+ return error;
42
+ }
9
43
  export function elapsedSecondsSince(startedAtMs, nowMs = Date.now()) {
10
44
  return Math.max(0, Math.floor((nowMs - startedAtMs) / 1000));
11
45
  }
@@ -76,6 +110,7 @@ export class AgentiaCommand extends Command {
76
110
  const warnings = this.jsonWarnings();
77
111
  return {
78
112
  ...base,
113
+ error: safeErrorJson(err, base),
79
114
  ...(warnings.length > 0 ? { warnings } : {}),
80
115
  transactionId: this.commandTransactionId,
81
116
  };
@@ -2,16 +2,20 @@ import {modules} from './runtime.js';
2
2
  const AGENTIA_NPM_REGISTRY = modules["cli-version.js"]["AGENTIA_NPM_REGISTRY"]
3
3
  const AGENTIA_PACKAGE_NAME = modules["cli-version.js"]["AGENTIA_PACKAGE_NAME"]
4
4
  const AGENTIA_RELEASE_CHANNEL = modules["cli-version.js"]["AGENTIA_RELEASE_CHANNEL"]
5
+ const AGENTIA_STABLE_CHANNEL = modules["cli-version.js"]["AGENTIA_STABLE_CHANNEL"]
5
6
  const CliVersionError = modules["cli-version.js"]["CliVersionError"]
6
7
  const VERSION_CACHE_FILENAME = modules["cli-version.js"]["VERSION_CACHE_FILENAME"]
8
+ const VERSION_CACHE_SCHEMA_VERSION = modules["cli-version.js"]["VERSION_CACHE_SCHEMA_VERSION"]
7
9
  const VERSION_CHECK_INTERVAL_MS = modules["cli-version.js"]["VERSION_CHECK_INTERVAL_MS"]
8
10
  const defaultVersionRegistryClient = modules["cli-version.js"]["defaultVersionRegistryClient"]
9
- const fetchChannelVersion = modules["cli-version.js"]["fetchChannelVersion"]
11
+ const fetchDistTags = modules["cli-version.js"]["fetchDistTags"]
10
12
  const isNewerVersion = modules["cli-version.js"]["isNewerVersion"]
13
+ const isPrereleaseVersion = modules["cli-version.js"]["isPrereleaseVersion"]
11
14
  const isVersionCacheStale = modules["cli-version.js"]["isVersionCacheStale"]
12
15
  const readVersionCache = modules["cli-version.js"]["readVersionCache"]
13
16
  const refreshVersionCache = modules["cli-version.js"]["refreshVersionCache"]
17
+ const resolveUpdateCandidate = modules["cli-version.js"]["resolveUpdateCandidate"]
14
18
  const setCliVersionRegistryClientForTests = modules["cli-version.js"]["setCliVersionRegistryClientForTests"]
15
19
  const versionCachePath = modules["cli-version.js"]["versionCachePath"]
16
20
  const writeVersionCache = modules["cli-version.js"]["writeVersionCache"]
17
- export {AGENTIA_NPM_REGISTRY, AGENTIA_PACKAGE_NAME, AGENTIA_RELEASE_CHANNEL, CliVersionError, VERSION_CACHE_FILENAME, VERSION_CHECK_INTERVAL_MS, defaultVersionRegistryClient, fetchChannelVersion, isNewerVersion, isVersionCacheStale, readVersionCache, refreshVersionCache, setCliVersionRegistryClientForTests, versionCachePath, writeVersionCache};
21
+ export {AGENTIA_NPM_REGISTRY, AGENTIA_PACKAGE_NAME, AGENTIA_RELEASE_CHANNEL, AGENTIA_STABLE_CHANNEL, CliVersionError, VERSION_CACHE_FILENAME, VERSION_CACHE_SCHEMA_VERSION, VERSION_CHECK_INTERVAL_MS, defaultVersionRegistryClient, fetchDistTags, isNewerVersion, isPrereleaseVersion, isVersionCacheStale, readVersionCache, refreshVersionCache, resolveUpdateCandidate, setCliVersionRegistryClientForTests, versionCachePath, writeVersionCache};
@@ -0,0 +1,10 @@
1
+ import {modules} from './runtime.js';
2
+ const buildEnvironmentSyncLogsFileName = modules["headless-file-upload.js"]["buildEnvironmentSyncLogsFileName"]
3
+ const buildLocalCommitLogsFileName = modules["headless-file-upload.js"]["buildLocalCommitLogsFileName"]
4
+ const buildMultipartFileBody = modules["headless-file-upload.js"]["buildMultipartFileBody"]
5
+ const formatFileNameDateTime = modules["headless-file-upload.js"]["formatFileNameDateTime"]
6
+ const isMissingHeadlessFileUploadEndpoint = modules["headless-file-upload.js"]["isMissingHeadlessFileUploadEndpoint"]
7
+ const uploadCapturedCommandLogs = modules["headless-file-upload.js"]["uploadCapturedCommandLogs"]
8
+ const uploadCapturedPublishLogs = modules["headless-file-upload.js"]["uploadCapturedPublishLogs"]
9
+ const uploadHeadlessFile = modules["headless-file-upload.js"]["uploadHeadlessFile"]
10
+ export {buildEnvironmentSyncLogsFileName, buildLocalCommitLogsFileName, buildMultipartFileBody, formatFileNameDateTime, isMissingHeadlessFileUploadEndpoint, uploadCapturedCommandLogs, uploadCapturedPublishLogs, uploadHeadlessFile};
@@ -0,0 +1,6 @@
1
+ import {modules} from './runtime.js';
2
+ const MISSING_JAVA_MESSAGE = modules["java-runtime.js"]["MISSING_JAVA_MESSAGE"]
3
+ const isMissingExecutableError = modules["java-runtime.js"]["isMissingExecutableError"]
4
+ const resolveJavaCommand = modules["java-runtime.js"]["resolveJavaCommand"]
5
+ const throwIfMissingJava = modules["java-runtime.js"]["throwIfMissingJava"]
6
+ export {MISSING_JAVA_MESSAGE, isMissingExecutableError, resolveJavaCommand, throwIfMissingJava};