@aifabrix/builder 2.54.1 → 2.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +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 +130 -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 +239 -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/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/list-external-systems.js +2 -1
- 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-certification-commands.js +2 -2
- package/lib/cli/setup-certification.help.js +3 -1
- package/lib/commands/agent-kit-help.js +79 -0
- package/lib/commands/agent-kit.js +346 -0
- package/lib/commands/channel-add-help.js +5 -5
- package/lib/commands/datasource-capability-relate-cli.js +5 -4
- 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 +117 -48
- 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-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/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 +7 -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 +229 -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/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 +137 -30
- package/lib/role-assistant/test-cases-honesty.js +155 -6
- package/lib/role-assistant/test-cases-lifecycle.js +291 -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 +50 -10
- package/lib/schema/external-datasource.schema.json +36 -5
- package/lib/schema/external-system.schema.json +20 -2
- package/lib/schema/role-assistant-test-case.schema.json +408 -0
- 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/authentication-slot-show.js +153 -0
- package/lib/utils/credential-display.js +43 -1
- 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/schema-loader.js +37 -0
- package/lib/validation/validate-external-file.js +5 -1
- package/lib/validation/validate.js +3 -2
- package/package.json +1 -1
- 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 +83 -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 +58 -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 +51 -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 +50 -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 +42 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/references/package-boundary.md +21 -0
- package/templates/agent-kit/skills/shared/hosts.md +78 -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 -2
- package/templates/applications/dataplane/env.template +1 -1
- package/templates/applications/dataplane/rbac.yaml +28 -0
- package/templates/applications/keycloak/env.template +3 -3
- package/templates/applications/miso-controller/application.yaml +1 -1
- package/templates/applications/miso-controller/env.template +8 -9
- 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,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestrate aifabrix search and aifabrix search skills.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Search command run path (retrieve only)
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const fs = require('../internal/fs-real-sync');
|
|
12
|
+
const logger = require('../utils/logger');
|
|
13
|
+
const { getWorkRoles, getWorkSkills, searchWork } = require('../api/work-search.api');
|
|
14
|
+
const { resolveSearchDataplaneContext } = require('./dataplane-context');
|
|
15
|
+
const { SearchCliError, authRequiredError } = require('./search-errors');
|
|
16
|
+
const { buildSearchBody, roleRefFromOptions, resourceTypeFromOptions } = require('./search-args');
|
|
17
|
+
const {
|
|
18
|
+
skillsEnvelope,
|
|
19
|
+
resourceTypesMap,
|
|
20
|
+
typeSpec,
|
|
21
|
+
isOperationRequired,
|
|
22
|
+
assertTypePublished,
|
|
23
|
+
assertOperationPublished
|
|
24
|
+
} = require('./search-skills');
|
|
25
|
+
const {
|
|
26
|
+
isInteractive,
|
|
27
|
+
missingFlagsError,
|
|
28
|
+
promptRoleAssistant,
|
|
29
|
+
promptResourceType,
|
|
30
|
+
promptOperation
|
|
31
|
+
} = require('./search-prompts');
|
|
32
|
+
const { emitSearchSuccess, emitSkillsSuccess } = require('./search-display');
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {Object} [overrides]
|
|
36
|
+
* @returns {Object}
|
|
37
|
+
*/
|
|
38
|
+
function defaultDeps(overrides = {}) {
|
|
39
|
+
return {
|
|
40
|
+
resolveContext: resolveSearchDataplaneContext,
|
|
41
|
+
getWorkRoles,
|
|
42
|
+
getWorkSkills,
|
|
43
|
+
searchWork,
|
|
44
|
+
prompt: (qs) => require('inquirer').prompt(qs),
|
|
45
|
+
logger,
|
|
46
|
+
isTty: () => Boolean(process.stdin && process.stdin.isTTY),
|
|
47
|
+
fsApi: fs,
|
|
48
|
+
...overrides
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {Object} options
|
|
54
|
+
* @param {Function} resolveContext
|
|
55
|
+
* @returns {Promise<Object>}
|
|
56
|
+
*/
|
|
57
|
+
async function resolveContextOrThrow(options, resolveContext) {
|
|
58
|
+
try {
|
|
59
|
+
return await resolveContext(options);
|
|
60
|
+
} catch (err) {
|
|
61
|
+
const message = err.message || String(err);
|
|
62
|
+
if (/login|auth|token|controller url/i.test(message)) {
|
|
63
|
+
throw authRequiredError(message);
|
|
64
|
+
}
|
|
65
|
+
throw new SearchCliError(message);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @param {Object} options
|
|
71
|
+
*/
|
|
72
|
+
function assertScriptSearchFlags(options) {
|
|
73
|
+
const missing = [];
|
|
74
|
+
if (!roleRefFromOptions(options)) missing.push('--role');
|
|
75
|
+
if (!resourceTypeFromOptions(options)) missing.push('--resource-type');
|
|
76
|
+
if (missing.length) {
|
|
77
|
+
throw missingFlagsError(missing);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param {Object} res
|
|
83
|
+
* @param {string} fallback
|
|
84
|
+
* @returns {Object}
|
|
85
|
+
*/
|
|
86
|
+
function payloadOrThrow(res, fallback) {
|
|
87
|
+
if (res && Number(res.status) === 200) {
|
|
88
|
+
const payload = skillsEnvelope(res.payload);
|
|
89
|
+
return payload && typeof payload === 'object' ? payload : {};
|
|
90
|
+
}
|
|
91
|
+
const text = String((res && res.errorText) || '').trim() || fallback;
|
|
92
|
+
throw new SearchCliError(text);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @param {Object} options
|
|
97
|
+
* @param {Object} ctx
|
|
98
|
+
* @param {Object} deps
|
|
99
|
+
* @returns {Promise<string>}
|
|
100
|
+
*/
|
|
101
|
+
async function resolveRoleRef(options, ctx, deps) {
|
|
102
|
+
const existing = roleRefFromOptions(options);
|
|
103
|
+
if (existing) {
|
|
104
|
+
return existing;
|
|
105
|
+
}
|
|
106
|
+
return promptRoleAssistant(ctx, deps);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {string} explicitType
|
|
111
|
+
* @param {string[]} typeKeys
|
|
112
|
+
* @param {Object} typeMap
|
|
113
|
+
* @param {boolean} interactive
|
|
114
|
+
* @param {Object} deps
|
|
115
|
+
* @returns {Promise<string>}
|
|
116
|
+
*/
|
|
117
|
+
async function resolveResourceType(explicitType, typeKeys, typeMap, interactive, deps) {
|
|
118
|
+
if (!typeKeys.length) {
|
|
119
|
+
throw new SearchCliError('No searchable resource types for this Role Assistant.');
|
|
120
|
+
}
|
|
121
|
+
if (explicitType) {
|
|
122
|
+
assertTypePublished(explicitType, typeMap);
|
|
123
|
+
return explicitType;
|
|
124
|
+
}
|
|
125
|
+
if (!interactive) {
|
|
126
|
+
throw missingFlagsError(['--resource-type']);
|
|
127
|
+
}
|
|
128
|
+
return promptResourceType(typeKeys, deps);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @param {string} explicitOp
|
|
133
|
+
* @param {Object} spec
|
|
134
|
+
* @param {boolean} interactive
|
|
135
|
+
* @param {Object} deps
|
|
136
|
+
* @returns {Promise<string>}
|
|
137
|
+
*/
|
|
138
|
+
async function resolveOperation(explicitOp, spec, interactive, deps) {
|
|
139
|
+
if (explicitOp) {
|
|
140
|
+
assertOperationPublished(explicitOp, spec);
|
|
141
|
+
return explicitOp;
|
|
142
|
+
}
|
|
143
|
+
if (isOperationRequired(spec) && !interactive) {
|
|
144
|
+
throw new SearchCliError(
|
|
145
|
+
'Operation is required for this resource type. Pass --operation.'
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
if (!interactive) {
|
|
149
|
+
return '';
|
|
150
|
+
}
|
|
151
|
+
return promptOperation(spec, deps);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @param {Object} body
|
|
156
|
+
* @param {Object} skillsPayload
|
|
157
|
+
* @param {Object} options
|
|
158
|
+
* @param {Object} deps
|
|
159
|
+
* @returns {Promise<Object>}
|
|
160
|
+
*/
|
|
161
|
+
async function fillTypeAndOperation(body, skillsPayload, options, deps) {
|
|
162
|
+
const typeMap = resourceTypesMap(skillsPayload);
|
|
163
|
+
const typeKeys = Object.keys(typeMap);
|
|
164
|
+
const interactive = isInteractive(options, deps.isTty);
|
|
165
|
+
const resourceType = await resolveResourceType(
|
|
166
|
+
body.resourceType || '',
|
|
167
|
+
typeKeys,
|
|
168
|
+
typeMap,
|
|
169
|
+
interactive,
|
|
170
|
+
deps
|
|
171
|
+
);
|
|
172
|
+
body.resourceType = resourceType;
|
|
173
|
+
const spec = typeSpec(typeMap, resourceType);
|
|
174
|
+
const operation = await resolveOperation(body.operation || '', spec, interactive, deps);
|
|
175
|
+
if (operation) {
|
|
176
|
+
body.operation = operation;
|
|
177
|
+
} else {
|
|
178
|
+
delete body.operation;
|
|
179
|
+
}
|
|
180
|
+
if (isOperationRequired(spec) && !body.operation) {
|
|
181
|
+
throw new SearchCliError(
|
|
182
|
+
'Operation is required for this resource type. Pass --operation.'
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
return body;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @param {Object} options
|
|
190
|
+
* @param {Object} [depOverrides]
|
|
191
|
+
* @returns {Promise<number>}
|
|
192
|
+
*/
|
|
193
|
+
async function runSearch(options, depOverrides) {
|
|
194
|
+
const deps = defaultDeps(depOverrides);
|
|
195
|
+
const body = buildSearchBody(options, deps.fsApi);
|
|
196
|
+
const interactive = isInteractive(options, deps.isTty);
|
|
197
|
+
if (!interactive) {
|
|
198
|
+
assertScriptSearchFlags(options);
|
|
199
|
+
}
|
|
200
|
+
const ctx = await resolveContextOrThrow(options, deps.resolveContext);
|
|
201
|
+
if (!body.roleRef) {
|
|
202
|
+
body.roleRef = await resolveRoleRef(options, ctx, deps);
|
|
203
|
+
}
|
|
204
|
+
const skillsRes = await deps.getWorkSkills(ctx.dataplaneUrl, ctx.authConfig, body.roleRef);
|
|
205
|
+
const skillsPayload = payloadOrThrow(skillsRes, 'Unable to load search skills.');
|
|
206
|
+
await fillTypeAndOperation(body, skillsPayload, options, deps);
|
|
207
|
+
const searchRes = await deps.searchWork(ctx.dataplaneUrl, ctx.authConfig, body);
|
|
208
|
+
const payload = payloadOrThrow(searchRes, 'Search request failed.');
|
|
209
|
+
emitSearchSuccess(options, body, payload, deps.logger, deps.fsApi);
|
|
210
|
+
return 0;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @param {Object} options
|
|
215
|
+
* @param {Object} [depOverrides]
|
|
216
|
+
* @returns {Promise<number>}
|
|
217
|
+
*/
|
|
218
|
+
async function runSearchSkills(options, depOverrides) {
|
|
219
|
+
const deps = defaultDeps(depOverrides);
|
|
220
|
+
const interactive = isInteractive(options, deps.isTty);
|
|
221
|
+
if (!interactive && !roleRefFromOptions(options)) {
|
|
222
|
+
throw missingFlagsError(['--role']);
|
|
223
|
+
}
|
|
224
|
+
const ctx = await resolveContextOrThrow(options, deps.resolveContext);
|
|
225
|
+
const roleRef = await resolveRoleRef(options, ctx, deps);
|
|
226
|
+
const skillsRes = await deps.getWorkSkills(ctx.dataplaneUrl, ctx.authConfig, roleRef);
|
|
227
|
+
const payload = payloadOrThrow(skillsRes, 'Unable to load search skills.');
|
|
228
|
+
if (!payload.roleRef) {
|
|
229
|
+
payload.roleRef = roleRef;
|
|
230
|
+
}
|
|
231
|
+
emitSkillsSuccess(options, payload, deps.logger, deps.fsApi);
|
|
232
|
+
return 0;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
module.exports = {
|
|
236
|
+
defaultDeps,
|
|
237
|
+
runSearch,
|
|
238
|
+
runSearchSkills,
|
|
239
|
+
fillTypeAndOperation,
|
|
240
|
+
resolveRoleRef
|
|
241
|
+
};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YAML-free copies of work.skills helpers (do not import the test runner).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Resource type / operation keys from a skills payload
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { SearchCliError } = require('./search-errors');
|
|
12
|
+
|
|
13
|
+
/** Table retrieve keys stamped by the search grammar (list/search page, get one). */
|
|
14
|
+
const RETRIEVE_TABLE_KEYS = new Set(['list', 'get', 'search']);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {*} item
|
|
18
|
+
* @returns {string}
|
|
19
|
+
*/
|
|
20
|
+
function operationKeyFromItem(item) {
|
|
21
|
+
if (typeof item === 'string' && item.trim()) {
|
|
22
|
+
return item.trim();
|
|
23
|
+
}
|
|
24
|
+
if (item && typeof item === 'object') {
|
|
25
|
+
return String(item.key || '').trim();
|
|
26
|
+
}
|
|
27
|
+
return '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {*} item
|
|
32
|
+
* @returns {boolean}
|
|
33
|
+
*/
|
|
34
|
+
function hasResultMode(item) {
|
|
35
|
+
return Boolean(item && typeof item === 'object' && String(item.resultMode || '').trim());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Retrieve/analyze only. Write-shaped keys stay off search.
|
|
40
|
+
* Keep table retrieve keys (list/get/search) and named views (source viewpoint).
|
|
41
|
+
*
|
|
42
|
+
* @param {*} item
|
|
43
|
+
* @param {boolean} grammarPresent
|
|
44
|
+
* @param {boolean} tableRetrievePresent
|
|
45
|
+
* @returns {boolean}
|
|
46
|
+
*/
|
|
47
|
+
function isRetrieveOperation(item, grammarPresent, tableRetrievePresent) {
|
|
48
|
+
const key = operationKeyFromItem(item);
|
|
49
|
+
if (!key) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if (RETRIEVE_TABLE_KEYS.has(key)) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (typeof item === 'string') {
|
|
56
|
+
return !tableRetrievePresent;
|
|
57
|
+
}
|
|
58
|
+
const source = String((item && item.source) || '')
|
|
59
|
+
.trim()
|
|
60
|
+
.toLowerCase();
|
|
61
|
+
if (source === 'viewpoint') {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
if (!source && !grammarPresent && !tableRetrievePresent) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {Object|null|undefined} spec
|
|
72
|
+
* @returns {*[]}
|
|
73
|
+
*/
|
|
74
|
+
function operationItems(spec) {
|
|
75
|
+
return Array.isArray(spec && spec.operations) ? spec.operations : [];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {Object|null|undefined} spec
|
|
80
|
+
* @returns {string[]}
|
|
81
|
+
*/
|
|
82
|
+
function operationKeys(spec) {
|
|
83
|
+
const raw = operationItems(spec);
|
|
84
|
+
const grammarPresent = raw.some(hasResultMode);
|
|
85
|
+
const tableRetrievePresent = raw.some((item) =>
|
|
86
|
+
RETRIEVE_TABLE_KEYS.has(operationKeyFromItem(item))
|
|
87
|
+
);
|
|
88
|
+
const keys = [];
|
|
89
|
+
for (const item of raw) {
|
|
90
|
+
if (!isRetrieveOperation(item, grammarPresent, tableRetrievePresent)) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const key = operationKeyFromItem(item);
|
|
94
|
+
if (key) {
|
|
95
|
+
keys.push(key);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return keys;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @param {Object|null|undefined} spec
|
|
103
|
+
* @returns {string[]}
|
|
104
|
+
*/
|
|
105
|
+
function allOperationKeys(spec) {
|
|
106
|
+
return operationItems(spec).map(operationKeyFromItem).filter(Boolean);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* work.skills is an object. MCP execute may wrap it as a one-element array.
|
|
111
|
+
* @param {*} skillsPayload
|
|
112
|
+
* @returns {Object|null}
|
|
113
|
+
*/
|
|
114
|
+
function skillsEnvelope(skillsPayload) {
|
|
115
|
+
let cur = skillsPayload;
|
|
116
|
+
if (Array.isArray(cur) && cur.length === 1 && cur[0] && typeof cur[0] === 'object') {
|
|
117
|
+
cur = cur[0];
|
|
118
|
+
}
|
|
119
|
+
if (!cur || typeof cur !== 'object' || Array.isArray(cur)) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
if (cur.search && typeof cur.search === 'object') {
|
|
123
|
+
return cur;
|
|
124
|
+
}
|
|
125
|
+
if (cur.data && typeof cur.data === 'object' && !Array.isArray(cur.data) && cur.data.search) {
|
|
126
|
+
return cur.data;
|
|
127
|
+
}
|
|
128
|
+
return cur;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @param {Object|null|undefined} skillsPayload
|
|
133
|
+
* @returns {Object}
|
|
134
|
+
*/
|
|
135
|
+
function resourceTypesMap(skillsPayload) {
|
|
136
|
+
const root = skillsEnvelope(skillsPayload);
|
|
137
|
+
const rts = root && root.search && root.search.resourceTypes;
|
|
138
|
+
return rts && typeof rts === 'object' && !Array.isArray(rts) ? rts : {};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @param {Object} typeMap
|
|
143
|
+
* @param {string} resourceType
|
|
144
|
+
* @returns {Object}
|
|
145
|
+
*/
|
|
146
|
+
function typeSpec(typeMap, resourceType) {
|
|
147
|
+
const spec = typeMap && typeMap[resourceType];
|
|
148
|
+
return spec && typeof spec === 'object' ? spec : {};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* @param {Object} spec
|
|
153
|
+
* @returns {boolean}
|
|
154
|
+
*/
|
|
155
|
+
function isOperationRequired(spec) {
|
|
156
|
+
return spec && spec.operationRequired === true;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @param {string} resourceType
|
|
161
|
+
* @param {Object} typeMap
|
|
162
|
+
*/
|
|
163
|
+
function assertTypePublished(resourceType, typeMap) {
|
|
164
|
+
if (!Object.prototype.hasOwnProperty.call(typeMap, resourceType)) {
|
|
165
|
+
throw new SearchCliError(
|
|
166
|
+
`Resource type "${resourceType}" is not published for this Role Assistant.`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @param {string} operation
|
|
173
|
+
* @param {Object} spec
|
|
174
|
+
*/
|
|
175
|
+
function assertOperationPublished(operation, spec) {
|
|
176
|
+
const keys = operationKeys(spec);
|
|
177
|
+
if (keys.includes(operation)) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (allOperationKeys(spec).includes(operation)) {
|
|
181
|
+
throw new SearchCliError(
|
|
182
|
+
`Operation "${operation}" is not a retrieve operation for this resource type.`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
throw new SearchCliError(
|
|
186
|
+
`Operation "${operation}" is not published for this resource type.`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
module.exports = {
|
|
191
|
+
operationKeys,
|
|
192
|
+
skillsEnvelope,
|
|
193
|
+
resourceTypesMap,
|
|
194
|
+
typeSpec,
|
|
195
|
+
isOperationRequired,
|
|
196
|
+
assertTypePublished,
|
|
197
|
+
assertOperationPublished
|
|
198
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connected System credential line for `aifabrix show` (usage slots + online/offline).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview TTY formatter for authentications[] / legacy authentication
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const { getAuthMethodFromAuthentication } = require('./authentication-shape');
|
|
13
|
+
|
|
14
|
+
/** Same labels as the dataplane Connected System authentication tab. */
|
|
15
|
+
const AUTHENTICATION_USAGE_LABELS = Object.freeze({
|
|
16
|
+
api: 'API calls',
|
|
17
|
+
webhookInbound: 'Webhook inbound',
|
|
18
|
+
syncExecution: 'Sync execution',
|
|
19
|
+
messageInbound: 'Message inbound',
|
|
20
|
+
messageOutbound: 'Message outbound',
|
|
21
|
+
callback: 'Callback',
|
|
22
|
+
provisioning: 'Provisioning'
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {string} method
|
|
27
|
+
* @param {string} glyph
|
|
28
|
+
* @returns {string}
|
|
29
|
+
*/
|
|
30
|
+
function chalkGlyph(method, glyph) {
|
|
31
|
+
const fn = chalk[method];
|
|
32
|
+
return typeof fn === 'function' ? fn(glyph) : glyph;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {string|null|undefined} status
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
function formatOnlineOfflineIcon(status) {
|
|
40
|
+
const raw = String(status || 'offline').trim().toLowerCase();
|
|
41
|
+
if (raw === 'online') return chalkGlyph('green', '✔');
|
|
42
|
+
if (raw === 'partially') return chalkGlyph('yellow', '⚠');
|
|
43
|
+
return chalkGlyph('red', '✖');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {unknown} value
|
|
48
|
+
* @returns {Object|null}
|
|
49
|
+
*/
|
|
50
|
+
function asObject(value) {
|
|
51
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {Object} slot
|
|
56
|
+
* @returns {string}
|
|
57
|
+
*/
|
|
58
|
+
function formatSlotType(slot) {
|
|
59
|
+
const authType = String(slot.authType || '').trim().toLowerCase();
|
|
60
|
+
if (authType === 'system' || authType === 'none') return authType;
|
|
61
|
+
if (authType === 'apiprovider') return 'apiProvider';
|
|
62
|
+
const method = getAuthMethodFromAuthentication(slot);
|
|
63
|
+
if (method) return method;
|
|
64
|
+
const nested = asObject(slot.credential);
|
|
65
|
+
const nestedMethod = nested && typeof nested.method === 'string' ? nested.method.trim() : '';
|
|
66
|
+
return nestedMethod || authType || '—';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @param {Object} slot
|
|
71
|
+
* @param {string|null|undefined} systemStatus
|
|
72
|
+
* @returns {string}
|
|
73
|
+
*/
|
|
74
|
+
function slotStatus(slot, systemStatus) {
|
|
75
|
+
const authType = String(slot.authType || '').trim().toLowerCase();
|
|
76
|
+
if (authType === 'system' || authType === 'none') return 'online';
|
|
77
|
+
return systemStatus || 'offline';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @param {Object} slot
|
|
82
|
+
* @param {string|null|undefined} systemStatus
|
|
83
|
+
* @param {boolean} includeUsage
|
|
84
|
+
* @returns {string}
|
|
85
|
+
*/
|
|
86
|
+
function formatOneSlot(slot, systemStatus, includeUsage) {
|
|
87
|
+
const type = formatSlotType(slot);
|
|
88
|
+
const icon = formatOnlineOfflineIcon(slotStatus(slot, systemStatus));
|
|
89
|
+
if (!includeUsage) return `${type} ${icon}`;
|
|
90
|
+
const usage = String(slot.usage || 'api').trim() || 'api';
|
|
91
|
+
const label = AUTHENTICATION_USAGE_LABELS[usage] || usage;
|
|
92
|
+
return `${label}: ${type} ${icon}`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @param {unknown} entry
|
|
97
|
+
* @returns {Object|null}
|
|
98
|
+
*/
|
|
99
|
+
function normalizeSlot(entry) {
|
|
100
|
+
const obj = asObject(entry);
|
|
101
|
+
if (!obj) return null;
|
|
102
|
+
const key = typeof obj.key === 'string' && obj.key.trim() ? obj.key.trim() : 'default';
|
|
103
|
+
const usage = typeof obj.usage === 'string' && obj.usage.trim() ? obj.usage.trim() : 'api';
|
|
104
|
+
return { ...obj, key, usage };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @param {Object|null|undefined} config
|
|
109
|
+
* @param {Object|null|undefined} system
|
|
110
|
+
* @returns {Object[]}
|
|
111
|
+
*/
|
|
112
|
+
function resolveAuthenticationSlots(config, system) {
|
|
113
|
+
const cfg = asObject(config) || {};
|
|
114
|
+
const sys = asObject(system) || {};
|
|
115
|
+
const fromCfg = Array.isArray(cfg.authentications) && cfg.authentications.length > 0
|
|
116
|
+
? cfg.authentications
|
|
117
|
+
: null;
|
|
118
|
+
const fromSys = Array.isArray(sys.authentications) && sys.authentications.length > 0
|
|
119
|
+
? sys.authentications
|
|
120
|
+
: null;
|
|
121
|
+
const rawSlots = fromCfg || fromSys;
|
|
122
|
+
if (rawSlots) return rawSlots.map(normalizeSlot).filter(Boolean);
|
|
123
|
+
const legacy = asObject(cfg.authentication) || asObject(sys.authentication);
|
|
124
|
+
if (!legacy) return [];
|
|
125
|
+
return [normalizeSlot({ ...legacy, key: 'default', usage: 'api' })];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* One slot: `oauth2 ✔`. Several: `API calls: oauth2 ✔, Webhook inbound: hmac ✔`.
|
|
130
|
+
* @param {Object} ext
|
|
131
|
+
* @returns {string}
|
|
132
|
+
*/
|
|
133
|
+
function formatCredentialShowLine(ext) {
|
|
134
|
+
if (!ext || typeof ext !== 'object') return '—';
|
|
135
|
+
const slots = Array.isArray(ext.authenticationSlots) ? ext.authenticationSlots : [];
|
|
136
|
+
const status = ext.authenticationStatus;
|
|
137
|
+
if (slots.length === 1) return formatOneSlot(slots[0], status, false);
|
|
138
|
+
if (slots.length > 1) {
|
|
139
|
+
return slots.map((slot) => formatOneSlot(slot, status, true)).join(', ');
|
|
140
|
+
}
|
|
141
|
+
const method = typeof ext.credentialMethod === 'string' ? ext.credentialMethod.trim() : '';
|
|
142
|
+
if (method && method.toLowerCase() !== 'unknown') {
|
|
143
|
+
return `${method} ${formatOnlineOfflineIcon(status)}`;
|
|
144
|
+
}
|
|
145
|
+
return '—';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
module.exports = {
|
|
149
|
+
AUTHENTICATION_USAGE_LABELS,
|
|
150
|
+
resolveAuthenticationSlots,
|
|
151
|
+
formatCredentialShowLine,
|
|
152
|
+
formatOnlineOfflineIcon
|
|
153
|
+
};
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
const chalk = require('chalk');
|
|
11
|
+
const { formatCredentialShowLine } = require('./authentication-slot-show');
|
|
11
12
|
|
|
12
13
|
/** @type {{ verified: string, pending: string, failed: string, expired: string }} */
|
|
13
14
|
const STATUS_ICONS = {
|
|
@@ -74,10 +75,51 @@ function formatCredentialWithStatus(credential) {
|
|
|
74
75
|
return { key, name, statusFormatted, statusLabel };
|
|
75
76
|
}
|
|
76
77
|
|
|
78
|
+
/**
|
|
79
|
+
* @param {unknown[]} values
|
|
80
|
+
* @returns {string|null}
|
|
81
|
+
*/
|
|
82
|
+
function firstNonEmptyScalar(values) {
|
|
83
|
+
for (const value of values) {
|
|
84
|
+
if (typeof value === 'number') return String(value);
|
|
85
|
+
if (typeof value === 'string' && value.trim()) return value.trim();
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Identity from a dataplane credential id or ForeignKeyReference. Never `[object Object]`.
|
|
92
|
+
* @param {unknown} value
|
|
93
|
+
* @returns {string|null}
|
|
94
|
+
*/
|
|
95
|
+
function formatCredentialIdentity(value) {
|
|
96
|
+
if (value === null || value === undefined || value === '') return null;
|
|
97
|
+
if (typeof value !== 'object') return String(value);
|
|
98
|
+
return firstNonEmptyScalar([
|
|
99
|
+
value.name,
|
|
100
|
+
value.displayName,
|
|
101
|
+
value.key,
|
|
102
|
+
value.id,
|
|
103
|
+
value.credentialKey,
|
|
104
|
+
value.credentialId
|
|
105
|
+
]);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Scalar credential id/key for show output. Objects must not print as [object Object].
|
|
110
|
+
* @param {unknown} value
|
|
111
|
+
* @returns {string}
|
|
112
|
+
*/
|
|
113
|
+
function formatCredentialIdValue(value) {
|
|
114
|
+
return formatCredentialIdentity(value) || '—';
|
|
115
|
+
}
|
|
116
|
+
|
|
77
117
|
module.exports = {
|
|
78
118
|
STATUS_ICONS,
|
|
79
119
|
STATUS_LABELS,
|
|
80
120
|
STATUS_CHALK,
|
|
81
121
|
formatCredentialStatus,
|
|
82
|
-
formatCredentialWithStatus
|
|
122
|
+
formatCredentialWithStatus,
|
|
123
|
+
formatCredentialIdValue,
|
|
124
|
+
formatCredentialShowLine
|
|
83
125
|
};
|
|
@@ -75,7 +75,11 @@ function logUploadReadinessSummaryCompact(ctx) {
|
|
|
75
75
|
const genMcp = publication?.generateMcpContract !== false;
|
|
76
76
|
const tierA = summarizeDatasourceTiersA(publication?.datasources || [], genMcp);
|
|
77
77
|
const systemCfg = manifest?.system || {};
|
|
78
|
-
const statusLabel = resolveConnectedSystemStatus({
|
|
78
|
+
const statusLabel = resolveConnectedSystemStatus({
|
|
79
|
+
command: 'upload',
|
|
80
|
+
publication,
|
|
81
|
+
systemFromDataplane: ctx.systemFromDataplane
|
|
82
|
+
});
|
|
79
83
|
|
|
80
84
|
logCompactHeader({ command: 'upload', systemKey, environment, dataplaneUrl });
|
|
81
85
|
if (forcePublish) {
|