@copado/agentia-cli 1.0.0-beta.9 → 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.
@@ -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}.`);
@@ -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};
@@ -1,10 +1,10 @@
1
1
  import { z } from 'zod';
2
2
  import { assertRequired } from '../assert.js';
3
3
  import { CicdGateway } from '../cicd-gateway.js';
4
- import { attachCapturedOutputLogs, MCP_STDIO_CAPTURE_OPTIONS, withCapturedCommandOutput, } from '../command-output-buffer.js';
4
+ import { MCP_STDIO_CAPTURE_OPTIONS, withCapturedCommandOutput, } from '../command-output-buffer.js';
5
5
  import { reconcileWorkSetCredential, sanitizeWorkSetUserStory } from '../credential-sync.js';
6
6
  import { readDefaults, resolveDefaults, writeLastWorkSelection, } from '../defaults-store.js';
7
- import { checkoutFeatureBranch, fetchOriginBranch, fetchOriginBranchIfExists, listPendingChanges, } from '../git-worktree.js';
7
+ import { checkoutFeatureBranch, fetchOriginBranch, fetchOriginBranchIfExists, getHeadCommitId, listPendingChanges, } from '../git-worktree.js';
8
8
  import { listPaginationZodFields, mcpPaginatedListPayload } from '../list-pagination.js';
9
9
  import { LocalQualityGatesError, parseQualityGatesEnvAssignments, runLocalQualityGates, } from '../local-quality-gates.js';
10
10
  import { FULL_METADATA_SELECTION_TYPES_HELP } from '../nested-metadata-registry.js';
@@ -21,7 +21,7 @@ import { validateWorkMutationPayload, WORK_LONG_TEXT_MAX_LENGTH, WORK_SHORT_TEXT
21
21
  import { fetchWorkItem, fetchWorkItems } from '../work-get.js';
22
22
  import { performWorkLocalCommit } from '../work-local-commit.js';
23
23
  import { reportLocalQualityGatesFailure, reportLocalQualityGatesOutcome, } from '../work-local-run-tests.js';
24
- import { capturingWorkPushHooks, performWorkPush, resolveActiveFeatureWorkItem, resolveWorkPushContext, resolveWorkPushNeed, } from '../work-push.js';
24
+ import { capturingWorkPushHooks, performWorkPush, resolveActiveFeatureWorkItem, resolveWorkPushContext, resolveWorkPushNeed, uploadCapturedPublishLogsBestEffort, } from '../work-push.js';
25
25
  import { performWorkSetNone } from '../work-set-none.js';
26
26
  import { isWorkSetWarning, parseWorkSetSelection, toWorkSetWarningResult, writeWorkSetWarningSelection, } from '../work-set-selection.js';
27
27
  import { reportSubmitUserStoriesAheadBehind } from '../work-submit-ahead-behind.js';
@@ -276,6 +276,7 @@ async function promoteWorkItemDone(args = {}) {
276
276
  pushResult = await performWorkPush({
277
277
  ...pushContext,
278
278
  hooks: capturingWorkPushHooks,
279
+ skipLogUpload: true,
279
280
  skipNestedMetadataDetection: args.skipNestedMetadataDetection,
280
281
  });
281
282
  }
@@ -293,6 +294,12 @@ async function promoteWorkItemDone(args = {}) {
293
294
  },
294
295
  method: 'POST',
295
296
  }));
297
+ const tipCommitId = pushResult?.commits.at(-1)?.id ?? (await getHeadCommitId());
298
+ await uploadCapturedPublishLogsBestEffort({
299
+ commitId: tipCommitId,
300
+ hooks: capturingWorkPushHooks,
301
+ linkedEntityId: await resolveWorkItemId(),
302
+ });
296
303
  return {
297
304
  branch,
298
305
  done,
@@ -343,6 +350,7 @@ async function workSubmit(args = {}) {
343
350
  pushResult = await performWorkPush({
344
351
  ...pushContext,
345
352
  hooks: capturingWorkPushHooks,
353
+ skipLogUpload: true,
346
354
  skipNestedMetadataDetection: args.skipNestedMetadataDetection,
347
355
  });
348
356
  }
@@ -352,13 +360,19 @@ async function workSubmit(args = {}) {
352
360
  workItem,
353
361
  });
354
362
  const submit = await capturingWorkPushHooks.withSpinner('Submitting work item', () => CicdGateway.call({
355
- body: attachCapturedOutputLogs({ workItem }),
363
+ body: { workItem },
356
364
  endpoint: workSubmitEndpoint(),
357
365
  headers: {
358
366
  'Content-Type': 'application/json',
359
367
  },
360
368
  method: 'POST',
361
369
  }));
370
+ const tipCommitId = pushResult?.commits.at(-1)?.id ?? (await getHeadCommitId());
371
+ await uploadCapturedPublishLogsBestEffort({
372
+ commitId: tipCommitId,
373
+ hooks: capturingWorkPushHooks,
374
+ linkedEntityId: await resolveWorkItemId(),
375
+ });
362
376
  return {
363
377
  branch,
364
378
  push: pushResult,