@aifabrix/builder 2.54.1 → 2.55.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/lib/agent-kit/apply-ops.js +82 -0
- package/lib/agent-kit/checksums.js +28 -0
- package/lib/agent-kit/classify.js +113 -0
- package/lib/agent-kit/claude-shim.js +61 -0
- package/lib/agent-kit/constants.js +55 -0
- package/lib/agent-kit/file-list.js +103 -0
- package/lib/agent-kit/host-approve.js +172 -0
- package/lib/agent-kit/hosting/github.js +63 -0
- package/lib/agent-kit/hosts.js +71 -0
- package/lib/agent-kit/init.js +319 -0
- package/lib/agent-kit/kit-root.js +17 -0
- package/lib/agent-kit/managed-section.js +79 -0
- package/lib/agent-kit/package-load.js +45 -0
- package/lib/agent-kit/plan-ops.js +69 -0
- package/lib/agent-kit/remote-prompts.js +272 -0
- package/lib/agent-kit/render-host-markdown.js +40 -0
- package/lib/agent-kit/repo-guard.js +47 -0
- package/lib/agent-kit/report.js +107 -0
- package/lib/agent-kit/run.js +82 -0
- package/lib/agent-kit/scm/git.js +122 -0
- package/lib/agent-kit/start.js +310 -0
- package/lib/agent-kit/state-file.js +83 -0
- package/lib/agent-kit/status.js +50 -0
- package/lib/agent-kit/v1-detect.js +81 -0
- package/lib/agent-kit/validate-kit.js +87 -0
- package/lib/agent-kit/workspace-name.js +40 -0
- package/lib/agent-kit/workspace-skeleton.js +103 -0
- package/lib/api/role-assistant-test-pack.api.js +86 -0
- package/lib/api/work-search.api.js +31 -4
- package/lib/api/work.api.js +19 -12
- package/lib/app/deploy.js +7 -4
- package/lib/app/list-external-systems.js +2 -1
- package/lib/app/offer-create-from-template.js +184 -0
- package/lib/app/show-display.js +33 -6
- package/lib/app/show.js +25 -2
- package/lib/channels/add-channel.js +1 -0
- package/lib/channels/approval-guides/claude.js +2 -2
- package/lib/channels/channel-add-failure.js +1 -0
- package/lib/channels/channel-add-remaining.js +15 -9
- package/lib/channels/channel-definition-status.js +115 -0
- package/lib/channels/channel-description.js +2 -1
- package/lib/channels/channel-install-envelope.js +4 -2
- package/lib/channels/channel-integration-generator.js +2 -0
- package/lib/channels/channel-runtime-resolver.js +14 -0
- package/lib/channels/channel-targets.js +31 -5
- package/lib/channels/claude-setup-values.js +4 -1
- package/lib/channels/slack-channel-add.js +59 -6
- package/lib/channels/slack-mcp-callback.js +51 -0
- package/lib/channels/slack-mcp-runtime.js +156 -0
- package/lib/channels/slack-provisioning/install-cli.js +14 -2
- package/lib/channels/slack-provisioning/with-curl-on-path.js +6 -1
- package/lib/cli/index.js +4 -0
- package/lib/cli/setup-app.js +8 -1
- package/lib/cli/setup-auth.js +11 -2
- package/lib/cli/setup-certification-commands.js +2 -2
- package/lib/cli/setup-certification.help.js +3 -1
- package/lib/commands/agent-kit-help.js +149 -0
- package/lib/commands/agent-kit.js +417 -0
- package/lib/commands/auth-status-user.js +99 -0
- package/lib/commands/auth-status.js +14 -4
- package/lib/commands/channel-add-help.js +5 -5
- package/lib/commands/datasource-capability-relate-cli.js +5 -4
- package/lib/commands/datasource-load-export-cli.js +7 -2
- package/lib/commands/datasource-test-trust-cli.js +5 -1
- package/lib/commands/governance-command-action.js +5 -4
- package/lib/commands/identity-membership-role-cache.js +6 -1
- package/lib/commands/lifecycle-command-action.js +16 -15
- package/lib/commands/login-credentials.js +8 -3
- package/lib/commands/login-device.js +14 -5
- package/lib/commands/login.js +14 -1
- package/lib/commands/logout.js +50 -15
- package/lib/commands/repair-auth-apply.js +1 -1
- package/lib/commands/repair-datasource-key-skip.js +39 -0
- package/lib/commands/repair-datasource-keys.js +24 -12
- package/lib/commands/repair-rbac.js +16 -10
- package/lib/commands/role-assistant-copy-output.js +61 -0
- package/lib/commands/role-assistant-copy.js +155 -0
- package/lib/commands/role-assistant-test-output.js +8 -9
- package/lib/commands/role-assistant-test-result-rows.js +42 -0
- package/lib/commands/role-assistant.js +140 -59
- package/lib/commands/search.js +143 -0
- package/lib/commands/test-trust-external.js +7 -5
- package/lib/commands/upload-sidecar-followups.js +4 -1
- package/lib/commands/verify-governance-command-action.js +9 -7
- package/lib/commands/verify-operations-command-action.js +9 -8
- package/lib/commands/verify-operations-skip-e2e.js +131 -0
- package/lib/commands/verify-operations-step-plan.js +6 -33
- package/lib/commands/verify-operations-steps.js +3 -1
- package/lib/commands/verify-trust-command-action.js +6 -5
- package/lib/datasource/capability/relate-operations.js +28 -10
- package/lib/datasource/capability/run-capability-relate.js +48 -25
- package/lib/datasource/datasource-identifier.js +13 -5
- package/lib/deployment/deployer-poll-run.js +117 -35
- package/lib/external-system/deploy-dataplane-published.js +70 -0
- package/lib/external-system/deploy.js +12 -2
- package/lib/external-system/download-role-assistant.js +41 -15
- package/lib/external-system/download.js +8 -3
- package/lib/generator/helpers.js +12 -1
- package/lib/generator/wizard-datasource-key.js +54 -0
- package/lib/generator/wizard.js +55 -54
- package/lib/integration-definition/apply-datasource-keys.js +75 -0
- package/lib/integration-definition/apply-relationships.js +195 -0
- package/lib/integration-definition/apply-static-enterprise.js +232 -0
- package/lib/integration-definition/apply-system-file.js +71 -0
- package/lib/integration-definition/apply-test-endpoint.js +89 -0
- package/lib/integration-definition/apply-viewpoint-defaults.js +157 -0
- package/lib/integration-definition/apply.js +78 -59
- package/lib/integration-definition/enrich-openapi-operations.js +36 -10
- package/lib/integration-definition/enrich-openapi-pick.js +87 -0
- package/lib/lifecycle/role-assistant-governance.js +56 -21
- package/lib/programmatic/capability-registry.js +1 -0
- package/lib/programmatic/index.js +2 -0
- package/lib/programmatic/openapi-apply-result-schemas.js +8 -0
- package/lib/programmatic/openapi-channel-install-schemas.js +4 -1
- package/lib/programmatic/openapi-component-schemas.js +1 -0
- package/lib/programmatic/openapi-descriptions.js +9 -3
- package/lib/programmatic/openapi-envelope-examples.js +7 -0
- package/lib/programmatic/openapi-operation-bindings.js +5 -0
- package/lib/programmatic/openapi-request-schemas.js +5 -0
- package/lib/programmatic/openapi-schema-descriptions-channel.js +8 -5
- package/lib/programmatic/openapi-schema-descriptions-operations.js +19 -0
- package/lib/programmatic/openapi-spec.js +1 -0
- package/lib/programmatic/request-timeout.js +3 -0
- package/lib/programmatic/route-handler-map.js +7 -0
- package/lib/programmatic/run-channel-catalog.js +50 -8
- package/lib/programmatic/run-channel-install-options.js +5 -1
- package/lib/programmatic/run-download.js +41 -0
- package/lib/protection/auth-context.js +3 -1
- package/lib/protection/protection-display.js +3 -2
- package/lib/protection/report-exit.js +50 -0
- package/lib/protection/run-commands.js +2 -0
- package/lib/role-assistant/knowledge-sync-settings-push.js +172 -0
- package/lib/role-assistant/knowledge-sync.js +9 -126
- package/lib/role-assistant/package-validate.js +175 -0
- package/lib/role-assistant/test-case-assertion-row.js +36 -0
- package/lib/role-assistant/test-case-copy-bind.js +77 -0
- package/lib/role-assistant/test-case-copy-expected.js +127 -0
- package/lib/role-assistant/test-case-copy-from-work.js +90 -0
- package/lib/role-assistant/test-case-copy-interactions.js +67 -0
- package/lib/role-assistant/test-case-copy.js +119 -0
- package/lib/role-assistant/test-case-expected-catalog.js +135 -0
- package/lib/role-assistant/test-case-validate.js +88 -0
- package/lib/role-assistant/test-cases-bid.js +117 -4
- package/lib/role-assistant/test-cases-evaluate.js +149 -31
- package/lib/role-assistant/test-cases-evidence.js +44 -5
- package/lib/role-assistant/test-cases-honesty.js +155 -6
- package/lib/role-assistant/test-cases-lifecycle.js +297 -0
- package/lib/role-assistant/test-cases-search-graph.js +122 -0
- package/lib/role-assistant/test-cases-search.js +20 -2
- package/lib/role-assistant/test-cases.js +34 -168
- package/lib/role-assistant/test-pack-map.js +180 -0
- package/lib/role-assistant/test-pack-sync.js +187 -0
- package/lib/role-assistant/test-runner-debug.js +54 -0
- package/lib/role-assistant/test-runner-respond-body.js +36 -0
- package/lib/role-assistant/test-runner-search.js +20 -5
- package/lib/role-assistant/test-runner-start-payload.js +63 -10
- package/lib/role-assistant/test-runner-workhub-answers.js +45 -16
- package/lib/role-assistant/test-runner-workhub.js +45 -21
- package/lib/role-assistant/test-runner.js +53 -10
- package/lib/schema/external-datasource.schema.json +36 -5
- package/lib/schema/external-system.schema.json +20 -2
- package/lib/schema/infra-parameter.schema.json +51 -3
- package/lib/schema/infra.parameter.yaml +476 -40
- package/lib/schema/role-assistant-test-case.schema.json +408 -0
- package/lib/schema/type/document-storage.json +1 -1
- package/lib/search/dataplane-context.js +23 -0
- package/lib/search/search-args.js +211 -0
- package/lib/search/search-display.js +238 -0
- package/lib/search/search-errors.js +50 -0
- package/lib/search/search-prompts.js +119 -0
- package/lib/search/search-roles.js +85 -0
- package/lib/search/search-run.js +241 -0
- package/lib/search/search-skills.js +198 -0
- package/lib/utils/api-required-permissions.js +271 -0
- package/lib/utils/api.js +16 -13
- package/lib/utils/authentication-slot-show.js +153 -0
- package/lib/utils/cli-json-exit.js +41 -0
- package/lib/utils/cli-utils.js +23 -5
- package/lib/utils/controller-url.js +78 -4
- package/lib/utils/credential-display.js +43 -1
- package/lib/utils/deployment-errors.js +15 -0
- package/lib/utils/deployment-validation-helpers.js +4 -1
- package/lib/utils/device-code.js +31 -10
- package/lib/utils/error-formatters/error-parser.js +16 -1
- package/lib/utils/error-formatters/permission-errors.js +19 -5
- package/lib/utils/external-system-readiness-compact-blocks.js +5 -1
- package/lib/utils/external-system-readiness-compact-display.js +30 -1
- package/lib/utils/external-system-validators.js +2 -1
- package/lib/utils/help-builder.js +3 -1
- package/lib/utils/keycloak-realm-ready.js +5 -2
- package/lib/utils/logger.js +1 -0
- package/lib/utils/paths.js +26 -5
- package/lib/utils/schema-loader.js +37 -0
- package/lib/utils/secrets-helpers.js +2 -2
- package/lib/utils/write-stream-and-wait.js +63 -0
- package/lib/validation/validate-external-file.js +5 -1
- package/lib/validation/validate.js +3 -2
- package/package.json +20 -6
- package/templates/agent-kit/adapters/claude/nested.CLAUDE.md +1 -0
- package/templates/agent-kit/adapters/claude/root.CLAUDE.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-0-plan.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-1-validate.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-2-build.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-3-push.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-1-validate.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-2-build.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-3-prove.md +5 -0
- package/templates/agent-kit/agent-kit.yaml +45 -0
- package/templates/agent-kit/instructions/AGENTKIT.md +104 -0
- package/templates/agent-kit/instructions/integration.AGENTS.md +25 -0
- package/templates/agent-kit/instructions/role-assistant.AGENTS.md +22 -0
- package/templates/agent-kit/instructions/root.AGENTS.md +37 -0
- package/templates/agent-kit/parity-inventory.yaml +188 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/SKILL.md +59 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/contract-checklist.md +40 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/delivery-gates.md +54 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/production-safety.md +35 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/scripts/reserved-system-key.js +19 -0
- package/templates/agent-kit/skills/aifabrix-plan/SKILL.md +52 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/challenge-checklist.md +108 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/interaction.md +34 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/plan-template.md +182 -0
- package/templates/agent-kit/skills/aifabrix-prove/SKILL.md +51 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/demo-template.md +65 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/evidence-lifecycle.md +68 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/learning-template.md +66 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/SKILL.md +43 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/references/package-boundary.md +21 -0
- package/templates/agent-kit/skills/shared/hosts.md +65 -0
- package/templates/agent-kit/skills/shared/login.md +16 -0
- package/templates/agent-kit/workspace/.cursor/plans/README.md +22 -0
- package/templates/agent-kit/workspace/LICENSE.mit +21 -0
- package/templates/agent-kit/workspace/README.md +89 -0
- package/templates/applications/builder-api/Dockerfile +3 -1
- package/templates/applications/dataplane/application.yaml +2 -3
- package/templates/applications/dataplane/env.template +5 -5
- package/templates/applications/dataplane/rbac.yaml +28 -0
- package/templates/applications/keycloak/env.template +3 -3
- package/templates/applications/miso-controller/application.yaml +21 -2
- package/templates/applications/miso-controller/env.template +96 -25
- package/templates/applications/miso-controller/rbac.yaml +5 -0
- package/templates/channels/claude/TROUBLESHOOTING.md +3 -0
- package/templates/channels/claude/channel.json +1 -1
- package/templates/channels/claude/install.template.md.hbs +1 -0
- package/templates/channels/claude/integration/claude-system.json +1 -1
- package/templates/channels/slack/channel.json +11 -0
- package/templates/channels/slack/install.template.md.hbs +9 -0
- package/templates/channels/slack/integration/slack-system.json +11 -0
- package/templates/channels/slack/manifest.template.json.hbs +6 -3
- package/templates/channels/teams-bot/channel.json +1 -0
- package/templates/python/docker-compose.hbs +14 -0
- package/templates/typescript/docker-compose.hbs +14 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aifabrix role-assistant copy — capture one Work Hub execution as YAML.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Leaf command; Builder materializes the case from Work Hub reference
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { resolveLifecycleAuth } = require('./lifecycle-external');
|
|
10
|
+
const { fetchWorkCopyReference, buildCopyCaseFromWorkReference } = require(
|
|
11
|
+
'../role-assistant/test-case-copy-from-work'
|
|
12
|
+
);
|
|
13
|
+
const { roleAssistantSystemKey } = require('../utils/role-assistant-paths');
|
|
14
|
+
const { roleAssistantTestsDir } = require('../role-assistant/test-cases');
|
|
15
|
+
const {
|
|
16
|
+
defaultCaseIdFromReference,
|
|
17
|
+
assertProcessExecutionId,
|
|
18
|
+
assertFolderToken,
|
|
19
|
+
copyTargetPath,
|
|
20
|
+
prepareCopyDocument,
|
|
21
|
+
yamlFromValidatedCase,
|
|
22
|
+
assertCopyTargetWritable,
|
|
23
|
+
persistCopyCaseYaml
|
|
24
|
+
} = require('../role-assistant/test-case-copy');
|
|
25
|
+
const { emitCopySuccess, emitCopyFailure } = require('./role-assistant-copy-output');
|
|
26
|
+
|
|
27
|
+
function copyHelpAfter() {
|
|
28
|
+
return `
|
|
29
|
+
Examples:
|
|
30
|
+
$ aifabrix role-assistant copy customer-support-bot --suite 001 --reference a9f09fb8-d9eb-477f-8bb4-59e670fc82a4
|
|
31
|
+
$ aifabrix role-assistant copy customer-support-bot --suite 001 --reference a9f09fb8-d9eb-477f-8bb4-59e670fc82a4 --case address-change
|
|
32
|
+
$ aifabrix role-assistant copy customer-support-bot --suite 001 --reference a9f09fb8-d9eb-477f-8bb4-59e670fc82a4 --dry-run
|
|
33
|
+
$ aifabrix role-assistant copy customer-support-bot --suite 001 --reference a9f09fb8-d9eb-477f-8bb4-59e670fc82a4 --json
|
|
34
|
+
|
|
35
|
+
Notes:
|
|
36
|
+
- <roleKey> is bare; package folder is role-assistant/ra-<roleKey>/.
|
|
37
|
+
- --reference is the Work Hub execution id (the same id printed after a run).
|
|
38
|
+
- Writes tests/<suite>/<caseId>.yaml. Default caseId is copy-<first 8 hex of the execution id>.
|
|
39
|
+
- Existing files are not overwritten unless --force is set.
|
|
40
|
+
- --dry-run prints YAML and does not write.
|
|
41
|
+
- Builds local YAML from Work Hub execution status and result. Does not publish; use upload / deploy.
|
|
42
|
+
`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function normalizeCopyOptions(options) {
|
|
46
|
+
const opts = options && typeof options === 'object' ? options : {};
|
|
47
|
+
return {
|
|
48
|
+
env: opts.env || 'dev',
|
|
49
|
+
suite: opts.suite,
|
|
50
|
+
reference: opts.reference,
|
|
51
|
+
case: opts.case,
|
|
52
|
+
force: opts.force === true,
|
|
53
|
+
dryRun: opts.dryRun === true,
|
|
54
|
+
json: opts.json === true,
|
|
55
|
+
testsDir: opts.testsDir || null
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function requireCopyFlags(opts) {
|
|
60
|
+
if (!opts.suite) {
|
|
61
|
+
throw new Error('--suite is required');
|
|
62
|
+
}
|
|
63
|
+
if (!opts.reference) {
|
|
64
|
+
throw new Error('--reference is required');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function fetchCopyCase(systemKey, opts, peId, caseId) {
|
|
69
|
+
const auth = await resolveLifecycleAuth(systemKey, {
|
|
70
|
+
env: opts.env,
|
|
71
|
+
run: false,
|
|
72
|
+
noPublish: true
|
|
73
|
+
});
|
|
74
|
+
if (!auth || !auth.dataplaneUrl || !auth.authConfig) {
|
|
75
|
+
throw new Error('Not authenticated. Run aifabrix login, then retry.');
|
|
76
|
+
}
|
|
77
|
+
const reference = await fetchWorkCopyReference(
|
|
78
|
+
auth.dataplaneUrl,
|
|
79
|
+
auth.authConfig,
|
|
80
|
+
peId
|
|
81
|
+
);
|
|
82
|
+
return buildCopyCaseFromWorkReference({
|
|
83
|
+
systemKey,
|
|
84
|
+
caseId,
|
|
85
|
+
processExecutionId: peId,
|
|
86
|
+
status: reference.status,
|
|
87
|
+
result: reference.result
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function runRoleAssistantCopy(roleKey, options) {
|
|
92
|
+
const opts = normalizeCopyOptions(options);
|
|
93
|
+
requireCopyFlags(opts);
|
|
94
|
+
const peId = assertProcessExecutionId(opts.reference);
|
|
95
|
+
const suiteId = assertFolderToken(opts.suite, 'Suite id');
|
|
96
|
+
const caseId = assertFolderToken(
|
|
97
|
+
opts.case || defaultCaseIdFromReference(peId),
|
|
98
|
+
'Case id'
|
|
99
|
+
);
|
|
100
|
+
const systemKey = roleAssistantSystemKey(roleKey);
|
|
101
|
+
const testsDir = roleAssistantTestsDir(systemKey, { testsDir: opts.testsDir });
|
|
102
|
+
const targetPath = copyTargetPath(testsDir, suiteId, caseId);
|
|
103
|
+
if (!opts.dryRun) {
|
|
104
|
+
assertCopyTargetWritable(targetPath, opts.force);
|
|
105
|
+
}
|
|
106
|
+
const payload = await fetchCopyCase(systemKey, opts, peId, caseId);
|
|
107
|
+
const caseDoc = prepareCopyDocument(payload, caseId, peId);
|
|
108
|
+
const yamlText = yamlFromValidatedCase(caseDoc);
|
|
109
|
+
if (!opts.dryRun) {
|
|
110
|
+
persistCopyCaseYaml(targetPath, yamlText);
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
success: true,
|
|
114
|
+
path: targetPath,
|
|
115
|
+
caseId,
|
|
116
|
+
suiteId,
|
|
117
|
+
processExecutionId: peId,
|
|
118
|
+
warnings: payload && payload.warnings,
|
|
119
|
+
yaml: yamlText,
|
|
120
|
+
dryRun: opts.dryRun
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function roleAssistantCopyHandler(roleKey, options) {
|
|
125
|
+
try {
|
|
126
|
+
const result = await runRoleAssistantCopy(roleKey, options);
|
|
127
|
+
emitCopySuccess(options, result);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
emitCopyFailure(options, error);
|
|
130
|
+
process.exit(error && error.exitCode ? error.exitCode : 1);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function registerRoleAssistantCopyCommand(roleAssistant) {
|
|
135
|
+
roleAssistant
|
|
136
|
+
.command('copy <roleKey>')
|
|
137
|
+
.description('Capture one Work Hub execution as a local YAML test case')
|
|
138
|
+
.requiredOption('--suite <suiteId>', 'Suite folder under tests/ (for example 001)')
|
|
139
|
+
.requiredOption('--reference <executionId>', 'Work Hub execution id')
|
|
140
|
+
.option('--case <caseId>', 'Case id (default: copy-<first 8 hex of the execution id>)')
|
|
141
|
+
.option('--force', 'Overwrite an existing YAML file')
|
|
142
|
+
.option('--dry-run', 'Print YAML and do not write')
|
|
143
|
+
.option('-e, --env <env>', 'Environment: dev, tst, or pro', 'dev')
|
|
144
|
+
.option('--json', 'Machine-readable output envelope')
|
|
145
|
+
.addHelpText('after', copyHelpAfter())
|
|
146
|
+
.action((roleKey, options) => roleAssistantCopyHandler(roleKey, options));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = {
|
|
150
|
+
copyHelpAfter,
|
|
151
|
+
normalizeCopyOptions,
|
|
152
|
+
runRoleAssistantCopy,
|
|
153
|
+
roleAssistantCopyHandler,
|
|
154
|
+
registerRoleAssistantCopyCommand
|
|
155
|
+
};
|
|
@@ -16,6 +16,7 @@ const {
|
|
|
16
16
|
formatBlockingError,
|
|
17
17
|
metadata
|
|
18
18
|
} = require('../utils/cli-test-layout-chalk');
|
|
19
|
+
const { formatCaseResultRows } = require('./role-assistant-test-result-rows');
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Bucket a lifecycle step status into ok | failed | skipped | other.
|
|
@@ -157,15 +158,12 @@ function displayCaseResultSummary(caseResult) {
|
|
|
157
158
|
}
|
|
158
159
|
if (caseResult.passed) {
|
|
159
160
|
logger.log(formatSuccessLine('Case assertions passed.'));
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
logger.log(formatWarningLine(row.message || String(row)));
|
|
163
|
-
}
|
|
164
|
-
return;
|
|
161
|
+
} else {
|
|
162
|
+
logger.log(formatBlockingError('Case assertions failed.'));
|
|
165
163
|
}
|
|
166
|
-
logger.log(
|
|
167
|
-
for (const
|
|
168
|
-
logger.log(
|
|
164
|
+
logger.log(metadata('Results:'));
|
|
165
|
+
for (const line of formatCaseResultRows(caseResult.assertions)) {
|
|
166
|
+
logger.log(line);
|
|
169
167
|
}
|
|
170
168
|
}
|
|
171
169
|
|
|
@@ -210,5 +208,6 @@ function displayRoleAssistantTestSummary(roleKey, verdict, portalUrl, result, ca
|
|
|
210
208
|
module.exports = {
|
|
211
209
|
formatStepsRunSummary,
|
|
212
210
|
buildRoleAssistantTestEnvelope,
|
|
213
|
-
displayRoleAssistantTestSummary
|
|
211
|
+
displayRoleAssistantTestSummary,
|
|
212
|
+
formatCaseResultRows
|
|
214
213
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human TTY lines for Role Assistant case assertion rows.
|
|
3
|
+
* @fileoverview Canonical glyphs for pass/fail/warn/notes/skip
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
formatSuccessLine,
|
|
10
|
+
formatWarningLine,
|
|
11
|
+
formatBlockingError,
|
|
12
|
+
infoLine,
|
|
13
|
+
metadata
|
|
14
|
+
} = require('../utils/cli-test-layout-chalk');
|
|
15
|
+
const { withKind } = require('../role-assistant/test-case-assertion-row');
|
|
16
|
+
|
|
17
|
+
function formatCaseResultLine(assertion) {
|
|
18
|
+
const row = withKind(assertion || {});
|
|
19
|
+
const text = `${row.id || 'assertion'} — ${row.message || ''}`.trim();
|
|
20
|
+
if (row.kind === 'fail') {
|
|
21
|
+
return ` ${formatBlockingError(text)}`;
|
|
22
|
+
}
|
|
23
|
+
if (row.kind === 'warn') {
|
|
24
|
+
return ` ${formatWarningLine(text)}`;
|
|
25
|
+
}
|
|
26
|
+
if (row.kind === 'notes') {
|
|
27
|
+
return ` ${infoLine(`ℹ ${text}`)}`;
|
|
28
|
+
}
|
|
29
|
+
if (row.kind === 'skip') {
|
|
30
|
+
return ` ${metadata(`⏭ ${text}`)}`;
|
|
31
|
+
}
|
|
32
|
+
return ` ${formatSuccessLine(text)}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function formatCaseResultRows(assertions) {
|
|
36
|
+
return (Array.isArray(assertions) ? assertions : []).map(formatCaseResultLine);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = {
|
|
40
|
+
formatCaseResultLine,
|
|
41
|
+
formatCaseResultRows
|
|
42
|
+
};
|
|
@@ -35,6 +35,11 @@ const {
|
|
|
35
35
|
lifecycleVerdictFromCaseExecution
|
|
36
36
|
} = require('../role-assistant/test-runner');
|
|
37
37
|
const { assertRoleAssistantEvidencePreflight } = require('../role-assistant/test-cases-evidence');
|
|
38
|
+
const { assertLocalCasesBeforeAuth } = require('../role-assistant/test-case-validate');
|
|
39
|
+
const {
|
|
40
|
+
loadPublishedTestsIntoOptions,
|
|
41
|
+
patchCaseStatusAfterRun
|
|
42
|
+
} = require('../role-assistant/test-pack-sync');
|
|
38
43
|
const { collectString } = require('./governance');
|
|
39
44
|
const {
|
|
40
45
|
sectionTitle,
|
|
@@ -50,27 +55,33 @@ const {
|
|
|
50
55
|
bareRoleKey,
|
|
51
56
|
roleAssistantSystemKey
|
|
52
57
|
} = require('../utils/role-assistant-paths');
|
|
58
|
+
const { registerRoleAssistantCopyCommand } = require('./role-assistant-copy');
|
|
53
59
|
|
|
54
60
|
function roleAssistantGroupHelpAfter() {
|
|
55
61
|
return `
|
|
56
62
|
Subcommands:
|
|
57
63
|
test <roleKey> Run lifecycle checks, optional YAML cases/suites, and print a portal deep link
|
|
64
|
+
copy <roleKey> Capture one Work Hub execution as a local YAML test case
|
|
58
65
|
|
|
59
66
|
Package workspace (top-level commands — same digital-worker package):
|
|
60
|
-
download / validate / upload
|
|
67
|
+
download / validate / upload ra-<roleKey> Manage role-assistant/ra-<roleKey>/
|
|
68
|
+
upload publishes settings and sidecars; operator Make available is a separate action
|
|
61
69
|
|
|
62
70
|
Examples:
|
|
63
71
|
$ aifabrix role-assistant test customer-support-bot
|
|
64
72
|
$ aifabrix role-assistant test customer-support-bot --suite 001
|
|
65
73
|
$ aifabrix role-assistant test customer-support-bot --list-cases
|
|
66
74
|
$ aifabrix role-assistant test customer-support-bot --env tst --json
|
|
67
|
-
$ aifabrix
|
|
75
|
+
$ aifabrix role-assistant copy customer-support-bot --suite 001 --reference a9f09fb8-d9eb-477f-8bb4-59e670fc82a4
|
|
76
|
+
$ aifabrix upload ra-customer-support-bot --env dev
|
|
68
77
|
$ aifabrix test ra-customer-support-bot
|
|
69
78
|
|
|
70
79
|
Notes:
|
|
71
|
-
-
|
|
80
|
+
- role-assistant test/copy use bare <roleKey>; top-level package commands use ra-<roleKey>.
|
|
72
81
|
- test uses the public/running worker by default; pass --publish (or upload) to refresh from local files.
|
|
82
|
+
- copy writes tests/<suite>/<caseId>.yaml from a Work Hub execution id; it does not publish.
|
|
73
83
|
- See: aifabrix role-assistant test -h
|
|
84
|
+
- See: aifabrix role-assistant copy -h
|
|
74
85
|
`;
|
|
75
86
|
}
|
|
76
87
|
|
|
@@ -84,6 +95,7 @@ Examples:
|
|
|
84
95
|
$ aifabrix role-assistant test customer-support-bot --suite 001
|
|
85
96
|
$ aifabrix role-assistant test customer-support-bot --list-cases
|
|
86
97
|
$ aifabrix role-assistant test customer-support-bot --suite 001 --fail-fast --json
|
|
98
|
+
$ aifabrix role-assistant test customer-support-bot --from-dataplane
|
|
87
99
|
$ aifabrix test ra-customer-support-bot
|
|
88
100
|
|
|
89
101
|
Notes:
|
|
@@ -93,6 +105,8 @@ Notes:
|
|
|
93
105
|
- Runs lifecycle checks, then prints a portal deep link for full step-by-step status.
|
|
94
106
|
- Case files with input.message/input.content execute Work Hub plan→accept (or work.start when executionPath: intent).
|
|
95
107
|
- Cases with executionPath: search|skills (input.executionPath or case-root executionPath) run work.skills / work.search instead of Work Hub.
|
|
108
|
+
- After each case, current status is stored on the published test pack (passed, failed, or skipped).
|
|
109
|
+
- --from-dataplane loads published tests, then runs them (all suites unless --case / --suite is set).
|
|
96
110
|
- Role Assistant packages do not need application.yaml; test uses device login and the published dataplane worker.
|
|
97
111
|
- Cases with preflight.evidence.requiredKeys read live Evidence from the dataplane before start and hard-stop if those keys are missing or not active.
|
|
98
112
|
- answers[] and approvals[] are matched to runtime wait payloads (questionKey/requestKey/waitReason).
|
|
@@ -138,6 +152,7 @@ function normalizeRoleAssistantTestOptions(options, cmd) {
|
|
|
138
152
|
casesRoot: trimOptionalString(options.casesRoot),
|
|
139
153
|
listCases: optionOrFlag(options, 'listCases', cmd, '--list-cases'),
|
|
140
154
|
failFast: optionOrFlag(options, 'failFast', cmd, '--fail-fast'),
|
|
155
|
+
fromDataplane: optionOrFlag(options, 'fromDataplane', cmd, '--from-dataplane'),
|
|
141
156
|
run: true
|
|
142
157
|
};
|
|
143
158
|
}
|
|
@@ -220,45 +235,91 @@ async function resolveSuiteCaseResults(systemKey, opts, result, verdict, portalU
|
|
|
220
235
|
return outcomes;
|
|
221
236
|
}
|
|
222
237
|
|
|
238
|
+
async function maybeLoadFromDataplane(systemKey, opts) {
|
|
239
|
+
if (!opts.fromDataplane) {
|
|
240
|
+
return opts;
|
|
241
|
+
}
|
|
242
|
+
const auth = await resolveLifecycleAuth(systemKey, { ...opts, run: false, noPublish: true });
|
|
243
|
+
return loadPublishedTestsIntoOptions(systemKey, opts, auth);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async function resolveSelectedCaseResults(systemKey, opts, result, verdict, portalUrl) {
|
|
247
|
+
const runDiscovered = Boolean(opts.suite || (opts.fromDataplane && !opts.case));
|
|
248
|
+
if (runDiscovered) {
|
|
249
|
+
return resolveSuiteCaseResults(systemKey, opts, result, verdict, portalUrl);
|
|
250
|
+
}
|
|
251
|
+
return resolveRoleAssistantCaseResult(systemKey, opts, result, verdict, portalUrl);
|
|
252
|
+
}
|
|
253
|
+
|
|
223
254
|
async function runRoleAssistantTestAction(roleKey, options, cmd) {
|
|
224
|
-
|
|
255
|
+
let opts = normalizeRoleAssistantTestOptions(options, cmd);
|
|
225
256
|
const systemKey = roleAssistantSystemKey(roleKey);
|
|
226
257
|
const displayKey = bareRoleKey(roleKey);
|
|
258
|
+
opts = await maybeLoadFromDataplane(systemKey, opts);
|
|
227
259
|
|
|
228
260
|
if (opts.listCases) {
|
|
229
261
|
return listRoleAssistantCases(systemKey, opts);
|
|
230
262
|
}
|
|
231
263
|
|
|
264
|
+
assertLocalCasesBeforeAuth(systemKey, opts);
|
|
265
|
+
|
|
232
266
|
const result = await runLifecycleForExternalSystem(systemKey, opts);
|
|
233
267
|
const verdict = lifecycleVerdictFromReport(result.report || {});
|
|
234
268
|
const portalUrl = buildExternalSystemUiUrl(result.dataplaneUiBaseUrl, systemKey);
|
|
269
|
+
const caseResult = await resolveSelectedCaseResults(systemKey, opts, result, verdict, portalUrl);
|
|
235
270
|
|
|
236
|
-
|
|
237
|
-
if (opts.suite) {
|
|
238
|
-
caseResult = await resolveSuiteCaseResults(systemKey, opts, result, verdict, portalUrl);
|
|
239
|
-
} else {
|
|
240
|
-
caseResult = await resolveRoleAssistantCaseResult(systemKey, opts, result, verdict, portalUrl);
|
|
241
|
-
}
|
|
271
|
+
const exitCode = computeRoleAssistantExitCode(verdict, caseResult);
|
|
242
272
|
|
|
243
273
|
if (opts.json) {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
274
|
+
// Large piped stdout writes on Linux are non-blocking; exiting right
|
|
275
|
+
// after console.log() can truncate the JSON before the OS write
|
|
276
|
+
// completes. Wait for the write to flush before exiting non-zero.
|
|
277
|
+
const payload = JSON.stringify(
|
|
278
|
+
logger.sanitizeValue(
|
|
279
|
+
buildRoleAssistantTestEnvelope(displayKey, verdict, portalUrl, result, opts, caseResult)
|
|
280
|
+
),
|
|
281
|
+
null,
|
|
282
|
+
2
|
|
250
283
|
);
|
|
251
|
-
|
|
252
|
-
|
|
284
|
+
return new Promise((resolve) => {
|
|
285
|
+
process.stdout.write(`${payload}\n`, () => {
|
|
286
|
+
if (exitCode !== 0) {
|
|
287
|
+
process.exit(exitCode);
|
|
288
|
+
}
|
|
289
|
+
resolve(exitCode);
|
|
290
|
+
});
|
|
291
|
+
});
|
|
253
292
|
}
|
|
254
293
|
|
|
255
|
-
|
|
294
|
+
displayRoleAssistantTestSummary(displayKey, verdict, portalUrl, result, caseResult);
|
|
256
295
|
if (exitCode !== 0) {
|
|
257
296
|
process.exit(exitCode);
|
|
258
297
|
}
|
|
259
298
|
return exitCode;
|
|
260
299
|
}
|
|
261
300
|
|
|
301
|
+
async function patchPublishedCaseStatus(roleKey, opts, roleCase, evaluation, authContext) {
|
|
302
|
+
const caseId = roleCase && roleCase.caseId;
|
|
303
|
+
if (!caseId) {
|
|
304
|
+
return evaluation;
|
|
305
|
+
}
|
|
306
|
+
let auth = authContext;
|
|
307
|
+
if (!auth || !auth.dataplaneUrl || !auth.authConfig) {
|
|
308
|
+
auth = await resolveLifecycleAuth(roleKey, { ...opts, run: false, noPublish: true });
|
|
309
|
+
}
|
|
310
|
+
if (!auth || !auth.dataplaneUrl || !auth.authConfig) {
|
|
311
|
+
return evaluation;
|
|
312
|
+
}
|
|
313
|
+
await patchCaseStatusAfterRun({
|
|
314
|
+
systemKey: roleAssistantSystemKey(roleKey),
|
|
315
|
+
caseId,
|
|
316
|
+
evaluation,
|
|
317
|
+
dataplaneUrl: auth.dataplaneUrl,
|
|
318
|
+
authConfig: auth.authConfig
|
|
319
|
+
});
|
|
320
|
+
return evaluation;
|
|
321
|
+
}
|
|
322
|
+
|
|
262
323
|
function attachCaseExecution(evaluation, executionResult, error) {
|
|
263
324
|
const errMsg = error && (error.message || String(error));
|
|
264
325
|
evaluation.execution = {
|
|
@@ -298,32 +359,35 @@ async function resolveRoleAssistantCaseResult(roleKey, opts, result, verdict, po
|
|
|
298
359
|
const roleCase = loadRoleAssistantTestCase(roleKey, opts.case, {
|
|
299
360
|
testsDir: opts.testsDir || null
|
|
300
361
|
});
|
|
362
|
+
let evaluation;
|
|
301
363
|
if (!isExecutableRoleAssistantCase(roleCase)) {
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
364
|
+
evaluation = evaluateRoleAssistantTestCase(roleCase, result, verdict, portalUrl);
|
|
365
|
+
} else {
|
|
366
|
+
try {
|
|
367
|
+
evaluation = await resolveExecutableCaseResult(
|
|
368
|
+
roleKey,
|
|
369
|
+
roleCase,
|
|
370
|
+
opts,
|
|
371
|
+
result,
|
|
372
|
+
verdict,
|
|
373
|
+
portalUrl
|
|
374
|
+
);
|
|
375
|
+
} catch (error) {
|
|
376
|
+
const failedInput = mergeCaseExecutionIntoLifecycleResult(result, {
|
|
377
|
+
finalStatus: { status: 'failed' },
|
|
378
|
+
workResult: null,
|
|
379
|
+
workResultError: error.message || String(error),
|
|
380
|
+
interactions: []
|
|
381
|
+
});
|
|
382
|
+
failedInput.workResultError = error.message || String(error);
|
|
383
|
+
evaluation = attachCaseExecution(
|
|
384
|
+
evaluateRoleAssistantTestCase(roleCase, failedInput, verdict, portalUrl),
|
|
385
|
+
null,
|
|
386
|
+
error
|
|
387
|
+
);
|
|
388
|
+
}
|
|
326
389
|
}
|
|
390
|
+
return patchPublishedCaseStatus(roleKey, opts, roleCase, evaluation);
|
|
327
391
|
}
|
|
328
392
|
|
|
329
393
|
async function roleAssistantTestHandler(roleKey, options, cmd) {
|
|
@@ -335,19 +399,8 @@ async function roleAssistantTestHandler(roleKey, options, cmd) {
|
|
|
335
399
|
}
|
|
336
400
|
}
|
|
337
401
|
|
|
338
|
-
function
|
|
339
|
-
|
|
340
|
-
.command('role-assistant')
|
|
341
|
-
.description(
|
|
342
|
-
'Role Assistant packages: lifecycle checks, YAML cases/suites, and portal deep links'
|
|
343
|
-
)
|
|
344
|
-
.addHelpText('after', roleAssistantGroupHelpAfter());
|
|
345
|
-
|
|
346
|
-
roleAssistant
|
|
347
|
-
.command('test <roleKey>')
|
|
348
|
-
.description(
|
|
349
|
-
'Lifecycle checks + optional cases/suites; prints portal deep link (bare <roleKey>)'
|
|
350
|
-
)
|
|
402
|
+
function addRoleAssistantTestRunOptions(cmd) {
|
|
403
|
+
return cmd
|
|
351
404
|
.option('-e, --env <env>', 'Environment: dev, tst, or pro', 'dev')
|
|
352
405
|
.option('--case <caseIdOrPath>', 'Run and evaluate one role-assistant test case')
|
|
353
406
|
.option('--tests-dir <dir>', 'Override role-assistant test case directory')
|
|
@@ -361,8 +414,16 @@ function setupRoleAssistantCommands(program) {
|
|
|
361
414
|
)
|
|
362
415
|
.option('--list-cases', 'List discoverable case files and exit')
|
|
363
416
|
.option('--fail-fast', 'Stop suite run after the first failing case')
|
|
417
|
+
.option(
|
|
418
|
+
'--from-dataplane',
|
|
419
|
+
'Load published tests from the dataplane, then run them (all suites unless --case or --suite is set)'
|
|
420
|
+
)
|
|
364
421
|
.option('-v, --verbose', 'Include full lifecycle report payload in --json output')
|
|
365
|
-
.option('-d, --debug', 'Write debug logs under role-assistant/<roleKey>/logs/')
|
|
422
|
+
.option('-d, --debug', 'Write debug logs under role-assistant/<roleKey>/logs/');
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function addRoleAssistantTestPublishOptions(cmd) {
|
|
426
|
+
return cmd
|
|
366
427
|
.option(
|
|
367
428
|
'--publish',
|
|
368
429
|
'Publish local Role Assistant package before checks (default: use public/running worker)'
|
|
@@ -385,9 +446,29 @@ function setupRoleAssistantCommands(program) {
|
|
|
385
446
|
'Ignored for Role Assistant packages (Connected System governance generate does not run)',
|
|
386
447
|
'bronze'
|
|
387
448
|
)
|
|
388
|
-
.option('--json', 'Machine-readable output envelope')
|
|
449
|
+
.option('--json', 'Machine-readable output envelope');
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function registerRoleAssistantTestCommand(roleAssistant) {
|
|
453
|
+
const cmd = roleAssistant
|
|
454
|
+
.command('test <roleKey>')
|
|
455
|
+
.description(
|
|
456
|
+
'Lifecycle checks + optional cases/suites; prints portal deep link (bare <roleKey>)'
|
|
457
|
+
);
|
|
458
|
+
addRoleAssistantTestPublishOptions(addRoleAssistantTestRunOptions(cmd))
|
|
389
459
|
.addHelpText('after', roleAssistantHelpAfter())
|
|
390
|
-
.action((roleKey, options,
|
|
460
|
+
.action((roleKey, options, invoked) => roleAssistantTestHandler(roleKey, options, invoked));
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function setupRoleAssistantCommands(program) {
|
|
464
|
+
const roleAssistant = program
|
|
465
|
+
.command('role-assistant')
|
|
466
|
+
.description(
|
|
467
|
+
'Role Assistant packages: lifecycle checks, YAML cases/suites, copy from Work Hub, and portal deep links'
|
|
468
|
+
)
|
|
469
|
+
.addHelpText('after', roleAssistantGroupHelpAfter());
|
|
470
|
+
registerRoleAssistantTestCommand(roleAssistant);
|
|
471
|
+
registerRoleAssistantCopyCommand(roleAssistant);
|
|
391
472
|
}
|
|
392
473
|
|
|
393
474
|
module.exports = {
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aifabrix search — retrieve governed Role Assistant information.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Commander registration for search and search skills
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const logger = require('../utils/logger');
|
|
12
|
+
const { runSearch, runSearchSkills } = require('../search/search-run');
|
|
13
|
+
const { exitCodeForSearchError } = require('../search/search-errors');
|
|
14
|
+
const { emitSearchError } = require('../search/search-display');
|
|
15
|
+
|
|
16
|
+
const SEARCH_HELP = `
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
$ aifabrix search
|
|
20
|
+
$ aifabrix search --role ra-cfo --resource-type customer
|
|
21
|
+
$ aifabrix search --role ra-cfo --resource-type customer --operation list --json
|
|
22
|
+
$ aifabrix search --role ra-cfo --resource-type customer --output ./search.json
|
|
23
|
+
$ aifabrix search skills --role ra-cfo
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
const SKILLS_HELP = `
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
$ aifabrix search skills
|
|
30
|
+
$ aifabrix search skills --role ra-cfo
|
|
31
|
+
$ aifabrix search skills --role ra-cfo --json
|
|
32
|
+
$ aifabrix search skills --role ra-cfo --output ./skills.json
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {*} value
|
|
37
|
+
* @param {string[]} previous
|
|
38
|
+
* @returns {string[]}
|
|
39
|
+
*/
|
|
40
|
+
function collectKnowledgeKey(value, previous) {
|
|
41
|
+
const next = Array.isArray(previous) ? previous : [];
|
|
42
|
+
next.push(value);
|
|
43
|
+
return next;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {import('commander').Command} cmd
|
|
48
|
+
*/
|
|
49
|
+
function addSharedSearchOptions(cmd) {
|
|
50
|
+
cmd
|
|
51
|
+
.option('--role <roleRef>', 'Role Assistant key (for example ra-cfo)')
|
|
52
|
+
.option('--role-ref <roleRef>', 'Alias for --role')
|
|
53
|
+
.option('-o, --output <file>', 'Write the JSON payload to this file')
|
|
54
|
+
.option('--no-interactive', 'Never prompt; missing required flags fail')
|
|
55
|
+
.option('-e, --env <environment>', 'Environment key')
|
|
56
|
+
.option('--json', 'Print the JSON payload on stdout (no prompts)')
|
|
57
|
+
.option('-v, --verbose', 'Include extra TTY detail when available');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {import('commander').Command} cmd
|
|
62
|
+
*/
|
|
63
|
+
function addSearchBodyOptions(cmd) {
|
|
64
|
+
cmd
|
|
65
|
+
.option('--resource-type <key>', 'Resource type published on that Role Assistant')
|
|
66
|
+
.option('--type <key>', 'Alias for --resource-type')
|
|
67
|
+
.option('--operation <key>', 'Named operation for that resource type')
|
|
68
|
+
.option('--filters <json>', 'JSON object of field filters')
|
|
69
|
+
.option('--filters-file <path>', 'JSON object of field filters from a file')
|
|
70
|
+
.option('--page <n>', 'Page number (integer ≥ 1)')
|
|
71
|
+
.option('--page-size <n>', 'Page size (integer 1–100)')
|
|
72
|
+
.option('--sort <spec>', 'Sort specification (pass-through)')
|
|
73
|
+
.option('--fields <csv>', 'Comma-separated field names')
|
|
74
|
+
.option('--graph', 'Include one-level related records')
|
|
75
|
+
.option('--query <text>', 'Semantic hop text when --graph is set')
|
|
76
|
+
.option('--knowledge-key <key>', 'Knowledge key (repeatable)', collectKnowledgeKey, [])
|
|
77
|
+
.option('--body <file>', 'JSON request body file (merged after flags)');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @param {Function} action
|
|
82
|
+
* @param {Object} options
|
|
83
|
+
* @returns {Promise<void>}
|
|
84
|
+
*/
|
|
85
|
+
async function dispatchSearchLeaf(action, options) {
|
|
86
|
+
try {
|
|
87
|
+
const code = await action(options);
|
|
88
|
+
if (code && code !== 0) {
|
|
89
|
+
process.exit(code);
|
|
90
|
+
}
|
|
91
|
+
} catch (err) {
|
|
92
|
+
const message = err.message || String(err);
|
|
93
|
+
emitSearchError(options, message, logger);
|
|
94
|
+
process.exit(exitCodeForSearchError(err));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @param {Object} options
|
|
100
|
+
* @param {import('commander').Command} command
|
|
101
|
+
* @returns {Object}
|
|
102
|
+
*/
|
|
103
|
+
function mergeCommandOptions(options, command) {
|
|
104
|
+
const parentOpts =
|
|
105
|
+
command && command.parent && typeof command.parent.opts === 'function'
|
|
106
|
+
? command.parent.opts()
|
|
107
|
+
: {};
|
|
108
|
+
return { ...parentOpts, ...options };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @param {import('commander').Command} program
|
|
113
|
+
*/
|
|
114
|
+
function setupSearchCommands(program) {
|
|
115
|
+
const search = program
|
|
116
|
+
.command('search')
|
|
117
|
+
.description('Search governed information for a Role Assistant assigned to you')
|
|
118
|
+
.addHelpText('after', SEARCH_HELP);
|
|
119
|
+
addSharedSearchOptions(search);
|
|
120
|
+
addSearchBodyOptions(search);
|
|
121
|
+
|
|
122
|
+
const searchRun = search
|
|
123
|
+
.command('run', { isDefault: true, hidden: true })
|
|
124
|
+
.description('Search governed information for a Role Assistant assigned to you')
|
|
125
|
+
.addHelpText('after', SEARCH_HELP);
|
|
126
|
+
searchRun.action(async(options, command) => {
|
|
127
|
+
await dispatchSearchLeaf(runSearch, mergeCommandOptions(options, command));
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const skills = search
|
|
131
|
+
.command('skills')
|
|
132
|
+
.description('List searchable resource types and operations for a Role Assistant')
|
|
133
|
+
.addHelpText('after', SKILLS_HELP);
|
|
134
|
+
addSharedSearchOptions(skills);
|
|
135
|
+
skills.action(async(options, command) => {
|
|
136
|
+
await dispatchSearchLeaf(runSearchSkills, mergeCommandOptions(options, command));
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = {
|
|
141
|
+
setupSearchCommands,
|
|
142
|
+
collectKnowledgeKey
|
|
143
|
+
};
|