@copado/agentia-cli 1.0.0-beta.2 → 1.0.0-beta.5

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 (55) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +416 -293
  3. package/dist/commands/cicd/data/template/save-detail.js +2 -2
  4. package/dist/commands/cicd/repository/auth/https/configure.js +21 -0
  5. package/dist/commands/cicd/repository/auth/oauth/login.js +56 -0
  6. package/dist/commands/cicd/repository/auth/setup.js +28 -0
  7. package/dist/commands/cicd/repository/auth/ssh/configure.js +22 -0
  8. package/dist/commands/cicd/repository/create.js +2 -2
  9. package/dist/commands/cicd/repository/reset.js +17 -5
  10. package/dist/commands/cicd/repository/update.js +6 -14
  11. package/dist/commands/cicd/work/environment-sync.js +66 -61
  12. package/dist/commands/cicd/work/get.js +5 -9
  13. package/dist/commands/cicd/work/submit.js +1 -1
  14. package/dist/commands/cicd/work/test/apex.js +37 -4
  15. package/dist/commands/cicd/work/test.js +20 -1
  16. package/dist/commands/runtime.js +26 -0
  17. package/dist/hooks/finally/ide-command-event.js +1 -1
  18. package/dist/hooks/init/plugin-host.js +6 -0
  19. package/dist/lib/agentia-command.js +16 -0
  20. package/dist/lib/cicd-gateway.js +2 -1
  21. package/dist/lib/cursor-mcp-config.js +3 -1
  22. package/dist/lib/data-types.js +3 -1
  23. package/dist/lib/git-worktree.js +2 -1
  24. package/dist/lib/local-quality-gates.js +4 -1
  25. package/dist/lib/mcp/data-tools.js +2 -2
  26. package/dist/lib/mcp/server.js +33 -7
  27. package/dist/lib/mcp/tool-annotations.js +3 -0
  28. package/dist/lib/mcp/tools.js +55 -12
  29. package/dist/lib/mcp/work-tools.js +44 -13
  30. package/dist/lib/plugin-host/auth.js +4 -0
  31. package/dist/lib/plugin-host/event-log.js +3 -0
  32. package/dist/lib/plugin-host/format.js +3 -0
  33. package/dist/lib/plugin-host/index.js +7 -0
  34. package/dist/lib/plugin-host/organization.js +4 -0
  35. package/dist/lib/plugin-host/projection-utils.js +6 -0
  36. package/dist/lib/plugin-host/registry.js +6 -0
  37. package/dist/lib/plugin-host/request-scope.js +4 -0
  38. package/dist/lib/plugin-host/work.js +4 -0
  39. package/dist/lib/project-root.js +3 -1
  40. package/dist/lib/repository-auth.js +8 -0
  41. package/dist/lib/repository-flags.js +2 -2
  42. package/dist/lib/repository-types.js +6 -1
  43. package/dist/lib/repository-url-prefill.js +4 -0
  44. package/dist/lib/runtime-invoke-context.js +6 -0
  45. package/dist/lib/runtime-rpc.js +14 -0
  46. package/dist/lib/runtime.js +1 -1
  47. package/dist/lib/setup-templates.js +2 -1
  48. package/dist/lib/work-apex-test-failures.js +13 -0
  49. package/dist/lib/work-apex-test.js +4 -1
  50. package/dist/lib/work-environment-sync.js +1 -2
  51. package/dist/lib/work-get.js +3 -0
  52. package/oclif.manifest.json +315 -174
  53. package/package.json +4 -3
  54. package/templates/skills/agentia-cicd/SKILL.md +1 -1
  55. package/templates/skills/agentia-cicd/references/work.md +2 -2
@@ -3,6 +3,7 @@ import { format } from 'node:util';
3
3
  import { createTransactionId, runWithGatewayTransactionContext } from './cicd-gateway.js';
4
4
  import { isCommandOutputCaptureActive } from './command-output-buffer.js';
5
5
  import { rememberIdeCommandError } from './ide-command-events.js';
6
+ const TRANSACTION_ID_REPORTED = Symbol('agentiaTransactionIdReported');
6
7
  export function elapsedSecondsSince(startedAtMs, nowMs = Date.now()) {
7
8
  return Math.max(0, Math.floor((nowMs - startedAtMs) / 1000));
8
9
  }
@@ -17,6 +18,10 @@ export class AgentiaCommand extends Command {
17
18
  this.commandTransactionId = transactionId;
18
19
  return runWithGatewayTransactionContext({ origin: 'cli', referer: this.id, transactionId }, () => super._run());
19
20
  }
21
+ async catch(error) {
22
+ this.reportHumanErrorTransactionId(error);
23
+ return super.catch(error);
24
+ }
20
25
  display(render) {
21
26
  if (!this.jsonEnabled() || isCommandOutputCaptureActive()) {
22
27
  render();
@@ -64,5 +69,16 @@ export class AgentiaCommand extends Command {
64
69
  throw error;
65
70
  }
66
71
  }
72
+ reportHumanErrorTransactionId(error) {
73
+ if (this.jsonEnabled() || this.commandTransactionId === undefined) {
74
+ return;
75
+ }
76
+ const reportedError = error;
77
+ if (reportedError[TRANSACTION_ID_REPORTED]) {
78
+ return;
79
+ }
80
+ reportedError[TRANSACTION_ID_REPORTED] = true;
81
+ this.logToStderr(`Transaction ID: ${this.commandTransactionId}`);
82
+ }
67
83
  }
68
84
  //# sourceMappingURL=agentia-command.js.map
@@ -9,6 +9,7 @@ const CicdGatewayError = modules["cicd-gateway.js"]["CicdGatewayError"]
9
9
  const GATEWAY_EVENT_API_CALL = modules["cicd-gateway.js"]["GATEWAY_EVENT_API_CALL"]
10
10
  const GATEWAY_EVENT_UNKNOWN = modules["cicd-gateway.js"]["GATEWAY_EVENT_UNKNOWN"]
11
11
  const MCP_CICD_DEFAULT_REQUEST_TIMEOUT_MS = modules["cicd-gateway.js"]["MCP_CICD_DEFAULT_REQUEST_TIMEOUT_MS"]
12
+ const PLUGIN_GATEWAY_EVENT_SERVICE = modules["cicd-gateway.js"]["PLUGIN_GATEWAY_EVENT_SERVICE"]
12
13
  const buildGatewayEventLogPayload = modules["cicd-gateway.js"]["buildGatewayEventLogPayload"]
13
14
  const cicdApiUrl = modules["cicd-gateway.js"]["cicdApiUrl"]
14
15
  const createTransactionId = modules["cicd-gateway.js"]["createTransactionId"]
@@ -40,4 +41,4 @@ const scheduleGatewayEventLog = modules["cicd-gateway.js"]["scheduleGatewayEvent
40
41
  const setGatewayEventLogSenderForTests = modules["cicd-gateway.js"]["setGatewayEventLogSenderForTests"]
41
42
  const setHttpRequestForTests = modules["cicd-gateway.js"]["setHttpRequestForTests"]
42
43
  const tryResolveCicdCredentials = modules["cicd-gateway.js"]["tryResolveCicdCredentials"]
43
- export {AGENTIA_CLIENT_ORIGIN_ENV, AGENTIA_IDE_VERSION_ENV, AI_GATEWAY_EVENT_SERVICE, CICD_ENV, CRT_GATEWAY_EVENT_SERVICE, CicdGateway, CicdGatewayError, GATEWAY_EVENT_API_CALL, GATEWAY_EVENT_UNKNOWN, MCP_CICD_DEFAULT_REQUEST_TIMEOUT_MS, buildGatewayEventLogPayload, cicdApiUrl, createTransactionId, discoverCicdBaseUrl, flushGatewayEventLogsForTests, formatCicdGatewayError, formatGatewayEventTimestamp, gatewayEventSource, gatewayRefererHeaders, gatewayUserAgent, getActiveHttpRequestOptionsForTests, getGatewayClientOrigin, getGatewayReferer, getGatewayTransactionId, isCicdWarningResponseBody, isCicdWarningStatus, maskUrlSecrets, maskedCicdApiUrl, normalizeCicdBaseUrl, parseRetryAfterHeader, resetGatewayEventLogSenderForTests, resetHttpRequestForTests, resolveAndValidateCicdEndpoint, resolveCicdCredentials, resolveCicdRequestTimeoutMs, resolveConfiguredCicdBaseUrl, runWithGatewayTransactionContext, scheduleGatewayEventLog, setGatewayEventLogSenderForTests, setHttpRequestForTests, tryResolveCicdCredentials};
44
+ export {AGENTIA_CLIENT_ORIGIN_ENV, AGENTIA_IDE_VERSION_ENV, AI_GATEWAY_EVENT_SERVICE, CICD_ENV, CRT_GATEWAY_EVENT_SERVICE, CicdGateway, CicdGatewayError, GATEWAY_EVENT_API_CALL, GATEWAY_EVENT_UNKNOWN, MCP_CICD_DEFAULT_REQUEST_TIMEOUT_MS, PLUGIN_GATEWAY_EVENT_SERVICE, buildGatewayEventLogPayload, cicdApiUrl, createTransactionId, discoverCicdBaseUrl, flushGatewayEventLogsForTests, formatCicdGatewayError, formatGatewayEventTimestamp, gatewayEventSource, gatewayRefererHeaders, gatewayUserAgent, getActiveHttpRequestOptionsForTests, getGatewayClientOrigin, getGatewayReferer, getGatewayTransactionId, isCicdWarningResponseBody, isCicdWarningStatus, maskUrlSecrets, maskedCicdApiUrl, normalizeCicdBaseUrl, parseRetryAfterHeader, resetGatewayEventLogSenderForTests, resetHttpRequestForTests, resolveAndValidateCicdEndpoint, resolveCicdCredentials, resolveCicdRequestTimeoutMs, resolveConfiguredCicdBaseUrl, runWithGatewayTransactionContext, scheduleGatewayEventLog, setGatewayEventLogSenderForTests, setHttpRequestForTests, tryResolveCicdCredentials};
@@ -3,14 +3,16 @@ const AGENTIA_MCP_ENTRY = modules["cursor-mcp-config.js"]["AGENTIA_MCP_ENTRY"]
3
3
  const AGENTIA_MCP_SERVER_NAME = modules["cursor-mcp-config.js"]["AGENTIA_MCP_SERVER_NAME"]
4
4
  const detectCursorInstall = modules["cursor-mcp-config.js"]["detectCursorInstall"]
5
5
  const findAgentiaMcpServer = modules["cursor-mcp-config.js"]["findAgentiaMcpServer"]
6
+ const findCurrentAgentiaMcpServer = modules["cursor-mcp-config.js"]["findCurrentAgentiaMcpServer"]
6
7
  const getCursorMcpStatus = modules["cursor-mcp-config.js"]["getCursorMcpStatus"]
7
8
  const globalCursorMcpPath = modules["cursor-mcp-config.js"]["globalCursorMcpPath"]
8
9
  const hasConflictingAgentiaEntry = modules["cursor-mcp-config.js"]["hasConflictingAgentiaEntry"]
9
10
  const inspectCursorMcpStatus = modules["cursor-mcp-config.js"]["inspectCursorMcpStatus"]
10
11
  const isAgentiaMcpEntry = modules["cursor-mcp-config.js"]["isAgentiaMcpEntry"]
12
+ const isCurrentAgentiaMcpEntry = modules["cursor-mcp-config.js"]["isCurrentAgentiaMcpEntry"]
11
13
  const localCursorMcpPath = modules["cursor-mcp-config.js"]["localCursorMcpPath"]
12
14
  const readCursorMcpDocument = modules["cursor-mcp-config.js"]["readCursorMcpDocument"]
13
15
  const resetCursorMcpDepsForTests = modules["cursor-mcp-config.js"]["resetCursorMcpDepsForTests"]
14
16
  const setCursorMcpDepsForTests = modules["cursor-mcp-config.js"]["setCursorMcpDepsForTests"]
15
17
  const upsertAgentiaCursorMcp = modules["cursor-mcp-config.js"]["upsertAgentiaCursorMcp"]
16
- export {AGENTIA_MCP_ENTRY, AGENTIA_MCP_SERVER_NAME, detectCursorInstall, findAgentiaMcpServer, getCursorMcpStatus, globalCursorMcpPath, hasConflictingAgentiaEntry, inspectCursorMcpStatus, isAgentiaMcpEntry, localCursorMcpPath, readCursorMcpDocument, resetCursorMcpDepsForTests, setCursorMcpDepsForTests, upsertAgentiaCursorMcp};
18
+ export {AGENTIA_MCP_ENTRY, AGENTIA_MCP_SERVER_NAME, detectCursorInstall, findAgentiaMcpServer, findCurrentAgentiaMcpServer, getCursorMcpStatus, globalCursorMcpPath, hasConflictingAgentiaEntry, inspectCursorMcpStatus, isAgentiaMcpEntry, isCurrentAgentiaMcpEntry, localCursorMcpPath, readCursorMcpDocument, resetCursorMcpDepsForTests, setCursorMcpDepsForTests, upsertAgentiaCursorMcp};
@@ -1,5 +1,6 @@
1
1
  import {modules} from './runtime.js';
2
2
  const DATA_TEMPLATES_BASE = modules["data-types.js"]["DATA_TEMPLATES_BASE"]
3
+ const DEFAULT_DATA_TEMPLATE_QUERY_LIMIT = modules["data-types.js"]["DEFAULT_DATA_TEMPLATE_QUERY_LIMIT"]
3
4
  const advancedFilterEndpoint = modules["data-types.js"]["advancedFilterEndpoint"]
4
5
  const advancedFiltersEndpoint = modules["data-types.js"]["advancedFiltersEndpoint"]
5
6
  const dataTemplateConvertOldEndpoint = modules["data-types.js"]["dataTemplateConvertOldEndpoint"]
@@ -21,10 +22,11 @@ const formatDatasetFileTable = modules["data-types.js"]["formatDatasetFileTable"
21
22
  const formatRecordMatchingFormulaTable = modules["data-types.js"]["formatRecordMatchingFormulaTable"]
22
23
  const formatSyncResultTable = modules["data-types.js"]["formatSyncResultTable"]
23
24
  const formatUserStoryDataCommitTable = modules["data-types.js"]["formatUserStoryDataCommitTable"]
25
+ const normalizeDataTemplateSavePayload = modules["data-types.js"]["normalizeDataTemplateSavePayload"]
24
26
  const normalizeDataTemplates = modules["data-types.js"]["normalizeDataTemplates"]
25
27
  const recordMatchingFormulaEndpoint = modules["data-types.js"]["recordMatchingFormulaEndpoint"]
26
28
  const recordMatchingFormulasByObjectEndpoint = modules["data-types.js"]["recordMatchingFormulasByObjectEndpoint"]
27
29
  const sobjectFieldsEndpoint = modules["data-types.js"]["sobjectFieldsEndpoint"]
28
30
  const sobjectRelationshipsEndpoint = modules["data-types.js"]["sobjectRelationshipsEndpoint"]
29
31
  const userStoryDataCommitsEndpoint = modules["data-types.js"]["userStoryDataCommitsEndpoint"]
30
- export {DATA_TEMPLATES_BASE, advancedFilterEndpoint, advancedFiltersEndpoint, dataTemplateConvertOldEndpoint, dataTemplateDetailEndpoint, dataTemplateEndpoint, dataTemplateRecordMatchingFormulasEndpoint, dataTemplateUpdatesEndpoint, dataTemplatesCommitEndpoint, dataTemplatesListEndpoint, dataTemplatesRecordsEndpoint, dataTemplatesRecordsMatchEndpoint, dataTemplatesSyncEndpoint, datasetFileContentEndpoint, datasetFilesEndpoint, formatAdvancedFilterTable, formatDataRecordTable, formatDataTemplateTable, formatDatasetFileTable, formatRecordMatchingFormulaTable, formatSyncResultTable, formatUserStoryDataCommitTable, normalizeDataTemplates, recordMatchingFormulaEndpoint, recordMatchingFormulasByObjectEndpoint, sobjectFieldsEndpoint, sobjectRelationshipsEndpoint, userStoryDataCommitsEndpoint};
32
+ export {DATA_TEMPLATES_BASE, DEFAULT_DATA_TEMPLATE_QUERY_LIMIT, advancedFilterEndpoint, advancedFiltersEndpoint, dataTemplateConvertOldEndpoint, dataTemplateDetailEndpoint, dataTemplateEndpoint, dataTemplateRecordMatchingFormulasEndpoint, dataTemplateUpdatesEndpoint, dataTemplatesCommitEndpoint, dataTemplatesListEndpoint, dataTemplatesRecordsEndpoint, dataTemplatesRecordsMatchEndpoint, dataTemplatesSyncEndpoint, datasetFileContentEndpoint, datasetFilesEndpoint, formatAdvancedFilterTable, formatDataRecordTable, formatDataTemplateTable, formatDatasetFileTable, formatRecordMatchingFormulaTable, formatSyncResultTable, formatUserStoryDataCommitTable, normalizeDataTemplateSavePayload, normalizeDataTemplates, recordMatchingFormulaEndpoint, recordMatchingFormulasByObjectEndpoint, sobjectFieldsEndpoint, sobjectRelationshipsEndpoint, userStoryDataCommitsEndpoint};
@@ -13,6 +13,7 @@ const createAndCheckoutBranch = modules["git-worktree.js"]["createAndCheckoutBra
13
13
  const fetchAndCheckoutBranch = modules["git-worktree.js"]["fetchAndCheckoutBranch"]
14
14
  const fetchOriginBranch = modules["git-worktree.js"]["fetchOriginBranch"]
15
15
  const fetchOriginBranchIfExists = modules["git-worktree.js"]["fetchOriginBranchIfExists"]
16
+ const formatGitExecError = modules["git-worktree.js"]["formatGitExecError"]
16
17
  const getCommitsNameStatus = modules["git-worktree.js"]["getCommitsNameStatus"]
17
18
  const getCurrentBranch = modules["git-worktree.js"]["getCurrentBranch"]
18
19
  const getFileAtRef = modules["git-worktree.js"]["getFileAtRef"]
@@ -48,4 +49,4 @@ const restoreFeatureBranch = modules["git-worktree.js"]["restoreFeatureBranch"]
48
49
  const restoreHeadPaths = modules["git-worktree.js"]["restoreHeadPaths"]
49
50
  const setGitExecForTests = modules["git-worktree.js"]["setGitExecForTests"]
50
51
  const stageAndCommit = modules["git-worktree.js"]["stageAndCommit"]
51
- export {NAME_STATUS_PRETTY_FORMAT, abortMerge, checkoutBranch, checkoutFeatureBranch, checkoutPreferredBranch, commitAllTrackedChanges, commitAllowEmpty, commitCurrentMerge, commitStagedChanges, countCommitsSince, createAndCheckoutBranch, fetchAndCheckoutBranch, fetchOriginBranch, fetchOriginBranchIfExists, getCommitsNameStatus, getCurrentBranch, getFileAtRef, getGitRepoRoot, getHeadCommitId, getHumanGitStatus, getMergeBase, getRemoteUrl, hasUnpushedCommits, isAncestor, isInsideGitWorkTree, isMergeInProgress, isSafeGitBranchName, listDiffNamesVsHead, listPendingChanges, listStagedChanges, listUnmergedFiles, localBranchExists, mergeFfOnly, mergeNoFf, mergeNoFfNoCommit, mergeTheirsIgnoreSpaceChange, originBranchRef, originFetchRefspec, parseNameOnly, parsePorcelainPaths, pullOriginBranch, pushOriginBranch, pushOriginBranches, resetGitExecForTests, resetHardHead, restoreFeatureBranch, restoreHeadPaths, setGitExecForTests, stageAndCommit};
52
+ export {NAME_STATUS_PRETTY_FORMAT, abortMerge, checkoutBranch, checkoutFeatureBranch, checkoutPreferredBranch, commitAllTrackedChanges, commitAllowEmpty, commitCurrentMerge, commitStagedChanges, countCommitsSince, createAndCheckoutBranch, fetchAndCheckoutBranch, fetchOriginBranch, fetchOriginBranchIfExists, formatGitExecError, getCommitsNameStatus, getCurrentBranch, getFileAtRef, getGitRepoRoot, getHeadCommitId, getHumanGitStatus, getMergeBase, getRemoteUrl, hasUnpushedCommits, isAncestor, isInsideGitWorkTree, isMergeInProgress, isSafeGitBranchName, listDiffNamesVsHead, listPendingChanges, listStagedChanges, listUnmergedFiles, localBranchExists, mergeFfOnly, mergeNoFf, mergeNoFfNoCommit, mergeTheirsIgnoreSpaceChange, originBranchRef, originFetchRefspec, parseNameOnly, parsePorcelainPaths, pullOriginBranch, pushOriginBranch, pushOriginBranches, resetGitExecForTests, resetHardHead, restoreFeatureBranch, restoreHeadPaths, setGitExecForTests, stageAndCommit};
@@ -1,13 +1,16 @@
1
1
  import {modules} from './runtime.js';
2
+ const AGENTIA_APEX_RERUN_FAILED_ENV = modules["local-quality-gates.js"]["AGENTIA_APEX_RERUN_FAILED_ENV"]
3
+ const AGENTIA_APEX_RERUN_FAILED_FLAG = modules["local-quality-gates.js"]["AGENTIA_APEX_RERUN_FAILED_FLAG"]
2
4
  const AGENTIA_APEX_TEST_CLASSES_ENV = modules["local-quality-gates.js"]["AGENTIA_APEX_TEST_CLASSES_ENV"]
3
5
  const LocalQualityGatesError = modules["local-quality-gates.js"]["LocalQualityGatesError"]
4
6
  const QUALITY_GATES_SCRIPT_UNIX = modules["local-quality-gates.js"]["QUALITY_GATES_SCRIPT_UNIX"]
5
7
  const QUALITY_GATES_SCRIPT_WINDOWS = modules["local-quality-gates.js"]["QUALITY_GATES_SCRIPT_WINDOWS"]
6
8
  const buildQualityGatesCommand = modules["local-quality-gates.js"]["buildQualityGatesCommand"]
9
+ const parseQualityGatesEnvAssignments = modules["local-quality-gates.js"]["parseQualityGatesEnvAssignments"]
7
10
  const qualityGatesScriptName = modules["local-quality-gates.js"]["qualityGatesScriptName"]
8
11
  const resetLocalQualityGatesForTests = modules["local-quality-gates.js"]["resetLocalQualityGatesForTests"]
9
12
  const resolveLocalQualityGatesScript = modules["local-quality-gates.js"]["resolveLocalQualityGatesScript"]
10
13
  const runLocalQualityGates = modules["local-quality-gates.js"]["runLocalQualityGates"]
11
14
  const setLocalQualityGatesExistsSyncForTests = modules["local-quality-gates.js"]["setLocalQualityGatesExistsSyncForTests"]
12
15
  const setLocalQualityGatesSpawnForTests = modules["local-quality-gates.js"]["setLocalQualityGatesSpawnForTests"]
13
- export {AGENTIA_APEX_TEST_CLASSES_ENV, LocalQualityGatesError, QUALITY_GATES_SCRIPT_UNIX, QUALITY_GATES_SCRIPT_WINDOWS, buildQualityGatesCommand, qualityGatesScriptName, resetLocalQualityGatesForTests, resolveLocalQualityGatesScript, runLocalQualityGates, setLocalQualityGatesExistsSyncForTests, setLocalQualityGatesSpawnForTests};
16
+ export {AGENTIA_APEX_RERUN_FAILED_ENV, AGENTIA_APEX_RERUN_FAILED_FLAG, AGENTIA_APEX_TEST_CLASSES_ENV, LocalQualityGatesError, QUALITY_GATES_SCRIPT_UNIX, QUALITY_GATES_SCRIPT_WINDOWS, buildQualityGatesCommand, parseQualityGatesEnvAssignments, qualityGatesScriptName, resetLocalQualityGatesForTests, resolveLocalQualityGatesScript, runLocalQualityGates, setLocalQualityGatesExistsSyncForTests, setLocalQualityGatesSpawnForTests};
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { assertRequired } from '../assert.js';
3
3
  import { CicdGateway } from '../cicd-gateway.js';
4
- import { advancedFilterEndpoint, advancedFiltersEndpoint, DATA_TEMPLATES_BASE, datasetFileContentEndpoint, datasetFilesEndpoint, dataTemplateConvertOldEndpoint, dataTemplateDetailEndpoint, dataTemplateEndpoint, dataTemplateRecordMatchingFormulasEndpoint, dataTemplatesCommitEndpoint, dataTemplatesListEndpoint, dataTemplatesRecordsEndpoint, dataTemplatesRecordsMatchEndpoint, dataTemplatesSyncEndpoint, dataTemplateUpdatesEndpoint, normalizeDataTemplates, recordMatchingFormulaEndpoint, recordMatchingFormulasByObjectEndpoint, sobjectFieldsEndpoint, sobjectRelationshipsEndpoint, userStoryDataCommitsEndpoint, } from '../data-types.js';
4
+ import { advancedFilterEndpoint, advancedFiltersEndpoint, DATA_TEMPLATES_BASE, datasetFileContentEndpoint, datasetFilesEndpoint, dataTemplateConvertOldEndpoint, dataTemplateDetailEndpoint, dataTemplateEndpoint, dataTemplateRecordMatchingFormulasEndpoint, dataTemplatesCommitEndpoint, dataTemplatesListEndpoint, dataTemplatesRecordsEndpoint, dataTemplatesRecordsMatchEndpoint, dataTemplatesSyncEndpoint, dataTemplateUpdatesEndpoint, normalizeDataTemplateSavePayload, normalizeDataTemplates, recordMatchingFormulaEndpoint, recordMatchingFormulasByObjectEndpoint, sobjectFieldsEndpoint, sobjectRelationshipsEndpoint, userStoryDataCommitsEndpoint, } from '../data-types.js';
5
5
  import { safelyHandleTool } from './result.js';
6
6
  async function dataTemplateList(args = {}) {
7
7
  const response = await CicdGateway.call({
@@ -55,7 +55,7 @@ async function dataTemplateSaveDetail(args) {
55
55
  throw new Error('Requires `body`.');
56
56
  }
57
57
  const result = await CicdGateway.call({
58
- body: args.body,
58
+ body: normalizeDataTemplateSavePayload(args.body),
59
59
  endpoint: dataTemplateDetailEndpoint(id),
60
60
  headers: { 'Content-Type': 'application/json' },
61
61
  method: 'PUT',
@@ -3,19 +3,19 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
3
3
  import { createRequire } from 'node:module';
4
4
  import process from 'node:process';
5
5
  import { migrateUserSettingsFromProjectConfig } from '../defaults-store.js';
6
- import { applyProjectRoot } from '../project-root.js';
6
+ import { applyProjectRoot, hasExplicitProjectRoot } from '../project-root.js';
7
7
  import { runWithMcpRequestSignal } from './request-context.js';
8
8
  import { runWithMcpToolContext } from './result.js';
9
9
  import { withToolAnnotations } from './tool-annotations.js';
10
10
  import { registerAgentiaMcpTools } from './tools.js';
11
11
  const require = createRequire(import.meta.url);
12
12
  const packageJson = require('../../../package.json');
13
- export function createAgentiaMcpServer(lifecycleSignal) {
13
+ export function createAgentiaMcpServer(lifecycleSignal, projectContextReady = Promise.resolve()) {
14
14
  const server = new McpServer({
15
15
  name: packageJson.name ?? 'agentia-cli',
16
16
  version: packageJson.version,
17
17
  });
18
- wrapMcpToolRegistration(server, lifecycleSignal);
18
+ wrapMcpToolRegistration(server, lifecycleSignal, projectContextReady);
19
19
  registerAgentiaMcpTools(server);
20
20
  return server;
21
21
  }
@@ -42,13 +42,14 @@ function combineSignals(requestSignal, lifecycleSignal) {
42
42
  signal: controller.signal,
43
43
  };
44
44
  }
45
- function wrapMcpToolRegistration(server, lifecycleSignal) {
45
+ function wrapMcpToolRegistration(server, lifecycleSignal, projectContextReady = Promise.resolve()) {
46
46
  const registerTool = server.registerTool.bind(server);
47
47
  server.registerTool = ((name, config, handler) => registerTool(name, withToolAnnotations(name, config), (...args) => {
48
48
  const extra = args.at(-1);
49
49
  const { dispose, signal } = combineSignals(extra?.signal, lifecycleSignal);
50
50
  return runWithMcpRequestSignal(signal, async () => {
51
51
  try {
52
+ await projectContextReady;
52
53
  return await runWithMcpToolContext(name, async () => handler(...args));
53
54
  }
54
55
  finally {
@@ -57,13 +58,38 @@ function wrapMcpToolRegistration(server, lifecycleSignal) {
57
58
  });
58
59
  }));
59
60
  }
60
- export async function startAgentiaMcpServer(transport = new StdioServerTransport()) {
61
- applyProjectRoot();
61
+ function clientSupportsRoots(server) {
62
+ return (server.server._clientCapabilities?.roots !== undefined);
63
+ }
64
+ async function applyMcpProjectRoot(server, includeMcpRoots) {
65
+ const rootUris = includeMcpRoots ? (await server.server.listRoots()).roots.map((root) => root.uri) : undefined;
66
+ applyProjectRoot(undefined, rootUris);
62
67
  await migrateUserSettingsFromProjectConfig().catch(() => {
63
68
  // Best-effort; MCP tools still fall back to reading legacy project keys.
64
69
  });
70
+ }
71
+ export async function startAgentiaMcpServer(transport = new StdioServerTransport()) {
65
72
  const lifecycle = new AbortController();
66
- const server = createAgentiaMcpServer(lifecycle.signal);
73
+ let resolveProjectContext;
74
+ let rejectProjectContext;
75
+ const projectContextReady = new Promise((resolve, reject) => {
76
+ resolveProjectContext = resolve;
77
+ rejectProjectContext = reject;
78
+ });
79
+ projectContextReady.catch((error) => {
80
+ const message = error instanceof Error ? error.message : String(error);
81
+ process.stderr.write(`[agentia-mcp] project context error: ${message}\n`);
82
+ });
83
+ const server = createAgentiaMcpServer(lifecycle.signal, projectContextReady);
84
+ if (hasExplicitProjectRoot()) {
85
+ await applyMcpProjectRoot(server, false);
86
+ resolveProjectContext();
87
+ }
88
+ else {
89
+ server.server.oninitialized = () => {
90
+ applyMcpProjectRoot(server, clientSupportsRoots(server)).then(resolveProjectContext, rejectProjectContext);
91
+ };
92
+ }
67
93
  let closing = false;
68
94
  const close = async () => {
69
95
  if (closing)
@@ -128,6 +128,7 @@ const READ_TOOLS = [
128
128
  'agentia_function_list',
129
129
  'agentia_function_result_get',
130
130
  'agentia_function_result_log_get',
131
+ 'agentia_health_check',
131
132
  'agentia_job_get',
132
133
  'agentia_job_list',
133
134
  'agentia_job_log_get',
@@ -212,6 +213,8 @@ const UPDATE_TOOLS = [
212
213
  'agentia_promotion_conflict_unresolve',
213
214
  'agentia_promotion_job_step_update',
214
215
  'agentia_repository_update',
216
+ 'agentia_repository_auth_https',
217
+ 'agentia_repository_auth_ssh',
215
218
  'agentia_stage_update',
216
219
  'agentia_testing_data_table_update',
217
220
  'agentia_testing_job_schedule_set',
@@ -37,7 +37,7 @@ import { buildPromotionManualTaskUpdatePayload, PROMOTION_MANUAL_TASK_STATUSES,
37
37
  import { performPromotionResume, performPromotionRun, PROMOTION_OPERATIONS, PROMOTION_RUN_DEFAULT_TIMEOUT_SECONDS, } from '../promotion-run.js';
38
38
  import { normalizePromotionDetail, normalizePromotionsListPage, promotionEndpoint, promotionListEndpoint, } from '../promotion-types.js';
39
39
  import { REPOSITORY_STRING_VALIDATION_KEYS, validateNonEmptyStringFields as validateRepositoryNonEmptyStringFields, } from '../repository-flags.js';
40
- import { normalizeRepositoriesListPage, normalizeRepository, normalizeRepositoryValidateResult, repositoriesEndpoint, REPOSITORY_AUTH_TYPES, REPOSITORY_PROVIDERS, REPOSITORY_SOURCE_FORMATS, repositoryEndpoint, repositoryResetEndpoint, repositoryValidateEndpoint, withRequiredRepositoryFields, } from '../repository-types.js';
40
+ import { normalizeRepositoriesListPage, normalizeRepository, normalizeRepositoryValidateResult, repositoriesEndpoint, REPOSITORY_PROVIDERS, REPOSITORY_SOURCE_FORMATS, repositoryEndpoint, repositoryHttpsAuthEndpoint, repositoryResetEndpoint, repositorySshAuthEndpoint, repositoryValidateEndpoint, } from '../repository-types.js';
41
41
  import { buildStageMutationPayload, validateStagePayload } from '../stage-flags.js';
42
42
  import { normalizePipelineStageConnection, normalizeStage, normalizeStagesListPage, pipelineStageConnectionEndpoint, pipelineStageConnectionsEndpoint, STAGE_META_STAGE_SUGGESTIONS, stageEndpoint, stagesEndpoint, } from '../stage-types.js';
43
43
  import { getUserContext } from '../user-context.js';
@@ -561,17 +561,12 @@ async function repositoryUpdate(args) {
561
561
  if (Object.keys(explicitPayload).length === 0) {
562
562
  throw new Error('Must provide at least one field to update.');
563
563
  }
564
- const currentResponse = await CicdGateway.call({
565
- endpoint: repositoryEndpoint(id),
566
- method: 'GET',
567
- });
568
- const payload = withRequiredRepositoryFields(explicitPayload, normalizeRepository(currentResponse));
569
- const validationError = validateRepositoryPayload(payload);
564
+ const validationError = validateRepositoryMutationPayload(explicitPayload);
570
565
  if (validationError !== undefined) {
571
566
  throw new Error(validationError);
572
567
  }
573
568
  const response = await CicdGateway.call({
574
- body: payload,
569
+ body: explicitPayload,
575
570
  endpoint: repositoryEndpoint(id),
576
571
  headers: {
577
572
  'Content-Type': 'application/json',
@@ -580,6 +575,26 @@ async function repositoryUpdate(args) {
580
575
  });
581
576
  return { repository: normalizeRepository(response) };
582
577
  }
578
+ async function repositoryAuthHttps(args) {
579
+ const { id, overwrite, ...payload } = args;
580
+ await CicdGateway.call({
581
+ body: payload,
582
+ endpoint: repositoryHttpsAuthEndpoint(assertRequired(id, 'id'), overwrite === true),
583
+ headers: { 'Content-Type': 'application/json' },
584
+ method: 'PUT',
585
+ });
586
+ return { id };
587
+ }
588
+ async function repositoryAuthSsh(args) {
589
+ const { id, overwrite, ...payload } = args;
590
+ const response = await CicdGateway.call({
591
+ body: payload,
592
+ endpoint: repositorySshAuthEndpoint(assertRequired(id, 'id'), overwrite === true),
593
+ headers: { 'Content-Type': 'application/json' },
594
+ method: 'POST',
595
+ });
596
+ return { id, publicKey: response.publicKey };
597
+ }
583
598
  async function repositoryDelete(args) {
584
599
  const id = assertRequired(args.id, 'id');
585
600
  await CicdGateway.call({
@@ -765,6 +780,9 @@ function validateRepositoryPayload(payload) {
765
780
  }
766
781
  return undefined;
767
782
  }
783
+ function validateRepositoryMutationPayload(payload) {
784
+ return validateRepositoryNonEmptyStringFields(payload, REPOSITORY_STRING_VALIDATION_KEYS);
785
+ }
768
786
  async function userGet(args = {}) {
769
787
  const user = await CicdGateway.call({
770
788
  endpoint: userEndpoint(resolveUserId(args.id)),
@@ -1334,18 +1352,14 @@ const pipelineConnectionMutationSchema = {
1334
1352
  };
1335
1353
  const repositoryMutationSchema = {
1336
1354
  allowFunctionsGitCache: z.boolean().optional().describe('Allow Functions Git cache for this repository.'),
1337
- authType: z.enum(REPOSITORY_AUTH_TYPES).optional().describe('Repository authentication type.'),
1338
1355
  branchBaseUrl: z.string().nullable().optional().describe('Base URL for repository branch links.'),
1339
1356
  commitBaseUrl: z.string().nullable().optional().describe('Base URL for repository commit links.'),
1340
- extraHeaders: z.string().nullable().optional().describe('Additional authentication headers.'),
1341
1357
  isCopadoTunnelEnabled: z.boolean().optional().describe('Enable Copado tunnel for this repository.'),
1342
- password: z.string().nullable().optional().describe('Repository password or token. Sensitive input.'),
1343
1358
  provider: z.enum(REPOSITORY_PROVIDERS).optional().describe('Git repository provider.'),
1344
1359
  pullRequestBaseUrl: z.string().nullable().optional().describe('Base URL for repository pull request links.'),
1345
1360
  sourceFormat: z.enum(REPOSITORY_SOURCE_FORMATS).optional().describe('Git repository source format.'),
1346
1361
  tagBaseUrl: z.string().nullable().optional().describe('Base URL for repository tag links.'),
1347
1362
  uri: z.string().nullable().optional().describe('Repository clone URI.'),
1348
- username: z.string().nullable().optional().describe('Repository username.'),
1349
1363
  };
1350
1364
  const promotionListSchema = {
1351
1365
  createdById: z.string().optional().describe('Filter by creator ID.'),
@@ -1955,6 +1969,35 @@ export function registerAgentiaMcpTools(server) {
1955
1969
  },
1956
1970
  title: 'Agentia Repository Update',
1957
1971
  }, (args) => safelyHandleTool(() => repositoryUpdate(args)));
1972
+ server.registerTool('agentia_repository_auth_https', {
1973
+ description: 'Configure HTTPS repository authentication. The password and optional headers are sensitive and are redacted from responses.',
1974
+ inputSchema: {
1975
+ branchBaseUrl: z.string(),
1976
+ commitBaseUrl: z.string(),
1977
+ extraHeaders: z.string().optional().describe('Sensitive optional authentication headers.'),
1978
+ id: z.string().describe('Copado Git repository ID.'),
1979
+ overwrite: z.boolean().optional().describe('Explicitly replace an existing validated credential.'),
1980
+ password: z.string().describe('Sensitive HTTPS password or personal access token.'),
1981
+ pullRequestBaseUrl: z.string(),
1982
+ tagBaseUrl: z.string(),
1983
+ uri: z.string(),
1984
+ username: z.string(),
1985
+ },
1986
+ title: 'Agentia Repository HTTPS Authentication',
1987
+ }, (args) => safelyHandleTool(() => repositoryAuthHttps(args)));
1988
+ server.registerTool('agentia_repository_auth_ssh', {
1989
+ description: 'Configure SSH repository authentication and return the generated public key.',
1990
+ inputSchema: {
1991
+ branchBaseUrl: z.string(),
1992
+ commitBaseUrl: z.string(),
1993
+ id: z.string().describe('Copado Git repository ID.'),
1994
+ overwrite: z.boolean().optional().describe('Explicitly replace an existing SSH key.'),
1995
+ pullRequestBaseUrl: z.string(),
1996
+ tagBaseUrl: z.string(),
1997
+ uri: z.string(),
1998
+ },
1999
+ title: 'Agentia Repository SSH Authentication',
2000
+ }, (args) => safelyHandleTool(() => repositoryAuthSsh(args)));
1958
2001
  server.registerTool('agentia_repository_delete', {
1959
2002
  description: 'Delete a Copado Git repository by ID via the CICD gateway.',
1960
2003
  inputSchema: { id: z.string().describe('Copado Git repository ID.') },
@@ -6,17 +6,19 @@ import { reconcileWorkSetCredential, sanitizeWorkSetUserStory } from '../credent
6
6
  import { readDefaults, resolveDefaults, writeLastWorkSelection, } from '../defaults-store.js';
7
7
  import { checkoutFeatureBranch, fetchOriginBranch, fetchOriginBranchIfExists, listPendingChanges, } from '../git-worktree.js';
8
8
  import { listPaginationZodFields, mcpPaginatedListPayload } from '../list-pagination.js';
9
- import { LocalQualityGatesError, runLocalQualityGates } from '../local-quality-gates.js';
9
+ import { LocalQualityGatesError, parseQualityGatesEnvAssignments, runLocalQualityGates, } from '../local-quality-gates.js';
10
10
  import { FULL_METADATA_SELECTION_TYPES_HELP } from '../nested-metadata-registry.js';
11
11
  import { PROJECT_DEFAULT_KEYS } from '../project-defaults.js';
12
12
  import { performPromotionRun, PROMOTION_RUN_DEFAULT_TIMEOUT_SECONDS, resolvePromotionIdForWorkItem, } from '../promotion-run.js';
13
13
  import { runWorkTestLocalQualityGates } from '../stock-quality-gates.js';
14
14
  import { getUserContext } from '../user-context.js';
15
15
  import { resolveWorkItemId } from '../work-active.js';
16
- import { DEFAULT_APEX_TEST_WAIT_MINUTES, parseApexTestClassNames, runWorkApexTests, validateApexTestWaitMinutes, } from '../work-apex-test.js';
16
+ import { planWorkApexTestRun, recordWorkApexTestOutcome } from '../work-apex-test-failures.js';
17
+ import { DEFAULT_APEX_TEST_WAIT_MINUTES, parseApexTestClassNames, runWorkApexTests, skippedWorkApexTestResult, validateApexTestWaitMinutes, WorkApexTestError, } from '../work-apex-test.js';
17
18
  import { buildWorkCommitRequest, normalizeWorkCommitInput, performWorkCommit, resolveWorkCommitPlatformExperience, WORK_COMMIT_ACTIONS, WORK_COMMIT_CHANGES_HELP, WORK_COMMIT_DEFAULT_TIMEOUT_SECONDS, WORK_COMMIT_METADATA_CATEGORY_HELP, } from '../work-commit.js';
18
19
  import { buildWorkCreatePayload } from '../work-defaults.js';
19
20
  import { validateWorkMutationPayload, WORK_LONG_TEXT_MAX_LENGTH, WORK_SHORT_TEXT_MAX_LENGTH, } from '../work-flags.js';
21
+ import { fetchUserStory } from '../work-get.js';
20
22
  import { performWorkLocalCommit } from '../work-local-commit.js';
21
23
  import { reportLocalQualityGatesFailure, reportLocalQualityGatesOutcome, } from '../work-local-run-tests.js';
22
24
  import { capturingWorkPushHooks, performWorkPush, resolveActiveFeatureWorkItem, resolveWorkPushContext, resolveWorkPushNeed, } from '../work-push.js';
@@ -128,11 +130,7 @@ async function workList(args = {}) {
128
130
  return mcpPaginatedListPayload('userStories', normalizeUserStoriesListPage(response));
129
131
  }
130
132
  async function workGet(args = {}) {
131
- const workItemId = await resolveWorkItemId(args.id);
132
- const userStory = await CicdGateway.call({
133
- endpoint: workEndpoint(workItemId),
134
- method: 'GET',
135
- });
133
+ const userStory = await fetchUserStory(args.id);
136
134
  return { userStory };
137
135
  }
138
136
  async function workCreate(args = {}) {
@@ -382,13 +380,16 @@ async function workTest(args = {}) {
382
380
  if (args.cloud === true) {
383
381
  throw new Error('Cloud quality gates are not implemented yet. Pass local: true or omit cloud to run project-root quality gates.');
384
382
  }
383
+ parseQualityGatesEnvAssignments(args.env);
385
384
  let qualityGates;
386
385
  try {
387
386
  qualityGates = await runWorkTestLocalQualityGates({
388
387
  apexTestClasses: args.apexTestClasses,
388
+ env: args.env,
389
389
  onOutput() {
390
390
  // Capture output for the tool result/error; do not stream to the MCP stdio transport.
391
391
  },
392
+ rerunFailed: args.rerunFailedApexTests === true,
392
393
  });
393
394
  }
394
395
  catch (error) {
@@ -420,9 +421,26 @@ async function workTest(args = {}) {
420
421
  };
421
422
  }
422
423
  async function workTestApex(args) {
423
- const classNames = parseApexTestClassNames(assertRequired(args.apexTestClasses, 'apexTestClasses'));
424
+ const classNames = parseApexTestClassNames(args.apexTestClasses);
424
425
  const waitMinutes = validateApexTestWaitMinutes(args.wait ?? DEFAULT_APEX_TEST_WAIT_MINUTES);
425
- return runWorkApexTests({ classNames, waitMinutes });
426
+ const plan = await planWorkApexTestRun({
427
+ requestedClassNames: classNames,
428
+ rerunFailed: args.rerunFailedApexTests === true,
429
+ });
430
+ if (plan.kind === 'skip') {
431
+ return skippedWorkApexTestResult(waitMinutes);
432
+ }
433
+ try {
434
+ const result = await runWorkApexTests({ classNames: plan.classNames, waitMinutes });
435
+ await recordWorkApexTestOutcome({ failed: false, result, userStory: plan.userStory });
436
+ return result;
437
+ }
438
+ catch (error) {
439
+ if (error instanceof WorkApexTestError) {
440
+ await recordWorkApexTestOutcome({ failed: true, result: error.result, userStory: plan.userStory });
441
+ }
442
+ throw error;
443
+ }
426
444
  }
427
445
  function hasMcpSimpleCommitArgs(args) {
428
446
  return (args.action !== undefined ||
@@ -770,7 +788,7 @@ export function registerAgentiaMcpWorkTools(server) {
770
788
  title: 'Agentia Cloud Promote',
771
789
  }, (args) => safelyHandleTool(() => cloudPromote(args || {})));
772
790
  server.registerTool('agentia_work_submit', {
773
- description: 'Submit the current feature/US-XXXX work item for pipeline quality gates and validation. Runs project-root .agentia_quality_gates.sh (macOS/Linux) or .agentia_quality_gates.cmd (Windows) when present, then fetches origin/<lastBaseBranch> and counts origin/<lastBaseBranch>..HEAD before checking origin. Pushes and registers commits when that feature-only range is non-empty and the branch is ahead of origin. When the last pending related job template name contains Commit, waits up to 5 minutes for that job before calling headless work/submit. 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. With done=true or deploy=true, matches Copado UI Submit when promoting (headless work/done) and uses the same commit wait. Prefer this over agentia_work_done.',
791
+ description: 'Submit the current feature/US-XXXX work item for pipeline quality gates and validation. Runs project-root .agentia_quality_gates.sh (macOS/Linux) or .agentia_quality_gates.cmd (Windows) when present, then fetches origin/<lastBaseBranch> and counts origin/<lastBaseBranch>..HEAD before checking origin. Pushes and registers commits when that feature-only range is non-empty and the branch is ahead of origin. When the last pending related job template name contains Commit, waits up to 5 minutes for that job before calling headless work/submit. 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). With done=true or deploy=true, matches Copado UI Submit when promoting (headless work/done) and uses the same commit wait. Prefer this over agentia_work_done.',
774
792
  inputSchema: {
775
793
  apexTestClasses: z
776
794
  .string()
@@ -793,7 +811,7 @@ export function registerAgentiaMcpWorkTools(server) {
793
811
  title: 'Agentia Work Submit',
794
812
  }, (args) => safelyHandleTool(() => workSubmit(args || {})));
795
813
  server.registerTool('agentia_work_test', {
796
- description: 'Run quality gates for the current work item. With local=true (the default when cloud is omitted), runs project-root .agentia_quality_gates.sh (macOS/Linux) or .agentia_quality_gates.cmd (Windows) when present. When no project script exists, warns and runs the stock Agentia setup sample from a temporary file. With cloud=true, runs remote Copado quality gates (not implemented yet).',
814
+ description: 'Run quality gates for the current work item. With local=true (the default when cloud is omitted), runs project-root .agentia_quality_gates.sh (macOS/Linux) or .agentia_quality_gates.cmd (Windows) when present. When no project script exists, warns and runs the stock Agentia setup sample from a temporary file. With cloud=true, runs remote Copado quality gates (not implemented yet). Optional env is an array of NAME=value strings injected into the quality-gate script environment (same as CLI -e/--env).',
797
815
  inputSchema: {
798
816
  apexTestClasses: z
799
817
  .string()
@@ -803,19 +821,32 @@ export function registerAgentiaMcpWorkTools(server) {
803
821
  .boolean()
804
822
  .optional()
805
823
  .describe('Run remote Copado quality gates (not implemented yet).'),
824
+ env: z
825
+ .array(z.string())
826
+ .optional()
827
+ .describe('Extra environment variables for the quality-gate script as NAME=value strings (same as CLI -e/--env). Applied before reserved AGENTIA_APEX_* variables.'),
806
828
  local: z
807
829
  .boolean()
808
830
  .optional()
809
831
  .describe('Run local project-root quality gates scripts. Used by default when cloud is omitted.'),
832
+ rerunFailedApexTests: z
833
+ .boolean()
834
+ .optional()
835
+ .describe('Pass AGENTIA_APEX_RERUN_FAILED=--rerun-failed-apex-tests to local quality gates so sample scripts forward that flag to work test apex.'),
810
836
  },
811
837
  title: 'Agentia Work Test',
812
838
  }, (args) => safelyHandleTool(() => workTest(args || {})));
813
839
  server.registerTool('agentia_work_test_apex', {
814
- description: 'Run specified Apex test classes via Salesforce CLI (`sf apex run test`) with code coverage. Usually run from project-root local quality gates (`.agentia_quality_gates.sh` / `.agentia_quality_gates.cmd`) when those scripts are configured. Returns the test-run summary when the run passes. Failed runs include failing tests with Message and StackTrace.',
840
+ description: 'Run specified Apex test classes via Salesforce CLI (`sf apex run test`) with code coverage. Usually run from project-root local quality gates (`.agentia_quality_gates.sh` / `.agentia_quality_gates.cmd`) when those scripts are configured. When apexTestClasses is omitted or empty, skips Salesforce CLI and returns skipped=true. Failed runs save `.agentia/apex.tests.<user-story>.json`; successful runs delete that file. rerunFailedApexTests runs the previously failed classes. Returns the test-run summary when the run passes. Failed runs include failing tests with Message and StackTrace.',
815
841
  inputSchema: {
816
842
  apexTestClasses: z
817
843
  .string()
818
- .describe('Comma-separated Apex test class names to run.'),
844
+ .optional()
845
+ .describe('Comma-separated Apex test class names to run. Omit or leave empty to skip without running Salesforce CLI.'),
846
+ rerunFailedApexTests: z
847
+ .boolean()
848
+ .optional()
849
+ .describe('Rerun Apex classes saved from the last failure for this user story. Combined with apexTestClasses, only matching failed classes run.'),
819
850
  wait: z
820
851
  .number()
821
852
  .int()
@@ -0,0 +1,4 @@
1
+ import {modules} from '../runtime.js';
2
+ const createAuthApi = modules["plugin-host/auth.js"]["createAuthApi"]
3
+ const projectAuthStatus = modules["plugin-host/auth.js"]["projectAuthStatus"]
4
+ export {createAuthApi, projectAuthStatus};
@@ -0,0 +1,3 @@
1
+ import {modules} from '../runtime.js';
2
+ const schedulePluginHostEvent = modules["plugin-host/event-log.js"]["schedulePluginHostEvent"]
3
+ export {schedulePluginHostEvent};
@@ -0,0 +1,3 @@
1
+ import {modules} from '../runtime.js';
2
+ const createFormatApi = modules["plugin-host/format.js"]["createFormatApi"]
3
+ export {createFormatApi};
@@ -0,0 +1,7 @@
1
+ import {modules} from '../runtime.js';
2
+ const AGENTIA_PLUGIN_HOST_API_VERSION = modules["plugin-host/index.js"]["AGENTIA_PLUGIN_HOST_API_VERSION"]
3
+ const AGENTIA_PLUGIN_HOST_KEY = modules["plugin-host/index.js"]["AGENTIA_PLUGIN_HOST_KEY"]
4
+ const createPluginHost = modules["plugin-host/index.js"]["createPluginHost"]
5
+ const getRegisteredPluginHost = modules["plugin-host/index.js"]["getRegisteredPluginHost"]
6
+ const registerPluginHost = modules["plugin-host/index.js"]["registerPluginHost"]
7
+ export {AGENTIA_PLUGIN_HOST_API_VERSION, AGENTIA_PLUGIN_HOST_KEY, createPluginHost, getRegisteredPluginHost, registerPluginHost};
@@ -0,0 +1,4 @@
1
+ import {modules} from '../runtime.js';
2
+ const createOrganizationApi = modules["plugin-host/organization.js"]["createOrganizationApi"]
3
+ const projectHealthReport = modules["plugin-host/organization.js"]["projectHealthReport"]
4
+ export {createOrganizationApi, projectHealthReport};
@@ -0,0 +1,6 @@
1
+ import {modules} from '../runtime.js';
2
+ const deepFreeze = modules["plugin-host/projection-utils.js"]["deepFreeze"]
3
+ const nonNegativeInt = modules["plugin-host/projection-utils.js"]["nonNegativeInt"]
4
+ const omitUndefined = modules["plugin-host/projection-utils.js"]["omitUndefined"]
5
+ const optionalText = modules["plugin-host/projection-utils.js"]["optionalText"]
6
+ export {deepFreeze, nonNegativeInt, omitUndefined, optionalText};
@@ -0,0 +1,6 @@
1
+ import {modules} from '../runtime.js';
2
+ const AGENTIA_PLUGIN_HOST_API_VERSION = modules["plugin-host/registry.js"]["AGENTIA_PLUGIN_HOST_API_VERSION"]
3
+ const AGENTIA_PLUGIN_HOST_KEY = modules["plugin-host/registry.js"]["AGENTIA_PLUGIN_HOST_KEY"]
4
+ const getRegisteredPluginHost = modules["plugin-host/registry.js"]["getRegisteredPluginHost"]
5
+ const registerPluginHost = modules["plugin-host/registry.js"]["registerPluginHost"]
6
+ export {AGENTIA_PLUGIN_HOST_API_VERSION, AGENTIA_PLUGIN_HOST_KEY, getRegisteredPluginHost, registerPluginHost};
@@ -0,0 +1,4 @@
1
+ import {modules} from '../runtime.js';
2
+ const guard = modules["plugin-host/request-scope.js"]["guard"]
3
+ const runWithTransaction = modules["plugin-host/request-scope.js"]["runWithTransaction"]
4
+ export {guard, runWithTransaction};
@@ -0,0 +1,4 @@
1
+ import {modules} from '../runtime.js';
2
+ const createWorkApi = modules["plugin-host/work.js"]["createWorkApi"]
3
+ const projectWorkItem = modules["plugin-host/work.js"]["projectWorkItem"]
4
+ export {createWorkApi, projectWorkItem};
@@ -1,7 +1,9 @@
1
1
  import {modules} from './runtime.js';
2
2
  const AGENTIA_PROJECT_ROOT_ENV = modules["project-root.js"]["AGENTIA_PROJECT_ROOT_ENV"]
3
+ const CLAUDE_PROJECT_DIR_ENV = modules["project-root.js"]["CLAUDE_PROJECT_DIR_ENV"]
3
4
  const applyProjectRoot = modules["project-root.js"]["applyProjectRoot"]
5
+ const hasExplicitProjectRoot = modules["project-root.js"]["hasExplicitProjectRoot"]
4
6
  const resetProjectRootDepsForTests = modules["project-root.js"]["resetProjectRootDepsForTests"]
5
7
  const resolveProjectRoot = modules["project-root.js"]["resolveProjectRoot"]
6
8
  const setProjectRootDepsForTests = modules["project-root.js"]["setProjectRootDepsForTests"]
7
- export {AGENTIA_PROJECT_ROOT_ENV, applyProjectRoot, resetProjectRootDepsForTests, resolveProjectRoot, setProjectRootDepsForTests};
9
+ export {AGENTIA_PROJECT_ROOT_ENV, CLAUDE_PROJECT_DIR_ENV, applyProjectRoot, hasExplicitProjectRoot, resetProjectRootDepsForTests, resolveProjectRoot, setProjectRootDepsForTests};
@@ -0,0 +1,8 @@
1
+ import {modules} from './runtime.js';
2
+ const configureHttps = modules["repository-auth.js"]["configureHttps"]
3
+ const configureSsh = modules["repository-auth.js"]["configureSsh"]
4
+ const getRepository = modules["repository-auth.js"]["getRepository"]
5
+ const promptConnection = modules["repository-auth.js"]["promptConnection"]
6
+ const promptHttpsPayload = modules["repository-auth.js"]["promptHttpsPayload"]
7
+ const readHttpsAuthPayloadFromStdin = modules["repository-auth.js"]["readHttpsAuthPayloadFromStdin"]
8
+ export {configureHttps, configureSsh, getRepository, promptConnection, promptHttpsPayload, readHttpsAuthPayloadFromStdin};
@@ -6,11 +6,11 @@ const buildRepositoryMutationPayload = modules["repository-flags.js"]["buildRepo
6
6
  const collectRepositoryMutationFlagKeys = modules["repository-flags.js"]["collectRepositoryMutationFlagKeys"]
7
7
  const repositoryBooleanFlags = modules["repository-flags.js"]["repositoryBooleanFlags"]
8
8
  const repositoryClearFlags = modules["repository-flags.js"]["repositoryClearFlags"]
9
+ const repositoryConnectionStringFlags = modules["repository-flags.js"]["repositoryConnectionStringFlags"]
9
10
  const repositoryCreateFlags = modules["repository-flags.js"]["repositoryCreateFlags"]
10
11
  const repositoryListFlags = modules["repository-flags.js"]["repositoryListFlags"]
11
- const repositoryOptionalStringFlags = modules["repository-flags.js"]["repositoryOptionalStringFlags"]
12
12
  const repositoryRequiredMutationFlags = modules["repository-flags.js"]["repositoryRequiredMutationFlags"]
13
13
  const repositoryUpdateFlags = modules["repository-flags.js"]["repositoryUpdateFlags"]
14
14
  const validateNonEmptyStringFields = modules["repository-flags.js"]["validateNonEmptyStringFields"]
15
15
  const validateRepositoryMutationFlags = modules["repository-flags.js"]["validateRepositoryMutationFlags"]
16
- export {REPOSITORY_STRING_VALIDATION_KEYS, buildRepositoryCreatePayload, buildRepositoryListFilters, buildRepositoryMutationPayload, collectRepositoryMutationFlagKeys, repositoryBooleanFlags, repositoryClearFlags, repositoryCreateFlags, repositoryListFlags, repositoryOptionalStringFlags, repositoryRequiredMutationFlags, repositoryUpdateFlags, validateNonEmptyStringFields, validateRepositoryMutationFlags};
16
+ export {REPOSITORY_STRING_VALIDATION_KEYS, buildRepositoryCreatePayload, buildRepositoryListFilters, buildRepositoryMutationPayload, collectRepositoryMutationFlagKeys, repositoryBooleanFlags, repositoryClearFlags, repositoryConnectionStringFlags, repositoryCreateFlags, repositoryListFlags, repositoryRequiredMutationFlags, repositoryUpdateFlags, validateNonEmptyStringFields, validateRepositoryMutationFlags};